aiqa-client 0.3.6__tar.gz → 0.3.7__tar.gz
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.
- {aiqa_client-0.3.6/aiqa_client.egg-info → aiqa_client-0.3.7}/PKG-INFO +5 -5
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/README.md +4 -4
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa/__init__.py +2 -9
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa/aiqa_exporter.py +27 -17
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa/client.py +42 -64
- aiqa_client-0.3.7/aiqa/constants.py +5 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa/tracing.py +4 -27
- {aiqa_client-0.3.6 → aiqa_client-0.3.7/aiqa_client.egg-info}/PKG-INFO +5 -5
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa_client.egg-info/SOURCES.txt +1 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/pyproject.toml +1 -1
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/LICENSE +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/MANIFEST.in +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa/experiment_runner.py +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa/object_serialiser.py +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa/py.typed +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa/test_experiment_runner.py +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa/test_tracing.py +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa_client.egg-info/dependency_links.txt +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa_client.egg-info/requires.txt +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/aiqa_client.egg-info/top_level.txt +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/setup.cfg +0 -0
- {aiqa_client-0.3.6 → aiqa_client-0.3.7}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aiqa-client
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: OpenTelemetry-based Python client for tracing functions and sending traces to the AIQA server
|
|
5
5
|
Author-email: AIQA <info@aiqa.dev>
|
|
6
6
|
License: MIT
|
|
@@ -134,12 +134,12 @@ asyncio.run(main())
|
|
|
134
134
|
To ensure all spans are sent before process exit:
|
|
135
135
|
|
|
136
136
|
```python
|
|
137
|
-
from aiqa import
|
|
137
|
+
from aiqa import flush_tracing
|
|
138
138
|
import asyncio
|
|
139
139
|
|
|
140
140
|
async def main():
|
|
141
141
|
# Your code here
|
|
142
|
-
await
|
|
142
|
+
await flush_tracing()
|
|
143
143
|
|
|
144
144
|
asyncio.run(main())
|
|
145
145
|
```
|
|
@@ -154,10 +154,10 @@ from aiqa import get_aiqa_client
|
|
|
154
154
|
client = get_aiqa_client()
|
|
155
155
|
|
|
156
156
|
# Disable tracing (spans won't be created or exported)
|
|
157
|
-
client.
|
|
157
|
+
client.enabled = False
|
|
158
158
|
|
|
159
159
|
# Re-enable tracing
|
|
160
|
-
client.
|
|
160
|
+
client.enabled = True
|
|
161
161
|
|
|
162
162
|
# Check if tracing is enabled
|
|
163
163
|
if client.enabled:
|
|
@@ -97,12 +97,12 @@ asyncio.run(main())
|
|
|
97
97
|
To ensure all spans are sent before process exit:
|
|
98
98
|
|
|
99
99
|
```python
|
|
100
|
-
from aiqa import
|
|
100
|
+
from aiqa import flush_tracing
|
|
101
101
|
import asyncio
|
|
102
102
|
|
|
103
103
|
async def main():
|
|
104
104
|
# Your code here
|
|
105
|
-
await
|
|
105
|
+
await flush_tracing()
|
|
106
106
|
|
|
107
107
|
asyncio.run(main())
|
|
108
108
|
```
|
|
@@ -117,10 +117,10 @@ from aiqa import get_aiqa_client
|
|
|
117
117
|
client = get_aiqa_client()
|
|
118
118
|
|
|
119
119
|
# Disable tracing (spans won't be created or exported)
|
|
120
|
-
client.
|
|
120
|
+
client.enabled = False
|
|
121
121
|
|
|
122
122
|
# Re-enable tracing
|
|
123
|
-
client.
|
|
123
|
+
client.enabled = True
|
|
124
124
|
|
|
125
125
|
# Check if tracing is enabled
|
|
126
126
|
if client.enabled:
|
|
@@ -22,12 +22,9 @@ Example:
|
|
|
22
22
|
from .tracing import (
|
|
23
23
|
WithTracing,
|
|
24
24
|
flush_tracing,
|
|
25
|
-
shutdown_tracing,
|
|
26
25
|
set_span_attribute,
|
|
27
26
|
set_span_name,
|
|
28
27
|
get_active_span,
|
|
29
|
-
get_provider,
|
|
30
|
-
get_exporter,
|
|
31
28
|
get_active_trace_id,
|
|
32
29
|
get_span_id,
|
|
33
30
|
create_span_from_trace_id,
|
|
@@ -37,22 +34,18 @@ from .tracing import (
|
|
|
37
34
|
set_component_tag,
|
|
38
35
|
get_span,
|
|
39
36
|
)
|
|
40
|
-
from .client import get_aiqa_client
|
|
37
|
+
from .client import get_aiqa_client
|
|
41
38
|
from .experiment_runner import ExperimentRunner
|
|
42
39
|
|
|
43
|
-
__version__ = "0.3.
|
|
40
|
+
__version__ = "0.3.7"
|
|
44
41
|
|
|
45
42
|
__all__ = [
|
|
46
43
|
"WithTracing",
|
|
47
44
|
"flush_tracing",
|
|
48
|
-
"shutdown_tracing",
|
|
49
45
|
"set_span_attribute",
|
|
50
46
|
"set_span_name",
|
|
51
47
|
"get_active_span",
|
|
52
|
-
"get_provider",
|
|
53
|
-
"get_exporter",
|
|
54
48
|
"get_aiqa_client",
|
|
55
|
-
"set_enabled",
|
|
56
49
|
"ExperimentRunner",
|
|
57
50
|
"get_active_trace_id",
|
|
58
51
|
"get_span_id",
|
|
@@ -13,6 +13,9 @@ from typing import List, Dict, Any, Optional
|
|
|
13
13
|
from opentelemetry.sdk.trace import ReadableSpan
|
|
14
14
|
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
|
|
15
15
|
|
|
16
|
+
from .constants import AIQA_TRACER_NAME
|
|
17
|
+
from . import __version__
|
|
18
|
+
|
|
16
19
|
logger = logging.getLogger("AIQA")
|
|
17
20
|
|
|
18
21
|
|
|
@@ -28,6 +31,7 @@ class AIQASpanExporter(SpanExporter):
|
|
|
28
31
|
api_key: Optional[str] = None,
|
|
29
32
|
flush_interval_seconds: float = 5.0,
|
|
30
33
|
max_batch_size_bytes: int = 5 * 1024 * 1024, # 5MB default
|
|
34
|
+
max_buffer_spans: int = 10000, # Maximum spans to buffer (prevents unbounded growth)
|
|
31
35
|
):
|
|
32
36
|
"""
|
|
33
37
|
Initialize the AIQA span exporter.
|
|
@@ -42,6 +46,7 @@ class AIQASpanExporter(SpanExporter):
|
|
|
42
46
|
self._api_key = api_key
|
|
43
47
|
self.flush_interval_ms = flush_interval_seconds * 1000
|
|
44
48
|
self.max_batch_size_bytes = max_batch_size_bytes
|
|
49
|
+
self.max_buffer_spans = max_buffer_spans
|
|
45
50
|
self.buffer: List[Dict[str, Any]] = []
|
|
46
51
|
self.buffer_span_keys: set = set() # Track (traceId, spanId) tuples to prevent duplicates (Python 3.8 compatible)
|
|
47
52
|
self.buffer_lock = threading.Lock()
|
|
@@ -88,7 +93,13 @@ class AIQASpanExporter(SpanExporter):
|
|
|
88
93
|
with self.buffer_lock:
|
|
89
94
|
serialized_spans = []
|
|
90
95
|
duplicates_count = 0
|
|
96
|
+
dropped_count = 0
|
|
91
97
|
for span in spans:
|
|
98
|
+
# Check if buffer is full (prevent unbounded growth)
|
|
99
|
+
if len(self.buffer) >= self.max_buffer_spans:
|
|
100
|
+
dropped_count += 1
|
|
101
|
+
continue
|
|
102
|
+
|
|
92
103
|
serialized = self._serialize_span(span)
|
|
93
104
|
span_key = (serialized["traceId"], serialized["spanId"])
|
|
94
105
|
if span_key not in self.buffer_span_keys:
|
|
@@ -100,6 +111,12 @@ class AIQASpanExporter(SpanExporter):
|
|
|
100
111
|
|
|
101
112
|
self.buffer.extend(serialized_spans)
|
|
102
113
|
buffer_size = len(self.buffer)
|
|
114
|
+
|
|
115
|
+
if dropped_count > 0:
|
|
116
|
+
logger.warning(
|
|
117
|
+
f"WARNING: Buffer full ({buffer_size} spans), dropped {dropped_count} span(s). "
|
|
118
|
+
f"Consider increasing max_buffer_spans or fixing server connectivity."
|
|
119
|
+
)
|
|
103
120
|
|
|
104
121
|
if duplicates_count > 0:
|
|
105
122
|
logger.debug(
|
|
@@ -172,10 +189,16 @@ class AIQASpanExporter(SpanExporter):
|
|
|
172
189
|
"traceFlags": span_context.trace_flags,
|
|
173
190
|
"duration": self._time_to_tuple(span.end_time - span.start_time) if span.end_time else None,
|
|
174
191
|
"ended": span.end_time is not None,
|
|
175
|
-
"instrumentationLibrary":
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
192
|
+
"instrumentationLibrary": self._get_instrumentation_library(span),
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
def _get_instrumentation_library(self, span: ReadableSpan) -> Dict[str, Any]:
|
|
196
|
+
"""
|
|
197
|
+
Get instrumentation library information from the span: just use the package version.
|
|
198
|
+
"""
|
|
199
|
+
return {
|
|
200
|
+
"name": AIQA_TRACER_NAME,
|
|
201
|
+
"version": __version__,
|
|
179
202
|
}
|
|
180
203
|
|
|
181
204
|
def _time_to_tuple(self, nanoseconds: int) -> tuple:
|
|
@@ -183,19 +206,6 @@ class AIQASpanExporter(SpanExporter):
|
|
|
183
206
|
seconds = int(nanoseconds // 1_000_000_000)
|
|
184
207
|
nanos = int(nanoseconds % 1_000_000_000)
|
|
185
208
|
return (seconds, nanos)
|
|
186
|
-
|
|
187
|
-
def _get_instrumentation_name(self) -> str:
|
|
188
|
-
"""Get instrumentation library name - always 'aiqa-tracer'."""
|
|
189
|
-
from .client import AIQA_TRACER_NAME
|
|
190
|
-
return AIQA_TRACER_NAME
|
|
191
|
-
|
|
192
|
-
def _get_instrumentation_version(self) -> Optional[str]:
|
|
193
|
-
"""Get instrumentation library version from __version__."""
|
|
194
|
-
try:
|
|
195
|
-
from . import __version__
|
|
196
|
-
return __version__
|
|
197
|
-
except (ImportError, AttributeError):
|
|
198
|
-
return None
|
|
199
209
|
|
|
200
210
|
def _build_request_headers(self) -> Dict[str, str]:
|
|
201
211
|
"""Build HTTP headers for span requests."""
|
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
import os
|
|
3
3
|
import logging
|
|
4
4
|
from functools import lru_cache
|
|
5
|
-
from typing import Optional
|
|
5
|
+
from typing import Optional, TYPE_CHECKING, Any
|
|
6
6
|
from opentelemetry import trace
|
|
7
7
|
from opentelemetry.sdk.trace import TracerProvider
|
|
8
8
|
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
9
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from .aiqa_exporter import AIQASpanExporter
|
|
12
|
+
|
|
10
13
|
logger = logging.getLogger("AIQA")
|
|
11
14
|
|
|
12
15
|
# Compatibility import for TraceIdRatioBased sampler
|
|
13
16
|
# In older OpenTelemetry versions it was TraceIdRatioBasedSampler
|
|
14
17
|
# In newer versions (>=1.24.0) it's TraceIdRatioBased
|
|
15
|
-
TraceIdRatioBased = None
|
|
18
|
+
TraceIdRatioBased: Optional[Any] = None
|
|
16
19
|
try:
|
|
17
20
|
from opentelemetry.sdk.trace.sampling import TraceIdRatioBased
|
|
18
21
|
except ImportError:
|
|
@@ -28,10 +31,7 @@ except ImportError:
|
|
|
28
31
|
# Set to None so we can check later
|
|
29
32
|
TraceIdRatioBased = None
|
|
30
33
|
|
|
31
|
-
from .
|
|
32
|
-
|
|
33
|
-
AIQA_TRACER_NAME = "aiqa-tracer"
|
|
34
|
-
|
|
34
|
+
from .constants import AIQA_TRACER_NAME
|
|
35
35
|
|
|
36
36
|
class AIQAClient:
|
|
37
37
|
"""
|
|
@@ -78,32 +78,38 @@ class AIQAClient:
|
|
|
78
78
|
|
|
79
79
|
@enabled.setter
|
|
80
80
|
def enabled(self, value: bool) -> None:
|
|
81
|
-
"""Set the enabled state.
|
|
82
|
-
self._enabled = value
|
|
83
|
-
|
|
84
|
-
def set_enabled(self, enabled: bool) -> None:
|
|
85
|
-
"""
|
|
86
|
-
Enable or disable AIQA tracing.
|
|
81
|
+
"""Set the enabled state.
|
|
87
82
|
|
|
88
83
|
When disabled:
|
|
89
84
|
- Tracing does not create spans
|
|
90
85
|
- Export does not send spans
|
|
91
|
-
|
|
92
|
-
Args:
|
|
93
|
-
enabled: True to enable tracing, False to disable
|
|
94
86
|
"""
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
logger.info("AIQA tracing enabled")
|
|
98
|
-
else:
|
|
99
|
-
logger.info("AIQA tracing disabled")
|
|
87
|
+
logger.info(f"AIQA tracing {'enabled' if value else 'disabled'}")
|
|
88
|
+
self._enabled = value
|
|
100
89
|
|
|
101
|
-
def
|
|
102
|
-
"""
|
|
103
|
-
|
|
90
|
+
def shutdown(self) -> None:
|
|
91
|
+
"""
|
|
92
|
+
Shutdown the tracer provider and exporter.
|
|
93
|
+
It is not necessary to call this function.
|
|
94
|
+
Use this to clean up resources at the end of all tracing.
|
|
95
|
+
|
|
96
|
+
This will also set enabled=False to prevent further tracing attempts.
|
|
97
|
+
"""
|
|
98
|
+
try:
|
|
99
|
+
logger.info("AIQA tracing shutting down")
|
|
100
|
+
# Disable tracing to prevent attempts to use shut-down system
|
|
101
|
+
self.enabled = False
|
|
102
|
+
if self._provider:
|
|
103
|
+
self._provider.shutdown()
|
|
104
|
+
if self._exporter:
|
|
105
|
+
self._exporter.shutdown()
|
|
106
|
+
except Exception as e:
|
|
107
|
+
logger.error(f"Error shutting down tracing: {e}")
|
|
108
|
+
# Still disable even if shutdown had errors
|
|
109
|
+
self.enabled = False
|
|
104
110
|
|
|
105
111
|
|
|
106
|
-
# Global singleton instance
|
|
112
|
+
# Global singleton instance
|
|
107
113
|
client: AIQAClient = AIQAClient()
|
|
108
114
|
|
|
109
115
|
# Component tag to add to all spans (can be set via AIQA_COMPONENT_TAG env var or programmatically)
|
|
@@ -154,24 +160,19 @@ def get_aiqa_client() -> AIQAClient:
|
|
|
154
160
|
logger.warning("AIQA tracing is disabled. Your application will continue to run without tracing.")
|
|
155
161
|
return client
|
|
156
162
|
|
|
157
|
-
def _init_tracing():
|
|
163
|
+
def _init_tracing() -> None:
|
|
158
164
|
"""Initialize tracing system and load configuration from environment variables."""
|
|
159
165
|
global client
|
|
160
166
|
if client._initialized:
|
|
161
167
|
return
|
|
162
168
|
|
|
163
169
|
try:
|
|
164
|
-
# Check for required environment variables
|
|
165
170
|
server_url = os.getenv("AIQA_SERVER_URL")
|
|
166
171
|
api_key = os.getenv("AIQA_API_KEY")
|
|
167
172
|
|
|
168
173
|
if not server_url or not api_key:
|
|
169
174
|
client.enabled = False
|
|
170
|
-
missing_vars = []
|
|
171
|
-
if not server_url:
|
|
172
|
-
missing_vars.append("AIQA_SERVER_URL")
|
|
173
|
-
if not api_key:
|
|
174
|
-
missing_vars.append("AIQA_API_KEY")
|
|
175
|
+
missing_vars = [var for var, val in [("AIQA_SERVER_URL", server_url), ("AIQA_API_KEY", api_key)] if not val]
|
|
175
176
|
logger.warning(
|
|
176
177
|
f"AIQA tracing is disabled: missing required environment variables: {', '.join(missing_vars)}"
|
|
177
178
|
)
|
|
@@ -218,10 +219,12 @@ def _init_tracing():
|
|
|
218
219
|
client._initialized = True # Mark as initialized even on error to prevent retry loops
|
|
219
220
|
raise
|
|
220
221
|
|
|
221
|
-
def _attach_aiqa_processor(provider: TracerProvider):
|
|
222
|
+
def _attach_aiqa_processor(provider: TracerProvider) -> None:
|
|
222
223
|
"""Attach AIQA span processor to the provider. Idempotent - safe to call multiple times."""
|
|
224
|
+
from .aiqa_exporter import AIQASpanExporter
|
|
225
|
+
|
|
223
226
|
try:
|
|
224
|
-
#
|
|
227
|
+
# Check if already attached
|
|
225
228
|
for p in provider._active_span_processor._span_processors:
|
|
226
229
|
if isinstance(getattr(p, "exporter", None), AIQASpanExporter):
|
|
227
230
|
logger.debug("AIQA span processor already attached, skipping")
|
|
@@ -241,44 +244,19 @@ def _attach_aiqa_processor(provider: TracerProvider):
|
|
|
241
244
|
raise
|
|
242
245
|
|
|
243
246
|
|
|
244
|
-
def set_enabled(enabled: bool) -> None:
|
|
245
|
-
"""
|
|
246
|
-
Enable or disable AIQA tracing.
|
|
247
|
-
|
|
248
|
-
When disabled:
|
|
249
|
-
- Tracing does not create spans
|
|
250
|
-
- Export does not send spans
|
|
251
|
-
|
|
252
|
-
Args:
|
|
253
|
-
enabled: True to enable tracing, False to disable
|
|
254
|
-
|
|
255
|
-
Example:
|
|
256
|
-
from aiqa import get_aiqa_client
|
|
257
|
-
|
|
258
|
-
client = get_aiqa_client()
|
|
259
|
-
client.set_enabled(False) # Disable tracing
|
|
260
|
-
"""
|
|
261
|
-
client = get_aiqa_client()
|
|
262
|
-
client.set_enabled(enabled)
|
|
263
247
|
|
|
264
|
-
|
|
265
|
-
def get_aiqa_tracer():
|
|
248
|
+
def get_aiqa_tracer() -> trace.Tracer:
|
|
266
249
|
"""
|
|
267
250
|
Get the AIQA tracer with version from __init__.py __version__.
|
|
268
|
-
This should be used instead of trace.get_tracer()
|
|
251
|
+
This should be used instead of trace.get_tracer() so that the version is set.
|
|
269
252
|
"""
|
|
270
253
|
try:
|
|
271
254
|
# Import here to avoid circular import
|
|
272
255
|
from . import __version__
|
|
273
|
-
|
|
274
256
|
# Compatibility: version parameter may not be supported in older OpenTelemetry versions
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
return trace.get_tracer(AIQA_TRACER_NAME, version=__version__)
|
|
278
|
-
except TypeError:
|
|
279
|
-
# Fall back to without version parameter (older versions)
|
|
280
|
-
return trace.get_tracer(AIQA_TRACER_NAME)
|
|
257
|
+
# Try with version parameter (newer OpenTelemetry versions)
|
|
258
|
+
return trace.get_tracer(AIQA_TRACER_NAME, version=__version__)
|
|
281
259
|
except Exception as e:
|
|
282
|
-
|
|
283
|
-
|
|
260
|
+
# Log issue but still return a tracer
|
|
261
|
+
logger.info(f"Issue getting AIQA tracer with version: {e}, using fallback")
|
|
284
262
|
return trace.get_tracer(AIQA_TRACER_NAME)
|
|
@@ -14,7 +14,8 @@ from opentelemetry.sdk.trace import TracerProvider
|
|
|
14
14
|
from opentelemetry.trace import Status, StatusCode, SpanContext, TraceFlags
|
|
15
15
|
from opentelemetry.propagate import inject, extract
|
|
16
16
|
from .aiqa_exporter import AIQASpanExporter
|
|
17
|
-
from .client import get_aiqa_client,
|
|
17
|
+
from .client import get_aiqa_client, get_component_tag, set_component_tag as _set_component_tag, get_aiqa_tracer
|
|
18
|
+
from .constants import AIQA_TRACER_NAME
|
|
18
19
|
from .object_serialiser import serialize_for_span
|
|
19
20
|
|
|
20
21
|
logger = logging.getLogger("AIQA")
|
|
@@ -25,6 +26,7 @@ async def flush_tracing() -> None:
|
|
|
25
26
|
Flush all pending spans to the server.
|
|
26
27
|
Flushes also happen automatically every few seconds. So you only need to call this function
|
|
27
28
|
if you want to flush immediately, e.g. before exiting a process.
|
|
29
|
+
A common use is if you are tracing unit tests or experiment runs.
|
|
28
30
|
|
|
29
31
|
This flushes both the BatchSpanProcessor and the exporter buffer.
|
|
30
32
|
"""
|
|
@@ -35,25 +37,10 @@ async def flush_tracing() -> None:
|
|
|
35
37
|
await client.exporter.flush()
|
|
36
38
|
|
|
37
39
|
|
|
38
|
-
async def shutdown_tracing() -> None:
|
|
39
|
-
"""
|
|
40
|
-
Shutdown the tracer provider and exporter.
|
|
41
|
-
It is not necessary to call this function.
|
|
42
|
-
"""
|
|
43
|
-
try:
|
|
44
|
-
client = get_aiqa_client()
|
|
45
|
-
if client.provider:
|
|
46
|
-
client.provider.shutdown() # Synchronous method
|
|
47
|
-
if client.exporter:
|
|
48
|
-
client.exporter.shutdown() # Synchronous method
|
|
49
|
-
except Exception as e:
|
|
50
|
-
logger.error(f"Error shutting down tracing: {e}")
|
|
51
|
-
|
|
52
|
-
|
|
53
40
|
# Export provider and exporter accessors for advanced usage
|
|
54
41
|
|
|
55
42
|
__all__ = [
|
|
56
|
-
"
|
|
43
|
+
"flush_tracing", "WithTracing",
|
|
57
44
|
"set_span_attribute", "set_span_name", "get_active_span",
|
|
58
45
|
"get_active_trace_id", "get_span_id", "create_span_from_trace_id", "inject_trace_context", "extract_trace_context",
|
|
59
46
|
"set_conversation_id", "set_component_tag", "set_token_usage", "set_provider_and_model", "get_span", "submit_feedback"
|
|
@@ -969,16 +956,6 @@ def set_component_tag(tag: str) -> None:
|
|
|
969
956
|
"""
|
|
970
957
|
_set_component_tag(tag)
|
|
971
958
|
|
|
972
|
-
def get_provider() -> Optional[TracerProvider]:
|
|
973
|
-
"""Get the tracer provider for advanced usage."""
|
|
974
|
-
client = get_aiqa_client()
|
|
975
|
-
return client.provider
|
|
976
|
-
|
|
977
|
-
def get_exporter() -> Optional[AIQASpanExporter]:
|
|
978
|
-
"""Get the exporter for advanced usage."""
|
|
979
|
-
client = get_aiqa_client()
|
|
980
|
-
return client.exporter
|
|
981
|
-
|
|
982
959
|
|
|
983
960
|
def get_active_trace_id() -> Optional[str]:
|
|
984
961
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aiqa-client
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: OpenTelemetry-based Python client for tracing functions and sending traces to the AIQA server
|
|
5
5
|
Author-email: AIQA <info@aiqa.dev>
|
|
6
6
|
License: MIT
|
|
@@ -134,12 +134,12 @@ asyncio.run(main())
|
|
|
134
134
|
To ensure all spans are sent before process exit:
|
|
135
135
|
|
|
136
136
|
```python
|
|
137
|
-
from aiqa import
|
|
137
|
+
from aiqa import flush_tracing
|
|
138
138
|
import asyncio
|
|
139
139
|
|
|
140
140
|
async def main():
|
|
141
141
|
# Your code here
|
|
142
|
-
await
|
|
142
|
+
await flush_tracing()
|
|
143
143
|
|
|
144
144
|
asyncio.run(main())
|
|
145
145
|
```
|
|
@@ -154,10 +154,10 @@ from aiqa import get_aiqa_client
|
|
|
154
154
|
client = get_aiqa_client()
|
|
155
155
|
|
|
156
156
|
# Disable tracing (spans won't be created or exported)
|
|
157
|
-
client.
|
|
157
|
+
client.enabled = False
|
|
158
158
|
|
|
159
159
|
# Re-enable tracing
|
|
160
|
-
client.
|
|
160
|
+
client.enabled = True
|
|
161
161
|
|
|
162
162
|
# Check if tracing is enabled
|
|
163
163
|
if client.enabled:
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "aiqa-client"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.7"
|
|
8
8
|
description = "OpenTelemetry-based Python client for tracing functions and sending traces to the AIQA server"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|