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.
- agenta/__init__.py +12 -3
- agenta/client/__init__.py +4 -4
- agenta/client/backend/__init__.py +4 -4
- agenta/client/backend/api_keys/client.py +2 -2
- agenta/client/backend/billing/client.py +2 -2
- agenta/client/backend/billing/raw_client.py +2 -2
- agenta/client/backend/client.py +56 -48
- agenta/client/backend/core/client_wrapper.py +2 -2
- agenta/client/backend/core/file.py +3 -1
- agenta/client/backend/core/http_client.py +3 -3
- agenta/client/backend/core/pydantic_utilities.py +13 -3
- agenta/client/backend/human_evaluations/client.py +2 -2
- agenta/client/backend/human_evaluations/raw_client.py +2 -2
- agenta/client/backend/organization/client.py +46 -34
- agenta/client/backend/organization/raw_client.py +32 -26
- agenta/client/backend/raw_client.py +26 -26
- agenta/client/backend/testsets/client.py +18 -18
- agenta/client/backend/testsets/raw_client.py +30 -30
- agenta/client/backend/types/__init__.py +4 -4
- agenta/client/backend/types/account_request.py +3 -1
- agenta/client/backend/types/account_response.py +3 -1
- agenta/client/backend/types/agenta_node_dto.py +3 -1
- agenta/client/backend/types/agenta_nodes_response.py +3 -1
- agenta/client/backend/types/agenta_root_dto.py +3 -1
- agenta/client/backend/types/agenta_roots_response.py +3 -1
- agenta/client/backend/types/agenta_tree_dto.py +3 -1
- agenta/client/backend/types/agenta_trees_response.py +3 -1
- agenta/client/backend/types/aggregated_result.py +3 -1
- agenta/client/backend/types/analytics_response.py +3 -1
- agenta/client/backend/types/annotation.py +6 -4
- agenta/client/backend/types/annotation_create.py +3 -1
- agenta/client/backend/types/annotation_edit.py +3 -1
- agenta/client/backend/types/annotation_link.py +3 -1
- agenta/client/backend/types/annotation_link_response.py +3 -1
- agenta/client/backend/types/annotation_query.py +3 -1
- agenta/client/backend/types/annotation_query_request.py +3 -1
- agenta/client/backend/types/annotation_reference.py +3 -1
- agenta/client/backend/types/annotation_references.py +3 -1
- agenta/client/backend/types/annotation_response.py +3 -1
- agenta/client/backend/types/annotations_response.py +3 -1
- agenta/client/backend/types/app.py +3 -1
- agenta/client/backend/types/app_variant_response.py +3 -1
- agenta/client/backend/types/app_variant_revision.py +3 -1
- agenta/client/backend/types/artifact.py +6 -4
- agenta/client/backend/types/base_output.py +3 -1
- agenta/client/backend/types/body_fetch_workflow_revision.py +3 -1
- agenta/client/backend/types/body_import_testset.py +3 -1
- agenta/client/backend/types/bucket_dto.py +3 -1
- agenta/client/backend/types/collect_status_response.py +3 -1
- agenta/client/backend/types/config_db.py +3 -1
- agenta/client/backend/types/config_dto.py +3 -1
- agenta/client/backend/types/config_response_model.py +3 -1
- agenta/client/backend/types/correct_answer.py +3 -1
- agenta/client/backend/types/create_app_output.py +3 -1
- agenta/client/backend/types/custom_model_settings_dto.py +3 -1
- agenta/client/backend/types/custom_provider_dto.py +3 -1
- agenta/client/backend/types/custom_provider_kind.py +1 -1
- agenta/client/backend/types/custom_provider_settings_dto.py +3 -1
- agenta/client/backend/types/delete_evaluation.py +3 -1
- agenta/client/backend/types/environment_output.py +3 -1
- agenta/client/backend/types/environment_output_extended.py +3 -1
- agenta/client/backend/types/environment_revision.py +3 -1
- agenta/client/backend/types/error.py +3 -1
- agenta/client/backend/types/evaluation.py +3 -1
- agenta/client/backend/types/evaluation_scenario.py +3 -1
- agenta/client/backend/types/evaluation_scenario_input.py +3 -1
- agenta/client/backend/types/evaluation_scenario_output.py +3 -1
- agenta/client/backend/types/evaluation_scenario_result.py +3 -1
- agenta/client/backend/types/evaluator.py +6 -4
- agenta/client/backend/types/evaluator_config.py +6 -4
- agenta/client/backend/types/evaluator_flags.py +3 -1
- agenta/client/backend/types/evaluator_mapping_output_interface.py +3 -1
- agenta/client/backend/types/evaluator_output_interface.py +3 -1
- agenta/client/backend/types/evaluator_query.py +3 -1
- agenta/client/backend/types/evaluator_query_request.py +3 -1
- agenta/client/backend/types/evaluator_request.py +3 -1
- agenta/client/backend/types/evaluator_response.py +3 -1
- agenta/client/backend/types/evaluators_response.py +3 -1
- agenta/client/backend/types/exception_dto.py +3 -1
- agenta/client/backend/types/extended_o_tel_tracing_response.py +3 -1
- agenta/client/backend/types/get_config_response.py +3 -1
- agenta/client/backend/types/header.py +3 -1
- agenta/client/backend/types/http_validation_error.py +3 -1
- agenta/client/backend/types/human_evaluation.py +3 -1
- agenta/client/backend/types/human_evaluation_scenario.py +3 -1
- agenta/client/backend/types/human_evaluation_scenario_input.py +3 -1
- agenta/client/backend/types/human_evaluation_scenario_output.py +3 -1
- agenta/client/backend/types/invite_request.py +3 -1
- agenta/client/backend/types/legacy_analytics_response.py +3 -1
- agenta/client/backend/types/legacy_data_point.py +3 -1
- agenta/client/backend/types/legacy_evaluator.py +3 -1
- agenta/client/backend/types/legacy_scope_request.py +3 -1
- agenta/client/backend/types/legacy_scopes_response.py +3 -1
- agenta/client/backend/types/legacy_subscription_request.py +3 -1
- agenta/client/backend/types/legacy_user_request.py +3 -1
- agenta/client/backend/types/legacy_user_response.py +3 -1
- agenta/client/backend/types/lifecycle_dto.py +3 -1
- agenta/client/backend/types/link_dto.py +3 -1
- agenta/client/backend/types/list_api_keys_response.py +3 -1
- agenta/client/backend/types/llm_run_rate_limit.py +3 -1
- agenta/client/backend/types/meta_request.py +3 -1
- agenta/client/backend/types/metrics_dto.py +3 -1
- agenta/client/backend/types/new_testset.py +3 -1
- agenta/client/backend/types/node_dto.py +3 -1
- agenta/client/backend/types/o_tel_context_dto.py +3 -1
- agenta/client/backend/types/o_tel_event.py +6 -4
- agenta/client/backend/types/o_tel_event_dto.py +3 -1
- agenta/client/backend/types/o_tel_extra_dto.py +3 -1
- agenta/client/backend/types/o_tel_flat_span.py +6 -4
- agenta/client/backend/types/o_tel_link.py +6 -4
- agenta/client/backend/types/o_tel_link_dto.py +3 -1
- agenta/client/backend/types/o_tel_links_response.py +3 -1
- agenta/client/backend/types/o_tel_span.py +1 -1
- agenta/client/backend/types/o_tel_span_dto.py +3 -1
- agenta/client/backend/types/o_tel_spans_tree.py +3 -1
- agenta/client/backend/types/o_tel_tracing_data_response.py +3 -1
- agenta/client/backend/types/o_tel_tracing_request.py +3 -1
- agenta/client/backend/types/o_tel_tracing_response.py +3 -1
- agenta/client/backend/types/organization.py +3 -1
- agenta/client/backend/types/organization_details.py +3 -1
- agenta/client/backend/types/organization_membership_request.py +3 -1
- agenta/client/backend/types/organization_output.py +3 -1
- agenta/client/backend/types/organization_request.py +3 -1
- agenta/client/backend/types/parent_dto.py +3 -1
- agenta/client/backend/types/project_membership_request.py +3 -1
- agenta/client/backend/types/project_request.py +3 -1
- agenta/client/backend/types/project_scope.py +3 -1
- agenta/client/backend/types/projects_response.py +3 -1
- agenta/client/backend/types/reference.py +6 -4
- agenta/client/backend/types/reference_dto.py +3 -1
- agenta/client/backend/types/reference_request_model.py +3 -1
- agenta/client/backend/types/result.py +3 -1
- agenta/client/backend/types/root_dto.py +3 -1
- agenta/client/backend/types/scopes_response_model.py +3 -1
- agenta/client/backend/types/secret_dto.py +3 -1
- agenta/client/backend/types/secret_response_dto.py +3 -1
- agenta/client/backend/types/simple_evaluation_output.py +3 -1
- agenta/client/backend/types/span_dto.py +6 -4
- agenta/client/backend/types/standard_provider_dto.py +3 -1
- agenta/client/backend/types/standard_provider_settings_dto.py +3 -1
- agenta/client/backend/types/status_dto.py +3 -1
- agenta/client/backend/types/tags_request.py +3 -1
- agenta/client/backend/types/testcase_response.py +6 -4
- agenta/client/backend/types/testset.py +6 -4
- agenta/client/backend/types/{test_set_output_response.py → testset_output_response.py} +4 -2
- agenta/client/backend/types/testset_request.py +3 -1
- agenta/client/backend/types/testset_response.py +3 -1
- agenta/client/backend/types/{test_set_simple_response.py → testset_simple_response.py} +4 -2
- agenta/client/backend/types/testsets_response.py +3 -1
- agenta/client/backend/types/time_dto.py +3 -1
- agenta/client/backend/types/tree_dto.py +3 -1
- agenta/client/backend/types/update_app_output.py +3 -1
- agenta/client/backend/types/user_request.py +3 -1
- agenta/client/backend/types/validation_error.py +3 -1
- agenta/client/backend/types/workflow_artifact.py +6 -4
- agenta/client/backend/types/workflow_data.py +3 -1
- agenta/client/backend/types/workflow_flags.py +3 -1
- agenta/client/backend/types/workflow_request.py +3 -1
- agenta/client/backend/types/workflow_response.py +3 -1
- agenta/client/backend/types/workflow_revision.py +6 -4
- agenta/client/backend/types/workflow_revision_request.py +3 -1
- agenta/client/backend/types/workflow_revision_response.py +3 -1
- agenta/client/backend/types/workflow_revisions_response.py +3 -1
- agenta/client/backend/types/workflow_variant.py +6 -4
- agenta/client/backend/types/workflow_variant_request.py +3 -1
- agenta/client/backend/types/workflow_variant_response.py +3 -1
- agenta/client/backend/types/workflow_variants_response.py +3 -1
- agenta/client/backend/types/workflows_response.py +3 -1
- agenta/client/backend/types/workspace.py +3 -1
- agenta/client/backend/types/workspace_member_response.py +3 -1
- agenta/client/backend/types/workspace_membership_request.py +3 -1
- agenta/client/backend/types/workspace_permission.py +3 -1
- agenta/client/backend/types/workspace_request.py +3 -1
- agenta/client/backend/types/workspace_response.py +3 -1
- agenta/client/backend/vault/raw_client.py +4 -4
- agenta/client/backend/workspace/client.py +2 -2
- agenta/client/client.py +102 -88
- agenta/sdk/__init__.py +52 -3
- agenta/sdk/agenta_init.py +43 -16
- agenta/sdk/assets.py +23 -15
- agenta/sdk/context/serving.py +20 -8
- agenta/sdk/context/tracing.py +40 -22
- agenta/sdk/contexts/__init__.py +0 -0
- agenta/sdk/contexts/routing.py +38 -0
- agenta/sdk/contexts/running.py +57 -0
- agenta/sdk/contexts/tracing.py +86 -0
- agenta/sdk/decorators/__init__.py +1 -0
- agenta/sdk/decorators/routing.py +284 -0
- agenta/sdk/decorators/running.py +692 -98
- agenta/sdk/decorators/serving.py +20 -21
- agenta/sdk/decorators/tracing.py +176 -131
- agenta/sdk/engines/__init__.py +0 -0
- agenta/sdk/engines/running/__init__.py +0 -0
- agenta/sdk/engines/running/utils.py +17 -0
- agenta/sdk/engines/tracing/__init__.py +1 -0
- agenta/sdk/engines/tracing/attributes.py +185 -0
- agenta/sdk/engines/tracing/conventions.py +49 -0
- agenta/sdk/engines/tracing/exporters.py +130 -0
- agenta/sdk/engines/tracing/inline.py +1154 -0
- agenta/sdk/engines/tracing/processors.py +190 -0
- agenta/sdk/engines/tracing/propagation.py +102 -0
- agenta/sdk/engines/tracing/spans.py +136 -0
- agenta/sdk/engines/tracing/tracing.py +324 -0
- agenta/sdk/evaluations/__init__.py +2 -0
- agenta/sdk/evaluations/metrics.py +37 -0
- agenta/sdk/evaluations/preview/__init__.py +0 -0
- agenta/sdk/evaluations/preview/evaluate.py +765 -0
- agenta/sdk/evaluations/preview/utils.py +861 -0
- agenta/sdk/evaluations/results.py +66 -0
- agenta/sdk/evaluations/runs.py +153 -0
- agenta/sdk/evaluations/scenarios.py +48 -0
- agenta/sdk/litellm/litellm.py +12 -0
- agenta/sdk/litellm/mockllm.py +6 -8
- agenta/sdk/litellm/mocks/__init__.py +5 -5
- agenta/sdk/managers/applications.py +304 -0
- agenta/sdk/managers/config.py +2 -2
- agenta/sdk/managers/evaluations.py +0 -0
- agenta/sdk/managers/evaluators.py +303 -0
- agenta/sdk/managers/secrets.py +161 -24
- agenta/sdk/managers/shared.py +3 -1
- agenta/sdk/managers/testsets.py +441 -0
- agenta/sdk/managers/vault.py +3 -3
- agenta/sdk/middleware/auth.py +0 -176
- agenta/sdk/middleware/config.py +27 -9
- agenta/sdk/middleware/vault.py +204 -9
- agenta/sdk/middlewares/__init__.py +0 -0
- agenta/sdk/middlewares/routing/__init__.py +0 -0
- agenta/sdk/middlewares/routing/auth.py +263 -0
- agenta/sdk/middlewares/routing/cors.py +30 -0
- agenta/sdk/middlewares/routing/otel.py +29 -0
- agenta/sdk/middlewares/running/__init__.py +0 -0
- agenta/sdk/middlewares/running/normalizer.py +321 -0
- agenta/sdk/middlewares/running/resolver.py +161 -0
- agenta/sdk/middlewares/running/vault.py +140 -0
- agenta/sdk/models/__init__.py +0 -0
- agenta/sdk/models/blobs.py +33 -0
- agenta/sdk/models/evaluations.py +119 -0
- agenta/sdk/models/git.py +126 -0
- agenta/sdk/models/shared.py +167 -0
- agenta/sdk/models/testsets.py +163 -0
- agenta/sdk/models/tracing.py +202 -0
- agenta/sdk/models/workflows.py +753 -0
- agenta/sdk/tracing/attributes.py +4 -4
- agenta/sdk/tracing/exporters.py +67 -17
- agenta/sdk/tracing/inline.py +37 -45
- agenta/sdk/tracing/processors.py +97 -0
- agenta/sdk/tracing/propagation.py +3 -1
- agenta/sdk/tracing/spans.py +4 -0
- agenta/sdk/tracing/tracing.py +13 -15
- agenta/sdk/types.py +222 -22
- agenta/sdk/utils/cache.py +1 -1
- agenta/sdk/utils/client.py +38 -0
- agenta/sdk/utils/helpers.py +13 -12
- agenta/sdk/utils/logging.py +18 -78
- agenta/sdk/utils/references.py +23 -0
- agenta/sdk/workflows/builtin.py +600 -0
- agenta/sdk/workflows/configurations.py +22 -0
- agenta/sdk/workflows/errors.py +292 -0
- agenta/sdk/workflows/handlers.py +1791 -0
- agenta/sdk/workflows/interfaces.py +948 -0
- agenta/sdk/workflows/sandbox.py +118 -0
- agenta/sdk/workflows/utils.py +303 -6
- {agenta-0.52.6.dist-info → agenta-0.63.2.dist-info}/METADATA +37 -33
- agenta-0.63.2.dist-info/RECORD +421 -0
- {agenta-0.52.6.dist-info → agenta-0.63.2.dist-info}/WHEEL +1 -1
- agenta/sdk/middleware/adapt.py +0 -253
- agenta/sdk/middleware/base.py +0 -40
- agenta/sdk/middleware/flags.py +0 -40
- agenta/sdk/workflows/types.py +0 -472
- agenta-0.52.6.dist-info/RECORD +0 -371
- /agenta/sdk/{workflows → engines/running}/registry.py +0 -0
agenta/sdk/tracing/attributes.py
CHANGED
|
@@ -6,7 +6,7 @@ PrimitivesSequence = Sequence[Primitive]
|
|
|
6
6
|
Attribute = Union[Primitive, PrimitivesSequence]
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def
|
|
9
|
+
def _marshall(
|
|
10
10
|
unmarshalled: Dict[str, Any],
|
|
11
11
|
*,
|
|
12
12
|
parent_key: Optional[str] = "",
|
|
@@ -59,7 +59,7 @@ def _marshal(
|
|
|
59
59
|
dict_key = child_key
|
|
60
60
|
|
|
61
61
|
marshalled.update(
|
|
62
|
-
|
|
62
|
+
_marshall(
|
|
63
63
|
value,
|
|
64
64
|
parent_key=dict_key,
|
|
65
65
|
depth=depth + 1,
|
|
@@ -76,7 +76,7 @@ def _marshal(
|
|
|
76
76
|
|
|
77
77
|
if isinstance(item, (dict, list)):
|
|
78
78
|
marshalled.update(
|
|
79
|
-
|
|
79
|
+
_marshall(
|
|
80
80
|
item,
|
|
81
81
|
parent_key=list_key,
|
|
82
82
|
depth=depth + 1,
|
|
@@ -177,7 +177,7 @@ def serialize(
|
|
|
177
177
|
k: v
|
|
178
178
|
for k, v in {
|
|
179
179
|
_encode_key(namespace, key): _encode_value(value)
|
|
180
|
-
for key, value in
|
|
180
|
+
for key, value in _marshall(attributes, max_depth=max_depth).items()
|
|
181
181
|
}.items()
|
|
182
182
|
if v is not None
|
|
183
183
|
}
|
agenta/sdk/tracing/exporters.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
from typing import Sequence, Dict, List, Optional
|
|
1
|
+
from typing import Sequence, Dict, List, Optional, Any
|
|
2
|
+
from threading import Thread
|
|
3
|
+
from os import environ
|
|
4
|
+
from uuid import UUID
|
|
2
5
|
|
|
3
6
|
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
4
7
|
from opentelemetry.sdk.trace.export import (
|
|
@@ -8,18 +11,21 @@ from opentelemetry.sdk.trace.export import (
|
|
|
8
11
|
ReadableSpan,
|
|
9
12
|
)
|
|
10
13
|
|
|
14
|
+
from agenta.sdk.utils.constants import TRUTHY
|
|
11
15
|
from agenta.sdk.utils.logging import get_module_logger
|
|
12
16
|
from agenta.sdk.utils.exceptions import suppress
|
|
13
17
|
from agenta.sdk.utils.cache import TTLLRUCache
|
|
14
|
-
from agenta.sdk.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
from agenta.sdk.contexts.tracing import (
|
|
19
|
+
otlp_context_manager,
|
|
20
|
+
otlp_context,
|
|
21
|
+
OTLPContext,
|
|
18
22
|
)
|
|
19
23
|
|
|
20
24
|
|
|
21
25
|
log = get_module_logger(__name__)
|
|
22
26
|
|
|
27
|
+
_ASYNC_EXPORT = environ.get("AGENTA_OTLP_ASYNC_EXPORT", "true").lower() in TRUTHY
|
|
28
|
+
|
|
23
29
|
|
|
24
30
|
class InlineTraceExporter(SpanExporter):
|
|
25
31
|
def __init__(
|
|
@@ -45,6 +51,8 @@ class InlineTraceExporter(SpanExporter):
|
|
|
45
51
|
|
|
46
52
|
self._registry[trace_id].append(span)
|
|
47
53
|
|
|
54
|
+
return
|
|
55
|
+
|
|
48
56
|
def shutdown(self) -> None:
|
|
49
57
|
self._shutdown = True
|
|
50
58
|
|
|
@@ -84,7 +92,7 @@ class OTLPExporter(OTLPSpanExporter):
|
|
|
84
92
|
self.credentials = credentials
|
|
85
93
|
|
|
86
94
|
def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
|
|
87
|
-
grouped_spans: Dict[str, List[
|
|
95
|
+
grouped_spans: Dict[Optional[str], List[ReadableSpan]] = dict()
|
|
88
96
|
|
|
89
97
|
for span in spans:
|
|
90
98
|
trace_id = span.get_span_context().trace_id
|
|
@@ -94,18 +102,28 @@ class OTLPExporter(OTLPSpanExporter):
|
|
|
94
102
|
credentials = self.credentials.get(trace_id)
|
|
95
103
|
|
|
96
104
|
if credentials not in grouped_spans:
|
|
97
|
-
grouped_spans[credentials] =
|
|
105
|
+
grouped_spans[credentials] = list()
|
|
98
106
|
|
|
99
107
|
grouped_spans[credentials].append(span)
|
|
100
108
|
|
|
101
109
|
serialized_spans = []
|
|
102
110
|
|
|
103
111
|
for credentials, _spans in grouped_spans.items():
|
|
104
|
-
with
|
|
105
|
-
context=
|
|
112
|
+
with otlp_context_manager(
|
|
113
|
+
context=OTLPContext(
|
|
106
114
|
credentials=credentials,
|
|
107
115
|
)
|
|
108
116
|
):
|
|
117
|
+
for _span in _spans:
|
|
118
|
+
trace_id = _span.get_span_context().trace_id
|
|
119
|
+
span_id = _span.get_span_context().span_id
|
|
120
|
+
|
|
121
|
+
# log.debug(
|
|
122
|
+
# "[SPAN] [EXPORT]",
|
|
123
|
+
# trace_id=UUID(int=trace_id).hex,
|
|
124
|
+
# span_id=UUID(int=span_id).hex[-16:],
|
|
125
|
+
# )
|
|
126
|
+
|
|
109
127
|
serialized_spans.append(super().export(_spans))
|
|
110
128
|
|
|
111
129
|
if all(serialized_spans):
|
|
@@ -114,16 +132,48 @@ class OTLPExporter(OTLPSpanExporter):
|
|
|
114
132
|
return SpanExportResult.FAILURE
|
|
115
133
|
|
|
116
134
|
def _export(self, serialized_data: bytes, timeout_sec: Optional[float] = None):
|
|
117
|
-
|
|
135
|
+
try:
|
|
136
|
+
credentials = otlp_context.get().credentials
|
|
137
|
+
|
|
138
|
+
if credentials:
|
|
139
|
+
self._session.headers.update({"Authorization": credentials})
|
|
140
|
+
|
|
141
|
+
def __export():
|
|
142
|
+
with suppress():
|
|
143
|
+
resp = None
|
|
144
|
+
if timeout_sec is not None:
|
|
145
|
+
resp = super(OTLPExporter, self)._export(
|
|
146
|
+
serialized_data,
|
|
147
|
+
timeout_sec,
|
|
148
|
+
)
|
|
149
|
+
else:
|
|
150
|
+
resp = super(OTLPExporter, self)._export(
|
|
151
|
+
serialized_data,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# log.debug(
|
|
155
|
+
# "[SPAN] [_EXPORT]",
|
|
156
|
+
# data=serialized_data,
|
|
157
|
+
# resp=resp,
|
|
158
|
+
# )
|
|
159
|
+
|
|
160
|
+
if _ASYNC_EXPORT is True:
|
|
161
|
+
# log.debug("[SPAN] [ASYNC.X]", credentials=(credentials is not None))
|
|
162
|
+
thread = Thread(target=__export, daemon=False)
|
|
163
|
+
thread.start()
|
|
164
|
+
else:
|
|
165
|
+
# log.debug("[SPAN] [ SYNC.X]", credentials=(credentials is not None))
|
|
166
|
+
return __export()
|
|
118
167
|
|
|
119
|
-
|
|
120
|
-
|
|
168
|
+
except Exception as e:
|
|
169
|
+
log.error(f"Export failed with error: {e}", exc_info=True)
|
|
121
170
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
171
|
+
finally:
|
|
172
|
+
|
|
173
|
+
class Response:
|
|
174
|
+
ok = True
|
|
175
|
+
|
|
176
|
+
return Response()
|
|
127
177
|
|
|
128
178
|
|
|
129
179
|
ConsoleExporter = ConsoleSpanExporter
|
agenta/sdk/tracing/inline.py
CHANGED
|
@@ -532,11 +532,11 @@ from json import loads, JSONDecodeError, dumps
|
|
|
532
532
|
from copy import copy
|
|
533
533
|
|
|
534
534
|
|
|
535
|
-
def
|
|
535
|
+
def _unmarshall_attributes(
|
|
536
536
|
marshalled: Dict[str, Any],
|
|
537
537
|
) -> Dict[str, Any]:
|
|
538
538
|
"""
|
|
539
|
-
|
|
539
|
+
Unmarshalls a dictionary of marshalled attributes into a nested dictionary
|
|
540
540
|
|
|
541
541
|
Example:
|
|
542
542
|
marshalled = {
|
|
@@ -566,42 +566,34 @@ def _unmarshal_attributes(
|
|
|
566
566
|
|
|
567
567
|
for key, value in marshalled.items():
|
|
568
568
|
keys = key.split(".")
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
if
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
569
|
+
current = unmarshalled
|
|
570
|
+
|
|
571
|
+
for i, key in enumerate(keys):
|
|
572
|
+
is_last = i == len(keys) - 1
|
|
573
|
+
next_key = keys[i + 1] if not is_last else None
|
|
574
|
+
is_index = key.isdigit()
|
|
575
|
+
key = int(key) if is_index else key
|
|
576
|
+
|
|
577
|
+
if is_last:
|
|
578
|
+
if isinstance(current, list) and isinstance(key, int):
|
|
579
|
+
while len(current) <= key:
|
|
580
|
+
current.append(None)
|
|
581
|
+
current[key] = value
|
|
582
|
+
elif isinstance(current, dict):
|
|
583
|
+
current[key] = value
|
|
584
584
|
else:
|
|
585
|
-
if
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
while len(level) <= last_key:
|
|
599
|
-
level.append(None)
|
|
600
|
-
|
|
601
|
-
level[last_key] = value
|
|
602
|
-
|
|
603
|
-
else:
|
|
604
|
-
level[last_key] = value
|
|
585
|
+
next_is_index = next_key.isdigit() if next_key else False
|
|
586
|
+
|
|
587
|
+
if isinstance(current, list) and isinstance(key, int):
|
|
588
|
+
while len(current) <= key:
|
|
589
|
+
current.append([] if next_is_index else {})
|
|
590
|
+
if current[key] is None:
|
|
591
|
+
current[key] = [] if next_is_index else {}
|
|
592
|
+
current = current[key]
|
|
593
|
+
elif isinstance(current, dict):
|
|
594
|
+
if key not in current:
|
|
595
|
+
current[key] = [] if next_is_index else {}
|
|
596
|
+
current = current[key]
|
|
605
597
|
|
|
606
598
|
return unmarshalled
|
|
607
599
|
|
|
@@ -750,7 +742,7 @@ def _parse_from_attributes(
|
|
|
750
742
|
for key in _data.keys():
|
|
751
743
|
del otel_span_dto.attributes[_encode_key("data", key)]
|
|
752
744
|
|
|
753
|
-
# _data =
|
|
745
|
+
# _data = _unmarshall_attributes(_data)
|
|
754
746
|
_data = _data if _data else None
|
|
755
747
|
|
|
756
748
|
# METRICS
|
|
@@ -759,7 +751,7 @@ def _parse_from_attributes(
|
|
|
759
751
|
for key in _metrics.keys():
|
|
760
752
|
del otel_span_dto.attributes[_encode_key("metrics", key)]
|
|
761
753
|
|
|
762
|
-
# _metrics =
|
|
754
|
+
# _metrics = _unmarshall_attributes(_metrics)
|
|
763
755
|
_metrics = _metrics if _metrics else None
|
|
764
756
|
|
|
765
757
|
# META
|
|
@@ -768,7 +760,7 @@ def _parse_from_attributes(
|
|
|
768
760
|
for key in _meta.keys():
|
|
769
761
|
del otel_span_dto.attributes[_encode_key("meta", key)]
|
|
770
762
|
|
|
771
|
-
# _meta =
|
|
763
|
+
# _meta = _unmarshall_attributes(_meta)
|
|
772
764
|
_meta = _meta if _meta else None
|
|
773
765
|
|
|
774
766
|
# TAGS
|
|
@@ -904,7 +896,7 @@ def parse_to_agenta_span_dto(
|
|
|
904
896
|
) -> SpanDTO:
|
|
905
897
|
# DATA
|
|
906
898
|
if span_dto.data:
|
|
907
|
-
span_dto.data =
|
|
899
|
+
span_dto.data = _unmarshall_attributes(span_dto.data)
|
|
908
900
|
|
|
909
901
|
if "outputs" in span_dto.data:
|
|
910
902
|
if "__default__" in span_dto.data["outputs"]:
|
|
@@ -912,19 +904,19 @@ def parse_to_agenta_span_dto(
|
|
|
912
904
|
|
|
913
905
|
# METRICS
|
|
914
906
|
if span_dto.metrics:
|
|
915
|
-
span_dto.metrics =
|
|
907
|
+
span_dto.metrics = _unmarshall_attributes(span_dto.metrics)
|
|
916
908
|
|
|
917
909
|
# META
|
|
918
910
|
if span_dto.meta:
|
|
919
|
-
span_dto.meta =
|
|
911
|
+
span_dto.meta = _unmarshall_attributes(span_dto.meta)
|
|
920
912
|
|
|
921
913
|
# TAGS
|
|
922
914
|
if span_dto.tags:
|
|
923
|
-
span_dto.tags =
|
|
915
|
+
span_dto.tags = _unmarshall_attributes(span_dto.tags)
|
|
924
916
|
|
|
925
917
|
# REFS
|
|
926
918
|
if span_dto.refs:
|
|
927
|
-
span_dto.refs =
|
|
919
|
+
span_dto.refs = _unmarshall_attributes(span_dto.refs)
|
|
928
920
|
|
|
929
921
|
if isinstance(span_dto.links, list):
|
|
930
922
|
for link in span_dto.links:
|
agenta/sdk/tracing/processors.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from typing import Optional, Dict, List
|
|
2
2
|
from threading import Lock
|
|
3
|
+
from json import dumps
|
|
4
|
+
from uuid import UUID
|
|
3
5
|
|
|
4
6
|
from opentelemetry.baggage import get_all as get_baggage
|
|
5
7
|
from opentelemetry.context import Context
|
|
@@ -9,10 +11,13 @@ from opentelemetry.sdk.trace.export import (
|
|
|
9
11
|
ReadableSpan,
|
|
10
12
|
BatchSpanProcessor,
|
|
11
13
|
)
|
|
14
|
+
from opentelemetry.trace import SpanContext
|
|
12
15
|
|
|
13
16
|
from agenta.sdk.utils.logging import get_module_logger
|
|
14
17
|
from agenta.sdk.tracing.conventions import Reference
|
|
15
18
|
|
|
19
|
+
from agenta.sdk.contexts.tracing import TracingContext
|
|
20
|
+
|
|
16
21
|
log = get_module_logger(__name__)
|
|
17
22
|
|
|
18
23
|
|
|
@@ -50,6 +55,15 @@ class TraceProcessor(SpanProcessor):
|
|
|
50
55
|
span: Span,
|
|
51
56
|
parent_context: Optional[Context] = None,
|
|
52
57
|
) -> None:
|
|
58
|
+
trace_id = span.context.trace_id
|
|
59
|
+
span_id = span.context.span_id
|
|
60
|
+
|
|
61
|
+
# log.debug(
|
|
62
|
+
# "[SPAN] [START] ",
|
|
63
|
+
# trace_id=UUID(int=trace_id).hex,
|
|
64
|
+
# span_id=UUID(int=span_id).hex[-16:],
|
|
65
|
+
# )
|
|
66
|
+
|
|
53
67
|
for key in self.references.keys():
|
|
54
68
|
span.set_attribute(f"ag.refs.{key}", self.references[key])
|
|
55
69
|
|
|
@@ -61,6 +75,83 @@ class TraceProcessor(SpanProcessor):
|
|
|
61
75
|
if _key in [_.value for _ in Reference.__members__.values()]:
|
|
62
76
|
span.set_attribute(key, baggage[key])
|
|
63
77
|
|
|
78
|
+
context = TracingContext.get()
|
|
79
|
+
|
|
80
|
+
trace_type = span.attributes.get("trace_type") if span.attributes else None
|
|
81
|
+
|
|
82
|
+
context.annotate = (
|
|
83
|
+
context.annotate
|
|
84
|
+
or (context.type == "annotation")
|
|
85
|
+
or (trace_type == "annotation")
|
|
86
|
+
)
|
|
87
|
+
context.type = (
|
|
88
|
+
(str(trace_type) if trace_type else None)
|
|
89
|
+
or context.type
|
|
90
|
+
or ("annotation" if context.annotate else "invocation")
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
span.set_attribute("ag.type.tree", context.type)
|
|
94
|
+
|
|
95
|
+
if context.flags:
|
|
96
|
+
for key in context.flags.keys():
|
|
97
|
+
span.set_attribute(f"ag.flags.{key}", context.flags[key])
|
|
98
|
+
# if context.tags:
|
|
99
|
+
# for key in context.tags.keys():
|
|
100
|
+
# span.set_attribute(f"ag.tags.{key}", context.tags[key])
|
|
101
|
+
# if context.meta:
|
|
102
|
+
# span.set_attribute(f"ag.meta.", dumps(context.meta))
|
|
103
|
+
|
|
104
|
+
# --- DISTRIBUTED
|
|
105
|
+
if not self.inline:
|
|
106
|
+
if context.links:
|
|
107
|
+
for key, link in context.links.items():
|
|
108
|
+
try:
|
|
109
|
+
link = link.model_dump(mode="json", exclude_none=True)
|
|
110
|
+
except: # pylint: disable=bare-except
|
|
111
|
+
pass
|
|
112
|
+
if not isinstance(link, dict):
|
|
113
|
+
continue
|
|
114
|
+
if not link.get("trace_id") or not link.get("span_id"):
|
|
115
|
+
continue
|
|
116
|
+
|
|
117
|
+
span.add_link(
|
|
118
|
+
context=SpanContext(
|
|
119
|
+
trace_id=int(str(link.get("trace_id")), 16),
|
|
120
|
+
span_id=int(str(link.get("span_id")), 16),
|
|
121
|
+
is_remote=True,
|
|
122
|
+
),
|
|
123
|
+
attributes=dict(
|
|
124
|
+
key=str(key),
|
|
125
|
+
),
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
if context.references:
|
|
129
|
+
for key, ref in context.references.items():
|
|
130
|
+
try:
|
|
131
|
+
ref = ref.model_dump(mode="json", exclude_none=True)
|
|
132
|
+
except: # pylint: disable=bare-except
|
|
133
|
+
pass
|
|
134
|
+
if not isinstance(ref, dict):
|
|
135
|
+
continue
|
|
136
|
+
if not ref.get("id") and not ref.get("slug") and not ref.get("version"):
|
|
137
|
+
continue
|
|
138
|
+
|
|
139
|
+
if ref.get("id"):
|
|
140
|
+
span.set_attribute(
|
|
141
|
+
f"ag.refs.{key}.id",
|
|
142
|
+
str(ref.get("id")),
|
|
143
|
+
)
|
|
144
|
+
if ref.get("slug"):
|
|
145
|
+
span.set_attribute(
|
|
146
|
+
f"ag.refs.{key}.slug",
|
|
147
|
+
str(ref.get("slug")),
|
|
148
|
+
)
|
|
149
|
+
if ref.get("version"):
|
|
150
|
+
span.set_attribute(
|
|
151
|
+
f"ag.refs.{key}.version",
|
|
152
|
+
str(ref.get("version")),
|
|
153
|
+
)
|
|
154
|
+
|
|
64
155
|
trace_id = span.context.trace_id
|
|
65
156
|
span_id = span.context.span_id
|
|
66
157
|
|
|
@@ -74,6 +165,12 @@ class TraceProcessor(SpanProcessor):
|
|
|
74
165
|
trace_id = span.context.trace_id
|
|
75
166
|
span_id = span.context.span_id
|
|
76
167
|
|
|
168
|
+
# log.debug(
|
|
169
|
+
# "[SPAN] [END] ",
|
|
170
|
+
# trace_id=UUID(int=trace_id).hex,
|
|
171
|
+
# span_id=UUID(int=span_id).hex[-16:],
|
|
172
|
+
# )
|
|
173
|
+
|
|
77
174
|
self._spans.setdefault(trace_id, []).append(span)
|
|
78
175
|
self._registry.setdefault(trace_id, {})
|
|
79
176
|
self._registry[trace_id].pop(span_id, None)
|
|
@@ -6,6 +6,8 @@ from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapProp
|
|
|
6
6
|
from opentelemetry.baggage import set_baggage
|
|
7
7
|
from opentelemetry.context import get_current
|
|
8
8
|
|
|
9
|
+
from agenta.sdk.contexts.tracing import TracingContext
|
|
10
|
+
|
|
9
11
|
import agenta as ag
|
|
10
12
|
|
|
11
13
|
|
|
@@ -72,7 +74,7 @@ def inject(
|
|
|
72
74
|
|
|
73
75
|
_context = get_current()
|
|
74
76
|
|
|
75
|
-
ctx =
|
|
77
|
+
ctx = TracingContext.get()
|
|
76
78
|
|
|
77
79
|
# --- Inject traceparent --- #
|
|
78
80
|
try:
|
agenta/sdk/tracing/spans.py
CHANGED
agenta/sdk/tracing/tracing.py
CHANGED
|
@@ -52,8 +52,6 @@ class Link(BaseModel):
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
class Tracing(metaclass=Singleton):
|
|
55
|
-
VERSION = "0.1.0"
|
|
56
|
-
|
|
57
55
|
Status = Status
|
|
58
56
|
StatusCode = StatusCode
|
|
59
57
|
|
|
@@ -101,19 +99,6 @@ class Tracing(metaclass=Singleton):
|
|
|
101
99
|
resource=Resource(attributes={"service.name": "agenta-sdk"})
|
|
102
100
|
)
|
|
103
101
|
|
|
104
|
-
# --- INLINE
|
|
105
|
-
if inline:
|
|
106
|
-
# TRACE PROCESSORS -- INLINE
|
|
107
|
-
self.inline = TraceProcessor(
|
|
108
|
-
InlineExporter(
|
|
109
|
-
registry=self.inline_spans,
|
|
110
|
-
),
|
|
111
|
-
references=self.references,
|
|
112
|
-
inline=inline,
|
|
113
|
-
)
|
|
114
|
-
self.tracer_provider.add_span_processor(self.inline)
|
|
115
|
-
# --- INLINE
|
|
116
|
-
|
|
117
102
|
# TRACE PROCESSORS -- OTLP
|
|
118
103
|
try:
|
|
119
104
|
log.info("Agenta - OLTP URL: %s", self.otlp_url)
|
|
@@ -131,6 +116,19 @@ class Tracing(metaclass=Singleton):
|
|
|
131
116
|
except: # pylint: disable=bare-except
|
|
132
117
|
log.warning("Agenta - OLTP unreachable, skipping exports.")
|
|
133
118
|
|
|
119
|
+
# --- INLINE
|
|
120
|
+
if inline:
|
|
121
|
+
# TRACE PROCESSORS -- INLINE
|
|
122
|
+
self.inline = TraceProcessor(
|
|
123
|
+
InlineExporter(
|
|
124
|
+
registry=self.inline_spans,
|
|
125
|
+
),
|
|
126
|
+
references=self.references,
|
|
127
|
+
inline=inline,
|
|
128
|
+
)
|
|
129
|
+
self.tracer_provider.add_span_processor(self.inline)
|
|
130
|
+
# --- INLINE
|
|
131
|
+
|
|
134
132
|
# GLOBAL TRACER PROVIDER -- INSTRUMENTATION LIBRARIES
|
|
135
133
|
set_tracer_provider(self.tracer_provider)
|
|
136
134
|
# TRACER
|