paid-python 0.3.0__py3-none-any.whl → 0.3.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.
- paid/tracing/autoinstrumentation.py +5 -29
- paid/tracing/context_data.py +25 -0
- paid/tracing/distributed_tracing.py +1 -1
- paid/tracing/tracing.py +8 -6
- {paid_python-0.3.0.dist-info → paid_python-0.3.2.dist-info}/METADATA +1 -2
- {paid_python-0.3.0.dist-info → paid_python-0.3.2.dist-info}/RECORD +8 -8
- {paid_python-0.3.0.dist-info → paid_python-0.3.2.dist-info}/LICENSE +0 -0
- {paid_python-0.3.0.dist-info → paid_python-0.3.2.dist-info}/WHEEL +0 -0
|
@@ -21,13 +21,6 @@ try:
|
|
|
21
21
|
except ImportError:
|
|
22
22
|
ANTHROPIC_AVAILABLE = False
|
|
23
23
|
|
|
24
|
-
try:
|
|
25
|
-
from opentelemetry.instrumentation.google_generativeai import GoogleGenerativeAiInstrumentor
|
|
26
|
-
|
|
27
|
-
GEMINI_AVAILABLE = True
|
|
28
|
-
except ImportError:
|
|
29
|
-
GEMINI_AVAILABLE = False
|
|
30
|
-
|
|
31
24
|
try:
|
|
32
25
|
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
|
|
33
26
|
|
|
@@ -79,7 +72,6 @@ def paid_autoinstrument(libraries: Optional[List[str]] = None) -> None:
|
|
|
79
72
|
Args:
|
|
80
73
|
libraries: List of library names to instrument. Currently supported:
|
|
81
74
|
- "anthropic": Anthropic library
|
|
82
|
-
- "gemini": Gemini library
|
|
83
75
|
- "openai": OpenAI library
|
|
84
76
|
- "openai-agents": OpenAI Agents SDK
|
|
85
77
|
- "bedrock": AWS Bedrock
|
|
@@ -114,7 +106,7 @@ def paid_autoinstrument(libraries: Optional[List[str]] = None) -> None:
|
|
|
114
106
|
|
|
115
107
|
# Default to all supported libraries if none specified
|
|
116
108
|
if libraries is None:
|
|
117
|
-
libraries = ["anthropic", "
|
|
109
|
+
libraries = ["anthropic", "openai", "openai-agents", "bedrock", "langchain", "google-genai"]
|
|
118
110
|
|
|
119
111
|
for library in libraries:
|
|
120
112
|
if library in _initialized_instrumentors:
|
|
@@ -123,8 +115,6 @@ def paid_autoinstrument(libraries: Optional[List[str]] = None) -> None:
|
|
|
123
115
|
|
|
124
116
|
if library == "anthropic":
|
|
125
117
|
_instrument_anthropic()
|
|
126
|
-
elif library == "gemini":
|
|
127
|
-
_instrument_gemini()
|
|
128
118
|
elif library == "openai":
|
|
129
119
|
_instrument_openai()
|
|
130
120
|
elif library == "openai-agents":
|
|
@@ -158,21 +148,6 @@ def _instrument_anthropic() -> None:
|
|
|
158
148
|
logger.info("Anthropic auto-instrumentation enabled")
|
|
159
149
|
|
|
160
150
|
|
|
161
|
-
def _instrument_gemini() -> None:
|
|
162
|
-
"""
|
|
163
|
-
Instrument the Google Gemini library using opentelemetry-instrumentation-google-generativeai.
|
|
164
|
-
"""
|
|
165
|
-
if not GEMINI_AVAILABLE:
|
|
166
|
-
logger.warning("Gemini library not available, skipping instrumentation")
|
|
167
|
-
return
|
|
168
|
-
|
|
169
|
-
# Instrument Gemini with Paid's tracer provider
|
|
170
|
-
GoogleGenerativeAiInstrumentor().instrument(tracer_provider=tracing.paid_tracer_provider)
|
|
171
|
-
|
|
172
|
-
_initialized_instrumentors.append("gemini")
|
|
173
|
-
logger.info("Gemini auto-instrumentation enabled")
|
|
174
|
-
|
|
175
|
-
|
|
176
151
|
def _instrument_openai() -> None:
|
|
177
152
|
"""
|
|
178
153
|
Instrument the OpenAI library using opentelemetry-instrumentation-openai.
|
|
@@ -227,12 +202,14 @@ def _instrument_langchain() -> None:
|
|
|
227
202
|
return
|
|
228
203
|
|
|
229
204
|
# Instrument LangChain with Paid's tracer provider
|
|
230
|
-
LangchainInstrumentor(disable_trace_context_propagation=True).instrument(
|
|
231
|
-
|
|
205
|
+
LangchainInstrumentor(disable_trace_context_propagation=True).instrument(
|
|
206
|
+
tracer_provider=tracing.paid_tracer_provider
|
|
207
|
+
)
|
|
232
208
|
|
|
233
209
|
_initialized_instrumentors.append("langchain")
|
|
234
210
|
logger.info("LangChain auto-instrumentation enabled")
|
|
235
211
|
|
|
212
|
+
|
|
236
213
|
def _instrument_google_genai() -> None:
|
|
237
214
|
"""
|
|
238
215
|
Instrument Google GenAI using openinference-instrumentation-google-genai.
|
|
@@ -241,7 +218,6 @@ def _instrument_google_genai() -> None:
|
|
|
241
218
|
logger.warning("Google GenAI instrumentation library not available, skipping instrumentation")
|
|
242
219
|
return
|
|
243
220
|
|
|
244
|
-
|
|
245
221
|
GoogleGenAIInstrumentor().instrument(tracer_provider=tracing.paid_tracer_provider)
|
|
246
222
|
_initialized_instrumentors.append("google-genai")
|
|
247
223
|
logger.info("Google GenAI auto-instrumentation enabled")
|
paid/tracing/context_data.py
CHANGED
|
@@ -44,6 +44,8 @@ class ContextData:
|
|
|
44
44
|
|
|
45
45
|
@classmethod
|
|
46
46
|
def set_context_key(cls, key: str, value: Any) -> None:
|
|
47
|
+
if value is None:
|
|
48
|
+
return
|
|
47
49
|
if key not in cls._context:
|
|
48
50
|
logger.warning(f"Invalid context key: {key}")
|
|
49
51
|
return
|
|
@@ -51,6 +53,18 @@ class ContextData:
|
|
|
51
53
|
reset_tokens = cls._get_or_create_reset_tokens()
|
|
52
54
|
reset_tokens[key] = reset_token
|
|
53
55
|
|
|
56
|
+
@classmethod
|
|
57
|
+
def unset_context_key(cls, key: str) -> None:
|
|
58
|
+
"""Unset a specific context key"""
|
|
59
|
+
if key not in cls._context:
|
|
60
|
+
logger.warning(f"Invalid context key: {key}")
|
|
61
|
+
return
|
|
62
|
+
reset_tokens = cls._reset_tokens.get()
|
|
63
|
+
if reset_tokens:
|
|
64
|
+
_ = cls._context[key].set(None)
|
|
65
|
+
if key in reset_tokens:
|
|
66
|
+
del reset_tokens[key]
|
|
67
|
+
|
|
54
68
|
@classmethod
|
|
55
69
|
def reset_context(cls) -> None:
|
|
56
70
|
reset_tokens = cls._reset_tokens.get()
|
|
@@ -58,3 +72,14 @@ class ContextData:
|
|
|
58
72
|
for key, reset_token in reset_tokens.items():
|
|
59
73
|
cls._context[key].reset(reset_token)
|
|
60
74
|
reset_tokens.clear()
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def reset_context_key(cls, key: str) -> None:
|
|
78
|
+
"""Reset a specific context key to its previous value using the stored reset token."""
|
|
79
|
+
if key not in cls._context:
|
|
80
|
+
logger.warning(f"Invalid context key: {key}")
|
|
81
|
+
return
|
|
82
|
+
reset_tokens = cls._reset_tokens.get()
|
|
83
|
+
if reset_tokens and key in reset_tokens:
|
|
84
|
+
cls._context[key].reset(reset_tokens[key])
|
|
85
|
+
del reset_tokens[key]
|
paid/tracing/tracing.py
CHANGED
|
@@ -73,6 +73,7 @@ class PaidSpanProcessor(SpanProcessor):
|
|
|
73
73
|
"gen_ai.response.messages",
|
|
74
74
|
"llm.output_message",
|
|
75
75
|
"llm.input_message",
|
|
76
|
+
"llm.invocation_parameters",
|
|
76
77
|
"output.value",
|
|
77
78
|
"input.value",
|
|
78
79
|
}
|
|
@@ -137,12 +138,11 @@ class PaidSpanProcessor(SpanProcessor):
|
|
|
137
138
|
"""Called to force flush. Always returns True since there's nothing to flush."""
|
|
138
139
|
return True
|
|
139
140
|
|
|
141
|
+
|
|
140
142
|
def setup_graceful_termination():
|
|
141
143
|
def flush_traces():
|
|
142
144
|
try:
|
|
143
|
-
if not isinstance(paid_tracer_provider, NoOpTracerProvider) and not paid_tracer_provider.force_flush(
|
|
144
|
-
10000
|
|
145
|
-
):
|
|
145
|
+
if not isinstance(paid_tracer_provider, NoOpTracerProvider) and not paid_tracer_provider.force_flush(10000):
|
|
146
146
|
logger.error("OTEL force flush : timeout reached")
|
|
147
147
|
except Exception as e:
|
|
148
148
|
logger.error(f"Error flushing traces: {e}")
|
|
@@ -169,8 +169,10 @@ def setup_graceful_termination():
|
|
|
169
169
|
for sig in (signal.SIGINT, signal.SIGTERM):
|
|
170
170
|
signal.signal(sig, create_chained_signal_handler(sig))
|
|
171
171
|
except Exception as e:
|
|
172
|
-
logger.warning(
|
|
173
|
-
|
|
172
|
+
logger.warning(
|
|
173
|
+
f"Could not set up termination handlers: {e}"
|
|
174
|
+
"\nConsider calling initialize_tracing() from the main thread during app initialization if you don't already"
|
|
175
|
+
)
|
|
174
176
|
|
|
175
177
|
|
|
176
178
|
def initialize_tracing(api_key: Optional[str] = None, collector_endpoint: Optional[str] = DEFAULT_COLLECTOR_ENDPOINT):
|
|
@@ -220,7 +222,7 @@ def initialize_tracing(api_key: Optional[str] = None, collector_endpoint: Option
|
|
|
220
222
|
span_processor = SimpleSpanProcessor(otlp_exporter)
|
|
221
223
|
paid_tracer_provider.add_span_processor(span_processor)
|
|
222
224
|
|
|
223
|
-
setup_graceful_termination()
|
|
225
|
+
setup_graceful_termination() # doesn't throw
|
|
224
226
|
|
|
225
227
|
logger.info("Paid tracing initialized successfully - collector at %s", collector_endpoint)
|
|
226
228
|
except Exception as e:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: paid-python
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary:
|
|
5
5
|
Requires-Python: >=3.9,<3.14
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -25,7 +25,6 @@ Requires-Dist: openinference-instrumentation-openai-agents (>=1.0.0)
|
|
|
25
25
|
Requires-Dist: opentelemetry-api (>=1.23.0)
|
|
26
26
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.23.0)
|
|
27
27
|
Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.47.0)
|
|
28
|
-
Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.47.0)
|
|
29
28
|
Requires-Dist: opentelemetry-instrumentation-langchain (>=0.47.0)
|
|
30
29
|
Requires-Dist: opentelemetry-instrumentation-openai (>=0.47.0)
|
|
31
30
|
Requires-Dist: opentelemetry-sdk (>=1.23.0)
|
|
@@ -37,12 +37,12 @@ paid/orders/lines/raw_client.py,sha256=KZN_yBokCOkf1lUb4ZJtX_NZbqmTqCdJNoaIOdWar
|
|
|
37
37
|
paid/orders/raw_client.py,sha256=650e1Sj2vi9KVJc15M3ENXIKYoth0qMz66dzvXy1Sb4,16245
|
|
38
38
|
paid/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
39
|
paid/tracing/__init__.py,sha256=Pe55koIwqJ6Vv5-9Wqi8xIdwCS2BbxZds-MK5fD-F5Y,506
|
|
40
|
-
paid/tracing/autoinstrumentation.py,sha256=
|
|
41
|
-
paid/tracing/context_data.py,sha256=
|
|
40
|
+
paid/tracing/autoinstrumentation.py,sha256=J1v1YNR6fISd0B-P9MPwWQGVqJ309PuYfaUHsfqGUGk,7650
|
|
41
|
+
paid/tracing/context_data.py,sha256=oiLocz-9qDqB5nQzJlrLsc2Mkr9MaNt_yF_hjppobKc,3298
|
|
42
42
|
paid/tracing/context_manager.py,sha256=ZQtsJ9JPxTwn2t4AW26WpYboaOEZdI2T1Sw0Rwsbf-E,8470
|
|
43
|
-
paid/tracing/distributed_tracing.py,sha256=
|
|
43
|
+
paid/tracing/distributed_tracing.py,sha256=Vht3U8QJmT5jlRVnrybTn-cI1RPuVtyb3V4eTu6gA4g,3991
|
|
44
44
|
paid/tracing/signal.py,sha256=PfYxF6EFQS8j7RY5_C5NXrCBVu9Hq2E2tyG4fdQScJk,3252
|
|
45
|
-
paid/tracing/tracing.py,sha256
|
|
45
|
+
paid/tracing/tracing.py,sha256=-gnN75ihJdgq6zTxXbpJSloHJqcRYBhb-RLyk1Bkxho,14803
|
|
46
46
|
paid/tracing/wrappers/__init__.py,sha256=IIleLB_JUbzLw7FshrU2VHZAKF3dZHMGy1O5zCBwwqM,1588
|
|
47
47
|
paid/tracing/wrappers/anthropic/__init__.py,sha256=_x1fjySAQxuT5cIGO_jU09LiGcZH-WQLqKg8mUFAu2w,115
|
|
48
48
|
paid/tracing/wrappers/anthropic/anthropicWrapper.py,sha256=pGchbOb41CbTxc7H8xXoM-LjR085spqrzXqCVC_rrFk,4913
|
|
@@ -99,7 +99,7 @@ paid/usage/__init__.py,sha256=_VhToAyIt_5axN6CLJwtxg3-CO7THa_23pbUzqhXJa4,85
|
|
|
99
99
|
paid/usage/client.py,sha256=280WJuepoovk3BAVbAx2yN2Q_qBdvx3CcPkLu8lXslc,3030
|
|
100
100
|
paid/usage/raw_client.py,sha256=2acg5C4lxuZodZjepU9QYF0fmBxgG-3ZgXs1zUJG-wM,3709
|
|
101
101
|
paid/version.py,sha256=QIpDFnOrxMxrs86eL0iNH0mSZ1DO078wWHYY9TYAoew,78
|
|
102
|
-
paid_python-0.3.
|
|
103
|
-
paid_python-0.3.
|
|
104
|
-
paid_python-0.3.
|
|
105
|
-
paid_python-0.3.
|
|
102
|
+
paid_python-0.3.2.dist-info/LICENSE,sha256=Nz4baY1zvv0Qy7lqrQtbaiMhmEeGr2Q7A93aqzpml4c,1071
|
|
103
|
+
paid_python-0.3.2.dist-info/METADATA,sha256=6oJYiI-SNj7ghh91lD6Sw4Av9vcwjnfxPxGP5V3GYU4,22335
|
|
104
|
+
paid_python-0.3.2.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
|
105
|
+
paid_python-0.3.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|