agenta 0.52.6__py3-none-any.whl → 0.63.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. agenta/__init__.py +12 -3
  2. agenta/client/__init__.py +4 -4
  3. agenta/client/backend/__init__.py +4 -4
  4. agenta/client/backend/api_keys/client.py +2 -2
  5. agenta/client/backend/billing/client.py +2 -2
  6. agenta/client/backend/billing/raw_client.py +2 -2
  7. agenta/client/backend/client.py +56 -48
  8. agenta/client/backend/core/client_wrapper.py +2 -2
  9. agenta/client/backend/core/file.py +3 -1
  10. agenta/client/backend/core/http_client.py +3 -3
  11. agenta/client/backend/core/pydantic_utilities.py +13 -3
  12. agenta/client/backend/human_evaluations/client.py +2 -2
  13. agenta/client/backend/human_evaluations/raw_client.py +2 -2
  14. agenta/client/backend/organization/client.py +46 -34
  15. agenta/client/backend/organization/raw_client.py +32 -26
  16. agenta/client/backend/raw_client.py +26 -26
  17. agenta/client/backend/testsets/client.py +18 -18
  18. agenta/client/backend/testsets/raw_client.py +30 -30
  19. agenta/client/backend/types/__init__.py +4 -4
  20. agenta/client/backend/types/account_request.py +3 -1
  21. agenta/client/backend/types/account_response.py +3 -1
  22. agenta/client/backend/types/agenta_node_dto.py +3 -1
  23. agenta/client/backend/types/agenta_nodes_response.py +3 -1
  24. agenta/client/backend/types/agenta_root_dto.py +3 -1
  25. agenta/client/backend/types/agenta_roots_response.py +3 -1
  26. agenta/client/backend/types/agenta_tree_dto.py +3 -1
  27. agenta/client/backend/types/agenta_trees_response.py +3 -1
  28. agenta/client/backend/types/aggregated_result.py +3 -1
  29. agenta/client/backend/types/analytics_response.py +3 -1
  30. agenta/client/backend/types/annotation.py +6 -4
  31. agenta/client/backend/types/annotation_create.py +3 -1
  32. agenta/client/backend/types/annotation_edit.py +3 -1
  33. agenta/client/backend/types/annotation_link.py +3 -1
  34. agenta/client/backend/types/annotation_link_response.py +3 -1
  35. agenta/client/backend/types/annotation_query.py +3 -1
  36. agenta/client/backend/types/annotation_query_request.py +3 -1
  37. agenta/client/backend/types/annotation_reference.py +3 -1
  38. agenta/client/backend/types/annotation_references.py +3 -1
  39. agenta/client/backend/types/annotation_response.py +3 -1
  40. agenta/client/backend/types/annotations_response.py +3 -1
  41. agenta/client/backend/types/app.py +3 -1
  42. agenta/client/backend/types/app_variant_response.py +3 -1
  43. agenta/client/backend/types/app_variant_revision.py +3 -1
  44. agenta/client/backend/types/artifact.py +6 -4
  45. agenta/client/backend/types/base_output.py +3 -1
  46. agenta/client/backend/types/body_fetch_workflow_revision.py +3 -1
  47. agenta/client/backend/types/body_import_testset.py +3 -1
  48. agenta/client/backend/types/bucket_dto.py +3 -1
  49. agenta/client/backend/types/collect_status_response.py +3 -1
  50. agenta/client/backend/types/config_db.py +3 -1
  51. agenta/client/backend/types/config_dto.py +3 -1
  52. agenta/client/backend/types/config_response_model.py +3 -1
  53. agenta/client/backend/types/correct_answer.py +3 -1
  54. agenta/client/backend/types/create_app_output.py +3 -1
  55. agenta/client/backend/types/custom_model_settings_dto.py +3 -1
  56. agenta/client/backend/types/custom_provider_dto.py +3 -1
  57. agenta/client/backend/types/custom_provider_kind.py +1 -1
  58. agenta/client/backend/types/custom_provider_settings_dto.py +3 -1
  59. agenta/client/backend/types/delete_evaluation.py +3 -1
  60. agenta/client/backend/types/environment_output.py +3 -1
  61. agenta/client/backend/types/environment_output_extended.py +3 -1
  62. agenta/client/backend/types/environment_revision.py +3 -1
  63. agenta/client/backend/types/error.py +3 -1
  64. agenta/client/backend/types/evaluation.py +3 -1
  65. agenta/client/backend/types/evaluation_scenario.py +3 -1
  66. agenta/client/backend/types/evaluation_scenario_input.py +3 -1
  67. agenta/client/backend/types/evaluation_scenario_output.py +3 -1
  68. agenta/client/backend/types/evaluation_scenario_result.py +3 -1
  69. agenta/client/backend/types/evaluator.py +6 -4
  70. agenta/client/backend/types/evaluator_config.py +6 -4
  71. agenta/client/backend/types/evaluator_flags.py +3 -1
  72. agenta/client/backend/types/evaluator_mapping_output_interface.py +3 -1
  73. agenta/client/backend/types/evaluator_output_interface.py +3 -1
  74. agenta/client/backend/types/evaluator_query.py +3 -1
  75. agenta/client/backend/types/evaluator_query_request.py +3 -1
  76. agenta/client/backend/types/evaluator_request.py +3 -1
  77. agenta/client/backend/types/evaluator_response.py +3 -1
  78. agenta/client/backend/types/evaluators_response.py +3 -1
  79. agenta/client/backend/types/exception_dto.py +3 -1
  80. agenta/client/backend/types/extended_o_tel_tracing_response.py +3 -1
  81. agenta/client/backend/types/get_config_response.py +3 -1
  82. agenta/client/backend/types/header.py +3 -1
  83. agenta/client/backend/types/http_validation_error.py +3 -1
  84. agenta/client/backend/types/human_evaluation.py +3 -1
  85. agenta/client/backend/types/human_evaluation_scenario.py +3 -1
  86. agenta/client/backend/types/human_evaluation_scenario_input.py +3 -1
  87. agenta/client/backend/types/human_evaluation_scenario_output.py +3 -1
  88. agenta/client/backend/types/invite_request.py +3 -1
  89. agenta/client/backend/types/legacy_analytics_response.py +3 -1
  90. agenta/client/backend/types/legacy_data_point.py +3 -1
  91. agenta/client/backend/types/legacy_evaluator.py +3 -1
  92. agenta/client/backend/types/legacy_scope_request.py +3 -1
  93. agenta/client/backend/types/legacy_scopes_response.py +3 -1
  94. agenta/client/backend/types/legacy_subscription_request.py +3 -1
  95. agenta/client/backend/types/legacy_user_request.py +3 -1
  96. agenta/client/backend/types/legacy_user_response.py +3 -1
  97. agenta/client/backend/types/lifecycle_dto.py +3 -1
  98. agenta/client/backend/types/link_dto.py +3 -1
  99. agenta/client/backend/types/list_api_keys_response.py +3 -1
  100. agenta/client/backend/types/llm_run_rate_limit.py +3 -1
  101. agenta/client/backend/types/meta_request.py +3 -1
  102. agenta/client/backend/types/metrics_dto.py +3 -1
  103. agenta/client/backend/types/new_testset.py +3 -1
  104. agenta/client/backend/types/node_dto.py +3 -1
  105. agenta/client/backend/types/o_tel_context_dto.py +3 -1
  106. agenta/client/backend/types/o_tel_event.py +6 -4
  107. agenta/client/backend/types/o_tel_event_dto.py +3 -1
  108. agenta/client/backend/types/o_tel_extra_dto.py +3 -1
  109. agenta/client/backend/types/o_tel_flat_span.py +6 -4
  110. agenta/client/backend/types/o_tel_link.py +6 -4
  111. agenta/client/backend/types/o_tel_link_dto.py +3 -1
  112. agenta/client/backend/types/o_tel_links_response.py +3 -1
  113. agenta/client/backend/types/o_tel_span.py +1 -1
  114. agenta/client/backend/types/o_tel_span_dto.py +3 -1
  115. agenta/client/backend/types/o_tel_spans_tree.py +3 -1
  116. agenta/client/backend/types/o_tel_tracing_data_response.py +3 -1
  117. agenta/client/backend/types/o_tel_tracing_request.py +3 -1
  118. agenta/client/backend/types/o_tel_tracing_response.py +3 -1
  119. agenta/client/backend/types/organization.py +3 -1
  120. agenta/client/backend/types/organization_details.py +3 -1
  121. agenta/client/backend/types/organization_membership_request.py +3 -1
  122. agenta/client/backend/types/organization_output.py +3 -1
  123. agenta/client/backend/types/organization_request.py +3 -1
  124. agenta/client/backend/types/parent_dto.py +3 -1
  125. agenta/client/backend/types/project_membership_request.py +3 -1
  126. agenta/client/backend/types/project_request.py +3 -1
  127. agenta/client/backend/types/project_scope.py +3 -1
  128. agenta/client/backend/types/projects_response.py +3 -1
  129. agenta/client/backend/types/reference.py +6 -4
  130. agenta/client/backend/types/reference_dto.py +3 -1
  131. agenta/client/backend/types/reference_request_model.py +3 -1
  132. agenta/client/backend/types/result.py +3 -1
  133. agenta/client/backend/types/root_dto.py +3 -1
  134. agenta/client/backend/types/scopes_response_model.py +3 -1
  135. agenta/client/backend/types/secret_dto.py +3 -1
  136. agenta/client/backend/types/secret_response_dto.py +3 -1
  137. agenta/client/backend/types/simple_evaluation_output.py +3 -1
  138. agenta/client/backend/types/span_dto.py +6 -4
  139. agenta/client/backend/types/standard_provider_dto.py +3 -1
  140. agenta/client/backend/types/standard_provider_settings_dto.py +3 -1
  141. agenta/client/backend/types/status_dto.py +3 -1
  142. agenta/client/backend/types/tags_request.py +3 -1
  143. agenta/client/backend/types/testcase_response.py +6 -4
  144. agenta/client/backend/types/testset.py +6 -4
  145. agenta/client/backend/types/{test_set_output_response.py → testset_output_response.py} +4 -2
  146. agenta/client/backend/types/testset_request.py +3 -1
  147. agenta/client/backend/types/testset_response.py +3 -1
  148. agenta/client/backend/types/{test_set_simple_response.py → testset_simple_response.py} +4 -2
  149. agenta/client/backend/types/testsets_response.py +3 -1
  150. agenta/client/backend/types/time_dto.py +3 -1
  151. agenta/client/backend/types/tree_dto.py +3 -1
  152. agenta/client/backend/types/update_app_output.py +3 -1
  153. agenta/client/backend/types/user_request.py +3 -1
  154. agenta/client/backend/types/validation_error.py +3 -1
  155. agenta/client/backend/types/workflow_artifact.py +6 -4
  156. agenta/client/backend/types/workflow_data.py +3 -1
  157. agenta/client/backend/types/workflow_flags.py +3 -1
  158. agenta/client/backend/types/workflow_request.py +3 -1
  159. agenta/client/backend/types/workflow_response.py +3 -1
  160. agenta/client/backend/types/workflow_revision.py +6 -4
  161. agenta/client/backend/types/workflow_revision_request.py +3 -1
  162. agenta/client/backend/types/workflow_revision_response.py +3 -1
  163. agenta/client/backend/types/workflow_revisions_response.py +3 -1
  164. agenta/client/backend/types/workflow_variant.py +6 -4
  165. agenta/client/backend/types/workflow_variant_request.py +3 -1
  166. agenta/client/backend/types/workflow_variant_response.py +3 -1
  167. agenta/client/backend/types/workflow_variants_response.py +3 -1
  168. agenta/client/backend/types/workflows_response.py +3 -1
  169. agenta/client/backend/types/workspace.py +3 -1
  170. agenta/client/backend/types/workspace_member_response.py +3 -1
  171. agenta/client/backend/types/workspace_membership_request.py +3 -1
  172. agenta/client/backend/types/workspace_permission.py +3 -1
  173. agenta/client/backend/types/workspace_request.py +3 -1
  174. agenta/client/backend/types/workspace_response.py +3 -1
  175. agenta/client/backend/vault/raw_client.py +4 -4
  176. agenta/client/backend/workspace/client.py +2 -2
  177. agenta/client/client.py +102 -88
  178. agenta/sdk/__init__.py +52 -3
  179. agenta/sdk/agenta_init.py +43 -16
  180. agenta/sdk/assets.py +23 -15
  181. agenta/sdk/context/serving.py +20 -8
  182. agenta/sdk/context/tracing.py +40 -22
  183. agenta/sdk/contexts/__init__.py +0 -0
  184. agenta/sdk/contexts/routing.py +38 -0
  185. agenta/sdk/contexts/running.py +57 -0
  186. agenta/sdk/contexts/tracing.py +86 -0
  187. agenta/sdk/decorators/__init__.py +1 -0
  188. agenta/sdk/decorators/routing.py +284 -0
  189. agenta/sdk/decorators/running.py +692 -98
  190. agenta/sdk/decorators/serving.py +20 -21
  191. agenta/sdk/decorators/tracing.py +176 -131
  192. agenta/sdk/engines/__init__.py +0 -0
  193. agenta/sdk/engines/running/__init__.py +0 -0
  194. agenta/sdk/engines/running/utils.py +17 -0
  195. agenta/sdk/engines/tracing/__init__.py +1 -0
  196. agenta/sdk/engines/tracing/attributes.py +185 -0
  197. agenta/sdk/engines/tracing/conventions.py +49 -0
  198. agenta/sdk/engines/tracing/exporters.py +130 -0
  199. agenta/sdk/engines/tracing/inline.py +1154 -0
  200. agenta/sdk/engines/tracing/processors.py +190 -0
  201. agenta/sdk/engines/tracing/propagation.py +102 -0
  202. agenta/sdk/engines/tracing/spans.py +136 -0
  203. agenta/sdk/engines/tracing/tracing.py +324 -0
  204. agenta/sdk/evaluations/__init__.py +2 -0
  205. agenta/sdk/evaluations/metrics.py +37 -0
  206. agenta/sdk/evaluations/preview/__init__.py +0 -0
  207. agenta/sdk/evaluations/preview/evaluate.py +765 -0
  208. agenta/sdk/evaluations/preview/utils.py +861 -0
  209. agenta/sdk/evaluations/results.py +66 -0
  210. agenta/sdk/evaluations/runs.py +153 -0
  211. agenta/sdk/evaluations/scenarios.py +48 -0
  212. agenta/sdk/litellm/litellm.py +12 -0
  213. agenta/sdk/litellm/mockllm.py +6 -8
  214. agenta/sdk/litellm/mocks/__init__.py +5 -5
  215. agenta/sdk/managers/applications.py +304 -0
  216. agenta/sdk/managers/config.py +2 -2
  217. agenta/sdk/managers/evaluations.py +0 -0
  218. agenta/sdk/managers/evaluators.py +303 -0
  219. agenta/sdk/managers/secrets.py +161 -24
  220. agenta/sdk/managers/shared.py +3 -1
  221. agenta/sdk/managers/testsets.py +441 -0
  222. agenta/sdk/managers/vault.py +3 -3
  223. agenta/sdk/middleware/auth.py +0 -176
  224. agenta/sdk/middleware/config.py +27 -9
  225. agenta/sdk/middleware/vault.py +204 -9
  226. agenta/sdk/middlewares/__init__.py +0 -0
  227. agenta/sdk/middlewares/routing/__init__.py +0 -0
  228. agenta/sdk/middlewares/routing/auth.py +263 -0
  229. agenta/sdk/middlewares/routing/cors.py +30 -0
  230. agenta/sdk/middlewares/routing/otel.py +29 -0
  231. agenta/sdk/middlewares/running/__init__.py +0 -0
  232. agenta/sdk/middlewares/running/normalizer.py +321 -0
  233. agenta/sdk/middlewares/running/resolver.py +161 -0
  234. agenta/sdk/middlewares/running/vault.py +140 -0
  235. agenta/sdk/models/__init__.py +0 -0
  236. agenta/sdk/models/blobs.py +33 -0
  237. agenta/sdk/models/evaluations.py +119 -0
  238. agenta/sdk/models/git.py +126 -0
  239. agenta/sdk/models/shared.py +167 -0
  240. agenta/sdk/models/testsets.py +163 -0
  241. agenta/sdk/models/tracing.py +202 -0
  242. agenta/sdk/models/workflows.py +753 -0
  243. agenta/sdk/tracing/attributes.py +4 -4
  244. agenta/sdk/tracing/exporters.py +67 -17
  245. agenta/sdk/tracing/inline.py +37 -45
  246. agenta/sdk/tracing/processors.py +97 -0
  247. agenta/sdk/tracing/propagation.py +3 -1
  248. agenta/sdk/tracing/spans.py +4 -0
  249. agenta/sdk/tracing/tracing.py +13 -15
  250. agenta/sdk/types.py +222 -22
  251. agenta/sdk/utils/cache.py +1 -1
  252. agenta/sdk/utils/client.py +38 -0
  253. agenta/sdk/utils/helpers.py +13 -12
  254. agenta/sdk/utils/logging.py +18 -78
  255. agenta/sdk/utils/references.py +23 -0
  256. agenta/sdk/workflows/builtin.py +600 -0
  257. agenta/sdk/workflows/configurations.py +22 -0
  258. agenta/sdk/workflows/errors.py +292 -0
  259. agenta/sdk/workflows/handlers.py +1791 -0
  260. agenta/sdk/workflows/interfaces.py +948 -0
  261. agenta/sdk/workflows/sandbox.py +118 -0
  262. agenta/sdk/workflows/utils.py +303 -6
  263. {agenta-0.52.6.dist-info → agenta-0.63.2.dist-info}/METADATA +37 -33
  264. agenta-0.63.2.dist-info/RECORD +421 -0
  265. {agenta-0.52.6.dist-info → agenta-0.63.2.dist-info}/WHEEL +1 -1
  266. agenta/sdk/middleware/adapt.py +0 -253
  267. agenta/sdk/middleware/base.py +0 -40
  268. agenta/sdk/middleware/flags.py +0 -40
  269. agenta/sdk/workflows/types.py +0 -472
  270. agenta-0.52.6.dist-info/RECORD +0 -371
  271. /agenta/sdk/{workflows → engines/running}/registry.py +0 -0
