agenta 0.30.0a1__py3-none-any.whl → 0.30.0a3__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.

Potentially problematic release.


This version of agenta might be problematic. Click here for more details.

Files changed (71) hide show
  1. agenta/__init__.py +1 -0
  2. agenta/client/backend/__init__.py +32 -3
  3. agenta/client/backend/access_control/__init__.py +1 -0
  4. agenta/client/backend/access_control/client.py +167 -0
  5. agenta/client/backend/apps/client.py +70 -10
  6. agenta/client/backend/client.py +61 -45
  7. agenta/client/backend/configs/client.py +6 -0
  8. agenta/client/backend/containers/client.py +6 -0
  9. agenta/client/backend/core/file.py +13 -8
  10. agenta/client/backend/environments/client.py +6 -0
  11. agenta/client/backend/evaluations/client.py +14 -1
  12. agenta/client/backend/evaluators/client.py +24 -0
  13. agenta/client/backend/observability/client.py +22 -16
  14. agenta/client/backend/observability_v_1/__init__.py +2 -2
  15. agenta/client/backend/observability_v_1/client.py +203 -0
  16. agenta/client/backend/observability_v_1/types/__init__.py +2 -1
  17. agenta/client/backend/observability_v_1/types/format.py +1 -1
  18. agenta/client/backend/observability_v_1/types/query_analytics_response.py +7 -0
  19. agenta/client/backend/scopes/__init__.py +1 -0
  20. agenta/client/backend/scopes/client.py +114 -0
  21. agenta/client/backend/testsets/client.py +305 -121
  22. agenta/client/backend/types/__init__.py +24 -2
  23. agenta/client/backend/types/analytics_response.py +24 -0
  24. agenta/client/backend/types/app.py +2 -1
  25. agenta/client/backend/types/body_import_testset.py +0 -1
  26. agenta/client/backend/types/bucket_dto.py +26 -0
  27. agenta/client/backend/types/header_dto.py +22 -0
  28. agenta/client/backend/types/legacy_analytics_response.py +29 -0
  29. agenta/client/backend/types/legacy_data_point.py +27 -0
  30. agenta/client/backend/types/metrics_dto.py +24 -0
  31. agenta/client/backend/types/permission.py +1 -0
  32. agenta/client/backend/types/projects_response.py +28 -0
  33. agenta/client/backend/types/provider_key_dto.py +23 -0
  34. agenta/client/backend/types/provider_kind.py +21 -0
  35. agenta/client/backend/types/secret_dto.py +24 -0
  36. agenta/client/backend/types/secret_kind.py +5 -0
  37. agenta/client/backend/types/secret_response_dto.py +27 -0
  38. agenta/client/backend/variants/client.py +66 -0
  39. agenta/client/backend/vault/__init__.py +1 -0
  40. agenta/client/backend/vault/client.py +685 -0
  41. agenta/client/client.py +1 -1
  42. agenta/sdk/__init__.py +1 -0
  43. agenta/sdk/agenta_init.py +47 -118
  44. agenta/sdk/assets.py +57 -46
  45. agenta/sdk/context/exporting.py +25 -0
  46. agenta/sdk/context/routing.py +12 -12
  47. agenta/sdk/context/tracing.py +26 -1
  48. agenta/sdk/decorators/routing.py +272 -267
  49. agenta/sdk/decorators/tracing.py +53 -31
  50. agenta/sdk/managers/config.py +8 -118
  51. agenta/sdk/managers/secrets.py +38 -0
  52. agenta/sdk/middleware/auth.py +128 -93
  53. agenta/sdk/middleware/cache.py +4 -0
  54. agenta/sdk/middleware/config.py +254 -0
  55. agenta/sdk/middleware/cors.py +27 -0
  56. agenta/sdk/middleware/otel.py +40 -0
  57. agenta/sdk/middleware/vault.py +158 -0
  58. agenta/sdk/tracing/exporters.py +40 -2
  59. agenta/sdk/tracing/inline.py +2 -2
  60. agenta/sdk/tracing/processors.py +11 -3
  61. agenta/sdk/tracing/tracing.py +14 -12
  62. agenta/sdk/utils/constants.py +1 -0
  63. agenta/sdk/utils/exceptions.py +20 -19
  64. agenta/sdk/utils/globals.py +4 -8
  65. agenta/sdk/utils/timing.py +58 -0
  66. {agenta-0.30.0a1.dist-info → agenta-0.30.0a3.dist-info}/METADATA +3 -2
  67. {agenta-0.30.0a1.dist-info → agenta-0.30.0a3.dist-info}/RECORD +69 -44
  68. {agenta-0.30.0a1.dist-info → agenta-0.30.0a3.dist-info}/WHEEL +1 -1
  69. agenta/client/backend/types/lm_providers_enum.py +0 -21
  70. agenta/sdk/tracing/context.py +0 -24
  71. {agenta-0.30.0a1.dist-info → agenta-0.30.0a3.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,254 @@
1
+ from typing import Callable, Optional, Tuple, Dict
2
+
3
+ from os import getenv
4
+ from json import dumps
5
+
6
+ from pydantic import BaseModel
7
+
8
+ from starlette.middleware.base import BaseHTTPMiddleware
9
+ from fastapi import Request, FastAPI
10
+
11
+ import httpx
12
+
13
+ from agenta.sdk.middleware.cache import TTLLRUCache, CACHE_CAPACITY, CACHE_TTL
14
+ from agenta.sdk.utils.constants import TRUTHY
15
+ from agenta.sdk.utils.exceptions import suppress
16
+
17
+ import agenta as ag
18
+
19
+
20
+ _CACHE_ENABLED = getenv("AGENTA_MIDDLEWARE_CACHE_ENABLED", "true").lower() in TRUTHY
21
+
22
+ _cache = TTLLRUCache(capacity=CACHE_CAPACITY, ttl=CACHE_TTL)
23
+
24
+
25
+ class Reference(BaseModel):
26
+ id: Optional[str] = None
27
+ slug: Optional[str] = None
28
+ version: Optional[str] = None
29
+
30
+
31
+ class ConfigMiddleware(BaseHTTPMiddleware):
32
+ def __init__(self, app: FastAPI):
33
+ super().__init__(app)
34
+
35
+ self.host = ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.host
36
+ self.application_id = ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.app_id
37
+
38
+ async def dispatch(
39
+ self,
40
+ request: Request,
41
+ call_next: Callable,
42
+ ):
43
+ request.state.config = {}
44
+
45
+ with suppress():
46
+ parameters, references = await self._get_config(request)
47
+
48
+ request.state.config = {
49
+ "parameters": parameters,
50
+ "references": references,
51
+ }
52
+
53
+ return await call_next(request)
54
+
55
+ # @atimeit
56
+ async def _get_config(self, request: Request) -> Optional[Tuple[Dict, Dict]]:
57
+ credentials = request.state.auth.get("credentials")
58
+
59
+ headers = None
60
+ if credentials:
61
+ headers = {"Authorization": credentials}
62
+
63
+ application_ref = await self._parse_application_ref(request)
64
+ variant_ref = await self._parse_variant_ref(request)
65
+ environment_ref = await self._parse_environment_ref(request)
66
+
67
+ refs = {}
68
+ if application_ref:
69
+ refs["application_ref"] = application_ref.model_dump()
70
+ if variant_ref:
71
+ refs["variant_ref"] = variant_ref.model_dump()
72
+ if environment_ref:
73
+ refs["environment_ref"] = environment_ref.model_dump()
74
+
75
+ if not refs:
76
+ return None, None
77
+
78
+ _hash = dumps(
79
+ {
80
+ "headers": headers,
81
+ "refs": refs,
82
+ },
83
+ sort_keys=True,
84
+ )
85
+
86
+ if _CACHE_ENABLED:
87
+ config_cache = _cache.get(_hash)
88
+
89
+ if config_cache:
90
+ parameters = config_cache.get("parameters")
91
+ references = config_cache.get("references")
92
+
93
+ return parameters, references
94
+
95
+ config = None
96
+ async with httpx.AsyncClient() as client:
97
+ response = await client.post(
98
+ f"{self.host}/api/variants/configs/fetch",
99
+ headers=headers,
100
+ json=refs,
101
+ )
102
+
103
+ if response.status_code != 200:
104
+ return None, None
105
+
106
+ config = response.json()
107
+
108
+ if not config:
109
+ _cache.put(_hash, {"parameters": None, "references": None})
110
+
111
+ return None, None
112
+
113
+ parameters = config.get("params")
114
+
115
+ references = {}
116
+
117
+ for ref_key in ["application_ref", "variant_ref", "environment_ref"]:
118
+ refs = config.get(ref_key)
119
+ ref_prefix = ref_key.split("_", maxsplit=1)[0]
120
+
121
+ for ref_part_key in ["id", "slug", "version"]:
122
+ ref_part = refs.get(ref_part_key)
123
+
124
+ if ref_part:
125
+ references[ref_prefix + "." + ref_part_key] = ref_part
126
+
127
+ _cache.put(_hash, {"parameters": parameters, "references": references})
128
+
129
+ return parameters, references
130
+
131
+ async def _parse_application_ref(
132
+ self,
133
+ request: Request,
134
+ ) -> Optional[Reference]:
135
+ baggage = request.state.otel.get("baggage") if request.state.otel else {}
136
+
137
+ body = {}
138
+ try:
139
+ body = await request.json()
140
+ except: # pylint: disable=bare-except
141
+ pass
142
+
143
+ application_id = (
144
+ # CLEANEST
145
+ baggage.get("application_id")
146
+ # ALTERNATIVE
147
+ or request.query_params.get("application_id")
148
+ # LEGACY
149
+ or request.query_params.get("app_id")
150
+ or self.application_id
151
+ )
152
+ application_slug = (
153
+ # CLEANEST
154
+ baggage.get("application_slug")
155
+ # ALTERNATIVE
156
+ or request.query_params.get("application_slug")
157
+ # LEGACY
158
+ or request.query_params.get("app_slug")
159
+ or body.get("app")
160
+ )
161
+
162
+ if not any([application_id, application_slug]):
163
+ return None
164
+
165
+ return Reference(
166
+ id=application_id,
167
+ slug=application_slug,
168
+ )
169
+
170
+ async def _parse_variant_ref(
171
+ self,
172
+ request: Request,
173
+ ) -> Optional[Reference]:
174
+ baggage = request.state.otel.get("baggage") if request.state.otel else {}
175
+
176
+ body = {}
177
+ try:
178
+ body = await request.json()
179
+ except: # pylint: disable=bare-except
180
+ pass
181
+
182
+ variant_id = (
183
+ # CLEANEST
184
+ baggage.get("variant_id")
185
+ # ALTERNATIVE
186
+ or request.query_params.get("variant_id")
187
+ )
188
+ variant_slug = (
189
+ # CLEANEST
190
+ baggage.get("variant_slug")
191
+ # ALTERNATIVE
192
+ or request.query_params.get("variant_slug")
193
+ # LEGACY
194
+ or request.query_params.get("config")
195
+ or body.get("config")
196
+ )
197
+ variant_version = (
198
+ # CLEANEST
199
+ baggage.get("variant_version")
200
+ # ALTERNATIVE
201
+ or request.query_params.get("variant_version")
202
+ )
203
+
204
+ if not any([variant_id, variant_slug, variant_version]):
205
+ return None
206
+
207
+ return Reference(
208
+ id=variant_id,
209
+ slug=variant_slug,
210
+ version=variant_version,
211
+ )
212
+
213
+ async def _parse_environment_ref(
214
+ self,
215
+ request: Request,
216
+ ) -> Optional[Reference]:
217
+ baggage = request.state.otel.get("baggage") if request.state.otel else {}
218
+
219
+ body = {}
220
+ try:
221
+ body = await request.json()
222
+ except: # pylint: disable=bare-except
223
+ pass
224
+
225
+ environment_id = (
226
+ # CLEANEST
227
+ baggage.get("environment_id")
228
+ # ALTERNATIVE
229
+ or request.query_params.get("environment_id")
230
+ )
231
+ environment_slug = (
232
+ # CLEANEST
233
+ baggage.get("environment_slug")
234
+ # ALTERNATIVE
235
+ or request.query_params.get("environment_slug")
236
+ # LEGACY
237
+ or request.query_params.get("environment")
238
+ or body.get("environment")
239
+ )
240
+ environment_version = (
241
+ # CLEANEST
242
+ baggage.get("environment_version")
243
+ # ALTERNATIVE
244
+ or request.query_params.get("environment_version")
245
+ )
246
+
247
+ if not any([environment_id, environment_slug, environment_version]):
248
+ return None
249
+
250
+ return Reference(
251
+ id=environment_id,
252
+ slug=environment_slug,
253
+ version=environment_version,
254
+ )
@@ -0,0 +1,27 @@
1
+ from os import getenv
2
+
3
+ from starlette.types import ASGIApp, Receive, Scope, Send
4
+ from fastapi.middleware.cors import CORSMiddleware as _CORSMiddleware
5
+
6
+ _TRUTHY = {"true", "1", "t", "y", "yes", "on", "enable", "enabled"}
7
+ _USE_CORS = getenv("AGENTA_USE_CORS", "enable").lower() in _TRUTHY
8
+
9
+
10
+ class CORSMiddleware(_CORSMiddleware):
11
+ def __init__(self, app: ASGIApp):
12
+ if _USE_CORS:
13
+ super().__init__(
14
+ app=app,
15
+ allow_origins=["*"],
16
+ allow_methods=["*"],
17
+ allow_headers=["*"],
18
+ allow_credentials=True,
19
+ expose_headers=None,
20
+ max_age=None,
21
+ )
22
+
23
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
24
+ if _USE_CORS:
25
+ return await super().__call__(scope, receive, send)
26
+
27
+ return await self.app(scope, receive, send)
@@ -0,0 +1,40 @@
1
+ from typing import Callable
2
+
3
+ from starlette.middleware.base import BaseHTTPMiddleware
4
+ from fastapi import Request, FastAPI
5
+
6
+ from opentelemetry.baggage.propagation import W3CBaggagePropagator
7
+
8
+ from agenta.sdk.utils.exceptions import suppress
9
+
10
+
11
+ class OTelMiddleware(BaseHTTPMiddleware):
12
+ def __init__(self, app: FastAPI):
13
+ super().__init__(app)
14
+
15
+ async def dispatch(self, request: Request, call_next: Callable):
16
+ request.state.otel = {}
17
+
18
+ with suppress():
19
+ baggage = await self._get_baggage(request)
20
+
21
+ request.state.otel = {"baggage": baggage}
22
+
23
+ return await call_next(request)
24
+
25
+ async def _get_baggage(
26
+ self,
27
+ request,
28
+ ):
29
+ _baggage = {"baggage": request.headers.get("Baggage", "")}
30
+
31
+ context = W3CBaggagePropagator().extract(_baggage)
32
+
33
+ baggage = {}
34
+
35
+ if context:
36
+ for partial in context.values():
37
+ for key, value in partial.items():
38
+ baggage[key] = value
39
+
40
+ return baggage
@@ -0,0 +1,158 @@
1
+ from os import getenv
2
+ from json import dumps
3
+ from typing import Callable, Dict, Optional, List, Any
4
+
5
+ import httpx
6
+ from fastapi import FastAPI, Request
7
+ from starlette.middleware.base import BaseHTTPMiddleware
8
+
9
+ from agenta.sdk.utils.constants import TRUTHY
10
+ from agenta.client.backend.types.provider_kind import ProviderKind
11
+ from agenta.sdk.utils.exceptions import suppress, display_exception
12
+ from agenta.client.backend.types.secret_dto import SecretDto as SecretDTO
13
+ from agenta.client.backend.types.provider_key_dto import (
14
+ ProviderKeyDto as ProviderKeyDTO,
15
+ )
16
+ from agenta.sdk.middleware.cache import TTLLRUCache, CACHE_CAPACITY, CACHE_TTL
17
+
18
+ import agenta as ag
19
+
20
+
21
+ # ProviderKind (agenta.client.backend.types.provider_kind import ProviderKind) defines a type hint that allows \
22
+ # for a fixed set of string literals representing various provider names, alongside `typing.Any`.
23
+ PROVIDER_KINDS = []
24
+
25
+ # Rationale behind the following:
26
+ # -------------------------------
27
+ # You cannot loop directly over the values in `typing.Literal` because:
28
+ # - `Literal` is not iterable.
29
+ # - `ProviderKind.__args__` includes `Literal` and `Any`, but the actual string values
30
+ # are nested within the `Literal`'s own `__args__` attribute.
31
+
32
+ # To solve this, we programmatically extract the values from `Literal` while retaining
33
+ # the structure of ProviderKind. This ensures:
34
+ # 1. We don't modify the original `ProviderKind` type definition.
35
+ # 2. We dynamically access the literal values for use at runtime when necessary.
36
+ for arg in ProviderKind.__args__: # type: ignore
37
+ if hasattr(arg, "__args__"):
38
+ PROVIDER_KINDS.extend(arg.__args__)
39
+
40
+
41
+ _CACHE_ENABLED = getenv("AGENTA_MIDDLEWARE_CACHE_ENABLED", "true").lower() in TRUTHY
42
+
43
+ _cache = TTLLRUCache(capacity=CACHE_CAPACITY, ttl=CACHE_TTL)
44
+
45
+
46
+ class VaultMiddleware(BaseHTTPMiddleware):
47
+ def __init__(self, app: FastAPI):
48
+ super().__init__(app)
49
+
50
+ self.host = ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.host
51
+
52
+ def _transform_secrets_response_to_secret_dto(
53
+ self, secrets_list: List[Dict[str, Any]]
54
+ ) -> List[Dict[str, Any]]:
55
+ secrets_dto_dict = [
56
+ {
57
+ "kind": secret.get("secret", {}).get("kind"),
58
+ "data": secret.get("secret", {}).get("data", {}),
59
+ }
60
+ for secret in secrets_list
61
+ ]
62
+ return secrets_dto_dict
63
+
64
+ async def dispatch(
65
+ self,
66
+ request: Request,
67
+ call_next: Callable,
68
+ ):
69
+ request.state.vault = {}
70
+
71
+ with suppress():
72
+ secrets = await self._get_secrets(request)
73
+
74
+ request.state.vault = {"secrets": secrets}
75
+
76
+ return await call_next(request)
77
+
78
+ async def _get_secrets(self, request: Request) -> Optional[Dict]:
79
+ credentials = request.state.auth.get("credentials")
80
+
81
+ headers = None
82
+ if credentials:
83
+ headers = {"Authorization": credentials}
84
+
85
+ _hash = dumps(
86
+ {
87
+ "headers": headers,
88
+ },
89
+ sort_keys=True,
90
+ )
91
+
92
+ if _CACHE_ENABLED:
93
+ secrets_cache = _cache.get(_hash)
94
+
95
+ if secrets_cache:
96
+ secrets = secrets_cache.get("secrets")
97
+
98
+ return secrets
99
+
100
+ local_secrets: List[SecretDTO] = []
101
+
102
+ try:
103
+ for provider_kind in PROVIDER_KINDS:
104
+ provider = provider_kind
105
+ key_name = f"{provider.upper()}_API_KEY"
106
+ key = getenv(key_name)
107
+
108
+ if not key:
109
+ continue
110
+
111
+ secret = SecretDTO( # 'kind' attribute in SecretDTO defaults to 'provider_kind'
112
+ data=ProviderKeyDTO(
113
+ provider=provider,
114
+ key=key,
115
+ ),
116
+ )
117
+
118
+ local_secrets.append(secret.model_dump())
119
+ except: # pylint: disable=bare-except
120
+ display_exception("Vault: Local Secrets Exception")
121
+
122
+ vault_secrets: List[SecretDTO] = []
123
+
124
+ try:
125
+ async with httpx.AsyncClient() as client:
126
+ response = await client.get(
127
+ f"{self.host}/api/vault/v1/secrets",
128
+ headers=headers,
129
+ )
130
+
131
+ if response.status_code != 200:
132
+ vault_secrets = []
133
+
134
+ else:
135
+ secrets = response.json()
136
+ vault_secrets = self._transform_secrets_response_to_secret_dto(
137
+ secrets
138
+ )
139
+ except: # pylint: disable=bare-except
140
+ display_exception("Vault: Vault Secrets Exception")
141
+
142
+ merged_secrets = {}
143
+
144
+ if local_secrets:
145
+ for secret in local_secrets:
146
+ provider = secret["data"]["provider"]
147
+ merged_secrets[provider] = secret
148
+
149
+ if vault_secrets:
150
+ for secret in vault_secrets:
151
+ provider = secret["data"]["provider"]
152
+ merged_secrets[provider] = secret
153
+
154
+ secrets = list(merged_secrets.values())
155
+
156
+ _cache.put(_hash, {"secrets": secrets})
157
+
158
+ return secrets
@@ -9,6 +9,11 @@ from opentelemetry.sdk.trace.export import (
9
9
  )
10
10
 
11
11
  from agenta.sdk.utils.exceptions import suppress
12
+ from agenta.sdk.context.exporting import (
13
+ exporting_context_manager,
14
+ exporting_context,
15
+ ExportingContext,
16
+ )
12
17
 
13
18
 
14
19
  class InlineTraceExporter(SpanExporter):
@@ -58,8 +63,41 @@ class InlineTraceExporter(SpanExporter):
58
63
  return trace
59
64
 
60
65
 
61
- OTLPSpanExporter._MAX_RETRY_TIMEOUT = 2 # pylint: disable=protected-access
66
+ class OTLPExporter(OTLPSpanExporter):
67
+ _MAX_RETRY_TIMEOUT = 2
68
+
69
+ def __init__(self, *args, credentials: Dict[int, str] = None, **kwargs):
70
+ super().__init__(*args, **kwargs)
71
+
72
+ self.credentials = credentials
73
+
74
+ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
75
+ credentials = None
76
+
77
+ if self.credentials:
78
+ trace_ids = set(span.get_span_context().trace_id for span in spans)
79
+
80
+ if len(trace_ids) == 1:
81
+ trace_id = trace_ids.pop()
82
+
83
+ if trace_id in self.credentials:
84
+ credentials = self.credentials.pop(trace_id)
85
+
86
+ with exporting_context_manager(
87
+ context=ExportingContext(
88
+ credentials=credentials,
89
+ )
90
+ ):
91
+ return super().export(spans)
92
+
93
+ def _export(self, serialized_data: bytes):
94
+ credentials = exporting_context.get().credentials
95
+
96
+ if credentials:
97
+ self._session.headers.update({"Authorization": credentials})
98
+
99
+ return super()._export(serialized_data)
100
+
62
101
 
63
102
  ConsoleExporter = ConsoleSpanExporter
64
103
  InlineExporter = InlineTraceExporter
65
- OTLPExporter = OTLPSpanExporter
@@ -101,8 +101,8 @@ class NodeDTO(BaseModel):
101
101
  Data = Dict[str, Any]
102
102
  Metrics = Dict[str, Any]
103
103
  Metadata = Dict[str, Any]
104
- Tags = Dict[str, str]
105
- Refs = Dict[str, str]
104
+ Tags = Dict[str, Any]
105
+ Refs = Dict[str, Any]
106
106
 
107
107
 
108
108
  class LinkDTO(BaseModel):
@@ -1,5 +1,6 @@
1
1
  from typing import Optional, Dict, List
2
2
 
3
+ from opentelemetry.baggage import get_all as get_baggage
3
4
  from opentelemetry.context import Context
4
5
  from opentelemetry.sdk.trace import Span
5
6
  from opentelemetry.sdk.trace.export import (
@@ -11,8 +12,7 @@ from opentelemetry.sdk.trace.export import (
11
12
  )
12
13
 
13
14
  from agenta.sdk.utils.logging import log
14
-
15
- # LOAD CONTEXT, HERE !
15
+ from agenta.sdk.tracing.conventions import Reference
16
16
 
17
17
 
18
18
  class TraceProcessor(BatchSpanProcessor):
@@ -43,9 +43,17 @@ class TraceProcessor(BatchSpanProcessor):
43
43
  span: Span,
44
44
  parent_context: Optional[Context] = None,
45
45
  ) -> None:
46
+ baggage = get_baggage(parent_context)
47
+
46
48
  for key in self.references.keys():
47
49
  span.set_attribute(f"ag.refs.{key}", self.references[key])
48
50
 
51
+ for key in baggage.keys():
52
+ if key.startswith("ag.refs."):
53
+ _key = key.replace("ag.refs.", "")
54
+ if _key in [_.value for _ in Reference.__members__.values()]:
55
+ span.set_attribute(key, baggage[key])
56
+
49
57
  if span.context.trace_id not in self._registry:
50
58
  self._registry[span.context.trace_id] = dict()
51
59
 
@@ -89,7 +97,7 @@ class TraceProcessor(BatchSpanProcessor):
89
97
  ret = super().force_flush(timeout_millis)
90
98
 
91
99
  if not ret:
92
- log.warning("Agenta SDK - skipping export due to timeout.")
100
+ log.warning("Agenta - Skipping export due to timeout.")
93
101
 
94
102
  def is_ready(
95
103
  self,
@@ -41,6 +41,8 @@ class Tracing(metaclass=Singleton):
41
41
  self.headers: Dict[str, str] = dict()
42
42
  # REFERENCES
43
43
  self.references: Dict[str, str] = dict()
44
+ # CREDENTIALS
45
+ self.credentials: Dict[int, str] = dict()
44
46
 
45
47
  # TRACER PROVIDER
46
48
  self.tracer_provider: Optional[TracerProvider] = None
@@ -60,13 +62,16 @@ class Tracing(metaclass=Singleton):
60
62
  def configure(
61
63
  self,
62
64
  api_key: Optional[str] = None,
65
+ service_id: Optional[str] = None,
63
66
  # DEPRECATING
64
67
  app_id: Optional[str] = None,
65
68
  ):
66
69
  # HEADERS (OTLP)
67
70
  if api_key:
68
- self.headers["Authorization"] = api_key
71
+ self.headers["Authorization"] = f"ApiKey {api_key}"
69
72
  # REFERENCES
73
+ if service_id:
74
+ self.references["service.id"] = service_id
70
75
  if app_id:
71
76
  self.references["application.id"] = app_id
72
77
 
@@ -84,31 +89,28 @@ class Tracing(metaclass=Singleton):
84
89
  self.tracer_provider.add_span_processor(self.inline)
85
90
  # TRACE PROCESSORS -- OTLP
86
91
  try:
87
- log.info("--------------------------------------------")
88
92
  log.info(
89
- "Agenta SDK - connecting to otlp receiver at: %s",
93
+ "Agenta - OLTP URL: %s",
90
94
  self.otlp_url,
91
95
  )
92
- log.info("--------------------------------------------")
93
- check(
94
- self.otlp_url,
95
- headers=self.headers,
96
- timeout=1,
97
- )
96
+ # check(
97
+ # self.otlp_url,
98
+ # headers=self.headers,
99
+ # timeout=1,
100
+ # )
98
101
 
99
102
  _otlp = TraceProcessor(
100
103
  OTLPExporter(
101
104
  endpoint=self.otlp_url,
102
105
  headers=self.headers,
106
+ credentials=self.credentials,
103
107
  ),
104
108
  references=self.references,
105
109
  )
106
110
 
107
111
  self.tracer_provider.add_span_processor(_otlp)
108
- log.info("Success: traces will be exported.")
109
- log.info("--------------------------------------------")
110
112
  except: # pylint: disable=bare-except
111
- log.warning("Agenta SDK - traces will not be exported.")
113
+ log.warning("Agenta - OLTP unreachable, skipping exports.")
112
114
 
113
115
  # GLOBAL TRACER PROVIDER -- INSTRUMENTATION LIBRARIES
114
116
  set_tracer_provider(self.tracer_provider)
@@ -0,0 +1 @@
1
+ TRUTHY = {"true", "1", "t", "y", "yes", "on", "enable", "enabled"}