@@ -28,13 +28,12 @@ from agenta.sdk.middleware.otel import OTelMiddleware
28
28
  from agenta.sdk.middleware.auth import AuthHTTPMiddleware
29
29
  from agenta.sdk.middleware.cors import CORSMiddleware
30
30
 
31
- from agenta.sdk.context.serving import (
32
- serving_context_manager,
31
+ from agenta.sdk.contexts.routing import (
32
+ routing_context_manager,
33
33
  RoutingContext,
34
34
  )
35
- from agenta.sdk.context.tracing import (
35
+ from agenta.sdk.contexts.tracing import (
36
36
  tracing_context_manager,
37
- tracing_context,
38
37
  TracingContext,
39
38
  )
40
39
  from agenta.sdk.router import router
@@ -338,7 +337,7 @@ class entrypoint:
338
337
  inline = state.inline
339
338
  mock = state.mock
340
339
 
341
- with serving_context_manager(
340
+ with routing_context_manager(
342
341
  context=RoutingContext(
343
342
  parameters=parameters,
344
343
  secrets=secrets,
@@ -394,15 +393,15 @@ class entrypoint:
394
393
 
395
394
  try:
396
395
  if isinstance(result, StarletteResponse):
397
- result.headers.setdefault("X-ag-version", "3.0")
396
+ result.headers.setdefault("x-ag-version", "3.0")
398
397
  if content_type:
399
- result.headers.setdefault("X-ag-content-type", content_type)
398
+ result.headers.setdefault("x-ag-content-type", content_type)
400
399
  if tree_id:
401
- result.headers.setdefault("X-ag-tree-id", tree_id)
400
+ result.headers.setdefault("x-ag-tree-id", tree_id)
402
401
  if trace_id:
403
- result.headers.setdefault("X-ag-trace-id", trace_id)
402
+ result.headers.setdefault("x-ag-trace-id", trace_id)
404
403
  if span_id:
405
- result.headers.setdefault("X-ag-span-id", span_id)
404
+ result.headers.setdefault("x-ag-span-id", span_id)
406
405
 
407
406
  return result
408
407
  except:
@@ -530,7 +529,7 @@ class entrypoint:
530
529
  async def fetch_inline_trace_id(
531
530
  self,
532
531
  ):
533
- context = tracing_context.get()
532
+ context = TracingContext.get()
534
533
 
535
534
  link = context.link
536
535
 
@@ -549,7 +548,7 @@ class entrypoint:
549
548
  TIMESTEP = 0.1
550
549
  NOFSTEPS = TIMEOUT / TIMESTEP
551
550
 
552
- context = tracing_context.get()
551
+ context = TracingContext.get()
553
552
 
554
553
  link = context.link
555
554
 
@@ -657,9 +656,9 @@ class entrypoint:
657
656
  def add_func_params_to_parser(self, updated_params: list) -> None:
658
657
  """Add function parameters to function signature."""
659
658
  for name, param in signature(self.func).parameters.items():
660
- assert (
661
- len(param.default.__class__.__bases__) == 1
662
- ), f"Inherited standard type of {param.default.__class__} needs to be one."
659
+ assert len(param.default.__class__.__bases__) == 1, (
660
+ f"Inherited standard type of {param.default.__class__} needs to be one."
661
+ )
663
662
  updated_params.append(
664
663
  Parameter(
665
664
  name,
@@ -719,9 +718,9 @@ class entrypoint:
719
718
  -1
720
719
  ] # Extract schema name
721
720
  if schema_name in schema_name_map:
722
- content["schema"][
723
- "$ref"
724
- ] = f"#/components/schemas/{schema_name_map[schema_name]}"
721
+ content["schema"]["$ref"] = (
722
+ f"#/components/schemas/{schema_name_map[schema_name]}"
723
+ )
725
724
 
726
725
  if "responses" in method:
727
726
  for status_code, response in method["responses"].items():
@@ -735,9 +734,9 @@ class entrypoint:
735
734
  -1
736
735
  ] # Extract schema name
737
736
  if schema_name in schema_name_map:
738
- content["schema"][
739
- "$ref"
740
- ] = f"#/components/schemas/{schema_name_map[schema_name]}"
737
+ content["schema"]["$ref"] = (
738
+ f"#/components/schemas/{schema_name_map[schema_name]}"
739
+ )
741
740
 
742
741
  # ✅ Update OpenAPI schema with fixed schemas
743
742
  openapi_schema["components"]["schemas"] = updated_schemas
@@ -1,8 +1,9 @@
1
+ # /agenta/sdk/decorators/tracing.py
2
+
1
3
  from typing import Callable, Optional, Any, Dict, List, Union
2
4
 
3
5
  from opentelemetry import context as otel_context
4
6
  from opentelemetry.context import attach, detach
5
- from opentelemetry import trace
6
7
 
7
8
 
8
9
  from functools import wraps
@@ -14,21 +15,37 @@ from inspect import (
14
15
  isasyncgenfunction,
15
16
  )
16
17
 
18
+ from pydantic import BaseModel
19
+
17
20
  from opentelemetry import baggage
18
21
  from opentelemetry.context import attach, detach, get_current
19
22
  from opentelemetry.baggage import set_baggage, get_all
20
23
 
21
24
  from agenta.sdk.utils.logging import get_module_logger
22
25
  from agenta.sdk.utils.exceptions import suppress
23
- from agenta.sdk.utils.otel import debug_otel_context
24
- from agenta.sdk.context.tracing import tracing_context
26
+ from agenta.sdk.contexts.tracing import (
27
+ TracingContext,
28
+ tracing_context_manager,
29
+ )
25
30
  from agenta.sdk.tracing.conventions import parse_span_kind
26
31
 
27
32
  import agenta as ag
28
33
 
34
+
29
35
  log = get_module_logger(__name__)
30
36
 
31
37
 
38
+ def _has_instrument(handler: Callable[..., Any]) -> bool:
39
+ return bool(getattr(handler, "__has_instrument__", False))
40
+
41
+
42
+ def auto_instrument(handler: Callable[..., Any]) -> Callable[..., Any]:
43
+ if _has_instrument(handler):
44
+ return handler
45
+
46
+ return instrument()(handler)
47
+
48
+
32
49
  class instrument: # pylint: disable=invalid-name
33
50
  DEFAULT_KEY = "__default__"
34
51
 
@@ -41,7 +58,8 @@ class instrument: # pylint: disable=invalid-name
41
58
  redact: Optional[Callable[..., Any]] = None,
42
59
  redact_on_error: Optional[bool] = True,
43
60
  max_depth: Optional[int] = 2,
44
- aggregate: Optional[Callable[[List[Any]], Any]] = None,
61
+ aggregate: Optional[Union[bool, Callable]] = None, # stream to batch
62
+ annotate: Optional[bool] = None, # annotation vs invocation
45
63
  # DEPRECATING
46
64
  kind: str = "task",
47
65
  spankind: Optional[str] = "TASK",
@@ -55,142 +73,183 @@ class instrument: # pylint: disable=invalid-name
55
73
  self.redact_on_error = redact_on_error
56
74
  self.max_depth = max_depth
57
75
  self.aggregate = aggregate
76
+ self.annotate = annotate
58
77
 
59
- def __call__(self, func: Callable[..., Any]):
60
- is_coroutine_function = iscoroutinefunction(func)
61
- is_sync_generator = isgeneratorfunction(func)
62
- is_async_generator = isasyncgenfunction(func)
78
+ def __call__(self, handler: Callable[..., Any]):
79
+ is_coroutine_function = iscoroutinefunction(handler)
80
+ is_sync_generator = isgeneratorfunction(handler)
81
+ is_async_generator = isasyncgenfunction(handler)
63
82
 
64
83
  # ---- ASYNC GENERATOR ----
65
84
  if is_async_generator:
66
85
 
67
- @wraps(func)
86
+ @wraps(handler)
68
87
  def astream_wrapper(*args, **kwargs):
69
- # debug_otel_context("[BEFORE STREAM] [BEFORE SETUP]")
88
+ with tracing_context_manager(context=TracingContext.get()):
89
+ # debug_otel_context("[BEFORE STREAM] [BEFORE SETUP]")
70
90
 
71
- captured_ctx = otel_context.get_current()
91
+ captured_ctx = otel_context.get_current()
72
92
 
73
- self._parse_type_and_kind()
93
+ self._parse_type_and_kind()
74
94
 
75
- self._attach_baggage()
95
+ self._attach_baggage()
76
96
 
77
- ctx = self._get_traceparent()
97
+ ctx = self._get_traceparent()
78
98
 
79
- # debug_otel_context("[BEFORE STREAM] [AFTER SETUP]")
99
+ # debug_otel_context("[BEFORE STREAM] [AFTER SETUP]")
80
100
 
81
- async def wrapped_generator():
82
- # debug_otel_context("[WITHIN STREAM] [BEFORE ATTACH]")
101
+ async def wrapped_generator():
102
+ # debug_otel_context("[WITHIN STREAM] [BEFORE ATTACH]")
83
103
 
84
- otel_token = otel_context.attach(captured_ctx)
104
+ otel_token = otel_context.attach(captured_ctx)
85
105
 
86
- # debug_otel_context("[WITHIN STREAM] [AFTER ATTACH]")
106
+ # debug_otel_context("[WITHIN STREAM] [AFTER ATTACH]")
87
107
 
88
- try:
89
- with ag.tracer.start_as_current_span(
90
- name=func.__name__,
91
- kind=self.kind,
92
- context=ctx,
93
- ):
94
- self._set_link()
95
- self._pre_instrument(func, *args, **kwargs)
108
+ try:
109
+ with ag.tracer.start_as_current_span(
110
+ name=handler.__name__,
111
+ kind=self.kind,
112
+ context=ctx,
113
+ ):
114
+ self._set_link()
115
+ self._pre_instrument(handler, *args, **kwargs)
96
116
 
97
- _result = []
117
+ _result = []
98
118
 
99
- agen = func(*args, **kwargs)
119
+ agen = handler(*args, **kwargs)
100
120
 
101
- try:
102
- async for chunk in agen:
103
- _result.append(chunk)
104
- yield chunk
121
+ try:
122
+ async for chunk in agen:
123
+ _result.append(chunk)
124
+ yield chunk
105
125
 
106
- finally:
107
- if self.aggregate:
108
- result = self.aggregate(_result)
109
- elif all(isinstance(r, str) for r in _result):
110
- result = "".join(_result)
111
- elif all(isinstance(r, bytes) for r in _result):
112
- result = b"".join(_result)
113
- else:
114
- result = _result
126
+ finally:
127
+ if self.aggregate and callable(self.aggregate):
128
+ result = self.aggregate(_result)
129
+ elif all(isinstance(r, str) for r in _result):
130
+ result = "".join(_result)
131
+ elif all(isinstance(r, bytes) for r in _result):
132
+ result = b"".join(_result)
133
+ else:
134
+ result = _result
115
135
 
116
- self._post_instrument(result)
136
+ self._post_instrument(result)
117
137
 
118
- finally:
119
- # debug_otel_context("[WITHIN STREAM] [BEFORE DETACH]")
138
+ finally:
139
+ # debug_otel_context("[WITHIN STREAM] [BEFORE DETACH]")
120
140
 
121
- otel_context.detach(otel_token)
141
+ otel_context.detach(otel_token)
122
142
 
123
- # debug_otel_context("[WITHIN STREAM] [AFTER DETACH]")
143
+ # debug_otel_context("[WITHIN STREAM] [AFTER DETACH]")
124
144
 
125
145
  return wrapped_generator()
126
146
 
147
+ setattr(astream_wrapper, "__has_instrument__", True)
148
+ setattr(astream_wrapper, "__original_handler__", handler)
127
149
  return astream_wrapper
128
150
 
129
151
  # ---- SYNC GENERATOR ----
130
152
  if is_sync_generator:
131
153
 
132
- @wraps(func)
154
+ @wraps(handler)
133
155
  def stream_wrapper(*args, **kwargs):
134
- self._parse_type_and_kind()
156
+ with tracing_context_manager(context=TracingContext.get()):
157
+ self._parse_type_and_kind()
135
158
 
136
- token = self._attach_baggage()
159
+ token = self._attach_baggage()
137
160
 
138
- ctx = self._get_traceparent()
161
+ ctx = self._get_traceparent()
139
162
 
140
- def wrapped_generator():
141
- try:
142
- with ag.tracer.start_as_current_span(
143
- name=func.__name__,
144
- kind=self.kind,
145
- context=ctx,
146
- ):
147
- self._set_link()
163
+ def wrapped_generator():
164
+ try:
165
+ with ag.tracer.start_as_current_span(
166
+ name=handler.__name__,
167
+ kind=self.kind,
168
+ context=ctx,
169
+ ):
170
+ self._set_link()
148
171
 
149
- self._pre_instrument(func, *args, **kwargs)
172
+ self._pre_instrument(handler, *args, **kwargs)
150
173
 
151
- _result = []
174
+ _result = []
152
175
 
153
- gen = func(*args, **kwargs)
176
+ gen = handler(*args, **kwargs)
154
177
 
155
- gen_return = None
178
+ gen_return = None
156
179
 
157
- try:
158
- while True:
159
- try:
160
- chunk = next(gen)
161
- except StopIteration as e:
162
- gen_return = e.value
163
- break
180
+ try:
181
+ while True:
182
+ try:
183
+ chunk = next(gen)
184
+ except StopIteration as e:
185
+ gen_return = e.value
186
+ break
164
187
 
165
- _result.append(chunk)
166
- yield chunk
188
+ _result.append(chunk)
189
+ yield chunk
167
190
 
168
- finally:
169
- if self.aggregate:
170
- result = self.aggregate(_result)
171
- elif all(isinstance(r, str) for r in _result):
172
- result = "".join(_result)
173
- elif all(isinstance(r, bytes) for r in _result):
174
- result = b"".join(_result)
175
- else:
176
- result = _result
191
+ finally:
192
+ if self.aggregate and callable(self.aggregate):
193
+ result = self.aggregate(_result)
194
+ elif all(isinstance(r, str) for r in _result):
195
+ result = "".join(_result)
196
+ elif all(isinstance(r, bytes) for r in _result):
197
+ result = b"".join(_result)
198
+ else:
199
+ result = _result
177
200
 
178
- self._post_instrument(result)
201
+ self._post_instrument(result)
179
202
 
180
- return gen_return
203
+ return gen_return
181
204
 
182
- finally:
183
- self._detach_baggage(token)
205
+ finally:
206
+ self._detach_baggage(token)
184
207
 
185
208
  return wrapped_generator()
186
209
 
210
+ setattr(stream_wrapper, "__has_instrument__", True)
211
+ setattr(stream_wrapper, "__original_handler__", handler)
187
212
  return stream_wrapper
188
213
 
189
- # ---- ASYNC FUNCTION (non-generator) ----
214
+ # ---- ASYNC FUNCTION ----
190
215
  if is_coroutine_function:
191
216
 
192
- @wraps(func)
217
+ @wraps(handler)
193
218
  async def awrapper(*args, **kwargs):
219
+ with tracing_context_manager(context=TracingContext.get()):
220
+ self._parse_type_and_kind()
221
+
222
+ token = self._attach_baggage()
223
+
224
+ ctx = self._get_traceparent()
225
+
226
+ try:
227
+ with ag.tracer.start_as_current_span(
228
+ name=handler.__name__,
229
+ kind=self.kind,
230
+ context=ctx,
231
+ ):
232
+ self._set_link()
233
+
234
+ self._pre_instrument(handler, *args, **kwargs)
235
+
236
+ result = await handler(*args, **kwargs)
237
+
238
+ self._post_instrument(result)
239
+
240
+ finally:
241
+ self._detach_baggage(token)
242
+
243
+ return result
244
+
245
+ setattr(awrapper, "__has_instrument__", True)
246
+ setattr(awrapper, "__original_handler__", handler)
247
+ return awrapper
248
+
249
+ # ---- SYNC FUNCTION ----
250
+ @wraps(handler)
251
+ def wrapper(*args, **kwargs):
252
+ with tracing_context_manager(context=TracingContext.get()):
194
253
  self._parse_type_and_kind()
195
254
 
196
255
  token = self._attach_baggage()
@@ -199,15 +258,15 @@ class instrument: # pylint: disable=invalid-name
199
258
 
200
259
  try:
201
260
  with ag.tracer.start_as_current_span(
202
- name=func.__name__,
261
+ name=handler.__name__,
203
262
  kind=self.kind,
204
263
  context=ctx,
205
264
  ):
206
265
  self._set_link()
207
266
 
208
- self._pre_instrument(func, *args, **kwargs)
267
+ self._pre_instrument(handler, *args, **kwargs)
209
268
 
210
- result = await func(*args, **kwargs)
269
+ result = handler(*args, **kwargs)
211
270
 
212
271
  self._post_instrument(result)
213
272
 
@@ -216,36 +275,8 @@ class instrument: # pylint: disable=invalid-name
216
275
 
217
276
  return result
218
277
 
219
- return awrapper
220
-
221
- # ---- SYNC FUNCTION (non-generator) ----
222
- @wraps(func)
223
- def wrapper(*args, **kwargs):
224
- self._parse_type_and_kind()
225
-
226
- token = self._attach_baggage()
227
-
228
- ctx = self._get_traceparent()
229
-
230
- try:
231
- with ag.tracer.start_as_current_span(
232
- name=func.__name__,
233
- kind=self.kind,
234
- context=ctx,
235
- ):
236
- self._set_link()
237
-
238
- self._pre_instrument(func, *args, **kwargs)
239
-
240
- result = func(*args, **kwargs)
241
-
242
- self._post_instrument(result)
243
-
244
- finally:
245
- self._detach_baggage(token)
246
-
247
- return result
248
-
278
+ setattr(wrapper, "__has_instrument__", True)
279
+ setattr(wrapper, "__original_handler__", handler)
249
280
  return wrapper
250
281
 
251
282
  def _parse_type_and_kind(self):
@@ -255,7 +286,7 @@ class instrument: # pylint: disable=invalid-name
255
286
  self.kind = parse_span_kind(self.type)
256
287
 
257
288
  def _get_traceparent(self):
258
- context = tracing_context.get()
289
+ context = TracingContext.get()
259
290
 
260
291
  traceparent = context.traceparent
261
292
 
@@ -268,7 +299,7 @@ class instrument: # pylint: disable=invalid-name
268
299
  def _set_link(self):
269
300
  span = ag.tracing.get_current_span()
270
301
 
271
- context = tracing_context.get()
302
+ context = TracingContext.get()
272
303
 
273
304
  if not context.link:
274
305
  context.link = {
@@ -276,10 +307,10 @@ class instrument: # pylint: disable=invalid-name
276
307
  "span_id": span.get_span_context().span_id,
277
308
  }
278
309
 
279
- tracing_context.set(context)
310
+ TracingContext.set(context)
280
311
 
281
312
  def _attach_baggage(self):
282
- context = tracing_context.get()
313
+ context = TracingContext.get()
283
314
 
284
315
  references = context.references
285
316
 
@@ -299,26 +330,24 @@ class instrument: # pylint: disable=invalid-name
299
330
 
300
331
  def _pre_instrument(
301
332
  self,
302
- func,
333
+ handler,
303
334
  *args,
304
335
  **kwargs,
305
336
  ):
306
337
  span = ag.tracing.get_current_span()
307
338
 
308
- context = tracing_context.get()
339
+ context = TracingContext.get()
309
340
 
310
341
  with suppress():
311
342
  trace_id = span.context.trace_id
312
343
 
313
344
  ag.tracing.credentials.put(trace_id, context.credentials)
314
345
 
315
- trace_type = context.type or "invocation"
316
346
  span_type = self.type or "task"
317
347
 
318
348
  span.set_attributes(
319
349
  attributes={
320
350
  "node": span_type,
321
- "tree": trace_type,
322
351
  },
323
352
  namespace="type",
324
353
  )
@@ -332,7 +361,7 @@ class instrument: # pylint: disable=invalid-name
332
361
  _inputs = self._redact(
333
362
  name=span.name,
334
363
  field="inputs",
335
- io=self._parse(func, *args, **kwargs),
364
+ io=self._parse(handler, *args, **kwargs),
336
365
  ignore=self.ignore_inputs,
337
366
  )
338
367
 
@@ -403,14 +432,14 @@ class instrument: # pylint: disable=invalid-name
403
432
 
404
433
  def _parse(
405
434
  self,
406
- func,
435
+ handler,
407
436
  *args,
408
437
  **kwargs,
409
438
  ) -> Dict[str, Any]:
410
439
  inputs = {
411
440
  key: value
412
441
  for key, value in chain(
413
- zip(getfullargspec(func).args, args),
442
+ zip(getfullargspec(handler).args, args),
414
443
  kwargs.items(),
415
444
  )
416
445
  }
@@ -464,6 +493,22 @@ class instrument: # pylint: disable=invalid-name
464
493
  if ag.tracing.redact_on_error:
465
494
  io = {}
466
495
 
496
+ if "request" in io:
497
+ with suppress():
498
+ if isinstance(io["request"], BaseModel):
499
+ io["request"] = io["request"].model_dump(
500
+ mode="json",
501
+ exclude_none=True,
502
+ )
503
+
504
+ if "response" in io:
505
+ with suppress():
506
+ if isinstance(io["response"], BaseModel):
507
+ io["response"] = io["response"].model_dump(
508
+ mode="json",
509
+ exclude_none=True,
510
+ )
511
+
467
512
  return io
468
513
 
469
514
  def _patch(
File without changes
File without changes
@@ -0,0 +1,17 @@
1
+ from typing import Optional, Tuple
2
+
3
+
4
+ async def parse_service_uri(
5
+ uri: str,
6
+ ) -> Tuple[Optional[str], Optional[str], Optional[str], Optional[str]]:
7
+ if not uri or not uri.strip():
8
+ return None, None, None, None
9
+
10
+ # uri ~ [<provider>|empty]:<kind>:<key>:[<version>|'latest'|empty]
11
+
12
+ parts = uri.split(":")
13
+
14
+ if len(parts) != 4:
15
+ return None, None, None, None
16
+
17
+ return tuple(parts)
@@ -0,0 +1 @@
1
+ from .tracing import Tracing, get_tracer