paid-python 1.0.6__tar.gz → 1.2.0__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.
- {paid_python-1.0.6 → paid_python-1.2.0}/PKG-INFO +65 -78
- {paid_python-1.0.6 → paid_python-1.2.0}/README.md +63 -76
- {paid_python-1.0.6 → paid_python-1.2.0}/pyproject.toml +2 -2
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/__init__.py +15 -0
- paid_python-1.2.0/src/paid/contacts/__init__.py +34 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/contacts/client.py +38 -16
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/contacts/raw_client.py +36 -10
- paid_python-1.2.0/src/paid/contacts/types/__init__.py +34 -0
- paid_python-1.2.0/src/paid/contacts/types/create_contact_request_roles_item.py +5 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/client_wrapper.py +2 -2
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/customers/client.py +8 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/customers/raw_client.py +8 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/orders/client.py +21 -8
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/orders/raw_client.py +26 -8
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/__init__.py +2 -1
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/context_data.py +2 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/context_manager.py +24 -37
- paid_python-1.2.0/src/paid/tracing/signal.py +156 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/tracing.py +101 -69
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/__init__.py +12 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/contact.py +2 -0
- paid_python-1.2.0/src/paid/types/contact_roles_item.py +5 -0
- paid_python-1.2.0/src/paid/types/create_order_line_attribute_request.py +21 -0
- paid_python-1.2.0/src/paid/types/create_order_line_request.py +32 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/customer.py +3 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/signal.py +6 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/update_contact_request.py +2 -0
- paid_python-1.2.0/src/paid/types/update_contact_request_roles_item.py +5 -0
- paid_python-1.2.0/src/paid/version.py +3 -0
- paid_python-1.0.6/src/paid/signals/__init__.py +0 -4
- paid_python-1.0.6/src/paid/tracing/signal.py +0 -84
- paid_python-1.0.6/src/paid/version.py +0 -6
- {paid_python-1.0.6 → paid_python-1.2.0}/LICENSE +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/client.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/api_error.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/datetime_utils.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/file.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/force_multipart.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/http_client.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/http_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/http_sse/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/http_sse/_api.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/http_sse/_decoders.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/http_sse/_exceptions.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/http_sse/_models.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/jsonable_encoder.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/pydantic_utilities.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/query_encoder.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/remove_none_from_dict.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/request_options.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/core/serialization.py +0 -0
- {paid_python-1.0.6/src/paid/contacts → paid_python-1.2.0/src/paid/customers}/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/environment.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/errors/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/errors/bad_request_error.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/errors/forbidden_error.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/errors/internal_server_error.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/errors/not_found_error.py +0 -0
- {paid_python-1.0.6/src/paid/customers → paid_python-1.2.0/src/paid/invoices}/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/invoices/client.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/invoices/raw_client.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/logger.py +0 -0
- {paid_python-1.0.6/src/paid/invoices → paid_python-1.2.0/src/paid/orders}/__init__.py +0 -0
- {paid_python-1.0.6/src/paid/orders → paid_python-1.2.0/src/paid/products}/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/products/client.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/products/raw_client.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/py.typed +0 -0
- {paid_python-1.0.6/src/paid/products → paid_python-1.2.0/src/paid/signals}/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/signals/client.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/signals/raw_client.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/anthropic_patches/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/anthropic_patches/patches.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/autoinstrumentation.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/distributed_tracing.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/gemini_patches/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/gemini_patches/patches.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/anthropic/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/anthropic/anthropicWrapper.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/bedrock/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/bedrock/bedrockWrapper.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/gemini/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/gemini/geminiWrapper.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/langchain/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/langchain/paidLangChainCallback.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/mistral/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/mistral/mistralWrapper.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/openai/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/openai/openAiWrapper.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/openai_agents/__init__.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/openai_agents/openaiAgentsHook.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/tracing/wrappers/utils.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/attribution.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/bulk_signals_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/contact_billing_address.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/contact_list_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/customer_attribution.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/customer_billing_address.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/customer_by_external_id.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/customer_by_id.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/customer_creation_state.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/customer_list_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/empty_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/error_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/invoice.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/invoice_line.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/invoice_line_payment_status.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/invoice_lines_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/invoice_list_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/invoice_payment_status.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/invoice_source.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/invoice_status.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/invoice_tax_status.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/order.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/order_creation_state.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/order_line.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/order_lines_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/order_list_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/pagination.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/product.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/product_by_external_id.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/product_by_id.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/product_list_response.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/update_customer_request.py +0 -0
- {paid_python-1.0.6 → paid_python-1.2.0}/src/paid/types/update_product_request.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: paid-python
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary:
|
|
5
5
|
Requires-Python: >=3.10,<3.14
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -19,7 +19,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
19
19
|
Classifier: Typing :: Typed
|
|
20
20
|
Requires-Dist: httpx (>=0.21.2)
|
|
21
21
|
Requires-Dist: mutagen (>=1.47.0)
|
|
22
|
-
Requires-Dist: openinference-instrumentation-anthropic (>=0.1.20)
|
|
22
|
+
Requires-Dist: openinference-instrumentation-anthropic (>=0.1.20,<1.0.0)
|
|
23
23
|
Requires-Dist: openinference-instrumentation-bedrock (>=0.1.0)
|
|
24
24
|
Requires-Dist: openinference-instrumentation-google-genai (>=0.1.8)
|
|
25
25
|
Requires-Dist: openinference-instrumentation-instructor (>=0.1.0)
|
|
@@ -144,15 +144,6 @@ Your Paid API key for authentication. This is used as a fallback when you don't
|
|
|
144
144
|
export PAID_API_KEY="your_api_key_here"
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
You can then initialize the client without passing the token:
|
|
148
|
-
|
|
149
|
-
```python
|
|
150
|
-
from paid import Paid
|
|
151
|
-
|
|
152
|
-
# API key is read from PAID_API_KEY environment variable
|
|
153
|
-
client = Paid()
|
|
154
|
-
```
|
|
155
|
-
|
|
156
147
|
### `PAID_ENABLED`
|
|
157
148
|
|
|
158
149
|
Controls whether Paid tracing is enabled. Set to `false` (case-insensitive) to disable all tracing functionality.
|
|
@@ -189,14 +180,19 @@ Defaults to `https://collector.agentpaid.io:4318/v1/traces`.
|
|
|
189
180
|
|
|
190
181
|
The easiest way to add cost tracking is using the `@paid_tracing` decorator or context manager:
|
|
191
182
|
|
|
183
|
+
> **Important:** Always call `initialize_tracing()` and `paid_autoinstrument()` once at startup before using `paid_tracing`. `initialize_tracing` also accepts optional arguments like OTEL collector endpoint and api key if you want to reroute your tracing somewhere else.
|
|
184
|
+
|
|
192
185
|
#### As a Decorator
|
|
193
186
|
|
|
194
187
|
```python
|
|
195
|
-
from paid.tracing import paid_tracing
|
|
188
|
+
from paid.tracing import paid_tracing, initialize_tracing, paid_autoinstrument
|
|
189
|
+
|
|
190
|
+
initialize_tracing()
|
|
191
|
+
paid_autoinstrument() # instruments all supported libraries by default
|
|
196
192
|
|
|
197
193
|
@paid_tracing("<external_customer_id>", external_product_id="<optional_external_product_id>")
|
|
198
194
|
def some_agent_workflow(): # your function
|
|
199
|
-
# Your logic - use any AI providers
|
|
195
|
+
# Your logic - use any AI providers and send signals with signal().
|
|
200
196
|
# This function is typically an event processor that should lead to AI calls or events emitted as Paid signals
|
|
201
197
|
```
|
|
202
198
|
|
|
@@ -205,7 +201,10 @@ def some_agent_workflow(): # your function
|
|
|
205
201
|
You can also use `paid_tracing` as a context manager with `with` statements:
|
|
206
202
|
|
|
207
203
|
```python
|
|
208
|
-
from paid.tracing import paid_tracing
|
|
204
|
+
from paid.tracing import paid_tracing, initialize_tracing, paid_autoinstrument
|
|
205
|
+
|
|
206
|
+
initialize_tracing()
|
|
207
|
+
paid_autoinstrument() # instruments all supported libraries by default
|
|
209
208
|
|
|
210
209
|
# Synchronous
|
|
211
210
|
with paid_tracing("customer_123", external_product_id="product_456"):
|
|
@@ -218,52 +217,26 @@ async with paid_tracing("customer_123", external_product_id="product_456"):
|
|
|
218
217
|
|
|
219
218
|
Both approaches:
|
|
220
219
|
|
|
221
|
-
- Initialize tracing using your API key you provided to the Paid client, falls back to `PAID_API_KEY` environment variable.
|
|
222
220
|
- Handle both sync and async functions/code blocks
|
|
223
221
|
- Gracefully fall back to normal execution if tracing fails
|
|
224
222
|
- Support the same parameters: `external_customer_id`, `external_product_id`, `tracing_token`, `store_prompt`, `metadata`
|
|
225
223
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
```python
|
|
229
|
-
from paid.tracing import initialize_tracing
|
|
230
|
-
initialize_tracing()
|
|
231
|
-
```
|
|
224
|
+
### Using AI Provider SDKs
|
|
232
225
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
### Using the Paid wrappers
|
|
236
|
-
|
|
237
|
-
You can track usage costs by using Paid wrappers around your AI provider's SDK.
|
|
238
|
-
As of now, the following SDKs' APIs are wrapped:
|
|
239
|
-
|
|
240
|
-
```
|
|
241
|
-
openai
|
|
242
|
-
openai-agents (as a hook)
|
|
243
|
-
anthropic
|
|
244
|
-
langchain (as a hook)
|
|
245
|
-
bedrock (boto3)
|
|
246
|
-
mistral
|
|
247
|
-
gemini (google-genai)
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
Example usage:
|
|
226
|
+
After calling `initialize_tracing()` and `paid_autoinstrument()`, use your AI provider SDKs directly — no wrapper classes needed:
|
|
251
227
|
|
|
252
228
|
```python
|
|
253
229
|
from openai import OpenAI
|
|
254
|
-
from paid.tracing import paid_tracing, initialize_tracing
|
|
255
|
-
from paid.tracing.wrappers.openai import PaidOpenAI
|
|
230
|
+
from paid.tracing import paid_tracing, initialize_tracing, paid_autoinstrument
|
|
256
231
|
|
|
257
232
|
initialize_tracing()
|
|
233
|
+
paid_autoinstrument(libraries=["openai"])
|
|
258
234
|
|
|
259
|
-
|
|
260
|
-
# This is the default and can be omitted
|
|
261
|
-
api_key="<OPENAI_API_KEY>",
|
|
262
|
-
))
|
|
235
|
+
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
263
236
|
|
|
264
237
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
265
238
|
def image_generate():
|
|
266
|
-
response =
|
|
239
|
+
response = openai_client.images.generate(
|
|
267
240
|
model="dall-e-3",
|
|
268
241
|
prompt="A sunset over mountains",
|
|
269
242
|
size="1024x1024",
|
|
@@ -284,13 +257,13 @@ You can attach custom metadata to your traces by passing a `metadata` dictionary
|
|
|
284
257
|
<summary><strong>Python - Decorator</strong></summary>
|
|
285
258
|
|
|
286
259
|
```python
|
|
287
|
-
from paid.tracing import paid_tracing, signal, initialize_tracing
|
|
288
|
-
from paid.tracing.wrappers import PaidOpenAI
|
|
260
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
289
261
|
from openai import OpenAI
|
|
290
262
|
|
|
291
263
|
initialize_tracing()
|
|
264
|
+
paid_autoinstrument(libraries=["openai"])
|
|
292
265
|
|
|
293
|
-
openai_client =
|
|
266
|
+
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
294
267
|
|
|
295
268
|
@paid_tracing(
|
|
296
269
|
"customer_123",
|
|
@@ -320,13 +293,13 @@ process_event(incoming_event)
|
|
|
320
293
|
<summary><strong>Python - Context Manager</strong></summary>
|
|
321
294
|
|
|
322
295
|
```python
|
|
323
|
-
from paid.tracing import paid_tracing, signal, initialize_tracing
|
|
324
|
-
from paid.tracing.wrappers import PaidOpenAI
|
|
296
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
325
297
|
from openai import OpenAI
|
|
326
298
|
|
|
327
299
|
initialize_tracing()
|
|
300
|
+
paid_autoinstrument(libraries=["openai"])
|
|
328
301
|
|
|
329
|
-
openai_client =
|
|
302
|
+
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
330
303
|
|
|
331
304
|
def process_event(event):
|
|
332
305
|
"""Process event with custom metadata"""
|
|
@@ -377,14 +350,13 @@ For maximum convenience, you can use OpenTelemetry auto-instrumentation to autom
|
|
|
377
350
|
|
|
378
351
|
```python
|
|
379
352
|
from paid import Paid
|
|
380
|
-
from paid.tracing import paid_autoinstrument, initialize_tracing
|
|
353
|
+
from paid.tracing import paid_autoinstrument, initialize_tracing, paid_tracing
|
|
381
354
|
from openai import OpenAI
|
|
382
355
|
|
|
383
356
|
# Initialize Paid SDK
|
|
384
357
|
client = Paid(token="PAID_API_KEY")
|
|
385
358
|
initialize_tracing()
|
|
386
|
-
|
|
387
|
-
paid_autoinstrument() # instruments all available: anthropic, gemini, openai, openai-agents, bedrock, langchain, instructor
|
|
359
|
+
paid_autoinstrument(libraries=["openai"])
|
|
388
360
|
|
|
389
361
|
# Now all OpenAI calls will be automatically traced
|
|
390
362
|
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
@@ -441,7 +413,10 @@ Use the `signal()` function which must be called within an active `@paid_tracing
|
|
|
441
413
|
Here's an example of how to use it:
|
|
442
414
|
|
|
443
415
|
```python
|
|
444
|
-
from paid.tracing import paid_tracing, signal
|
|
416
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
417
|
+
|
|
418
|
+
initialize_tracing()
|
|
419
|
+
paid_autoinstrument()
|
|
445
420
|
|
|
446
421
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
447
422
|
def do_work():
|
|
@@ -457,7 +432,10 @@ do_work()
|
|
|
457
432
|
Same approach with context manager:
|
|
458
433
|
|
|
459
434
|
```python
|
|
460
|
-
from paid.tracing import paid_tracing, signal
|
|
435
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
436
|
+
|
|
437
|
+
initialize_tracing()
|
|
438
|
+
paid_autoinstrument()
|
|
461
439
|
|
|
462
440
|
def do_work():
|
|
463
441
|
# ...do some work...
|
|
@@ -480,19 +458,22 @@ as the wrappers and hooks that recorded those costs.
|
|
|
480
458
|
This will look something like this:
|
|
481
459
|
|
|
482
460
|
```python
|
|
483
|
-
from paid.tracing import paid_tracing, signal
|
|
461
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
462
|
+
|
|
463
|
+
initialize_tracing()
|
|
464
|
+
paid_autoinstrument()
|
|
484
465
|
|
|
485
466
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
486
467
|
def do_work():
|
|
487
468
|
# ... your workflow logic
|
|
488
|
-
# ... your AI calls
|
|
469
|
+
# ... your AI calls (auto-instrumented)
|
|
489
470
|
signal(
|
|
490
471
|
event_name="<your_signal_name>",
|
|
491
472
|
data={ }, # optional data (ex. manual cost tracking data)
|
|
492
473
|
enable_cost_tracing=True, # set this flag to associate it with costs
|
|
493
474
|
)
|
|
494
475
|
# ... your workflow logic
|
|
495
|
-
# ... your AI calls
|
|
476
|
+
# ... your AI calls (auto-instrumented, can be sent after the signal too)
|
|
496
477
|
|
|
497
478
|
do_work()
|
|
498
479
|
```
|
|
@@ -511,13 +492,13 @@ For such cases, you can pass a tracing token directly to `@paid_tracing()` or co
|
|
|
511
492
|
The simplest way to implement distributed tracing is to pass the token directly to the decorator or context manager:
|
|
512
493
|
|
|
513
494
|
```python
|
|
514
|
-
from paid.tracing import paid_tracing, signal, generate_tracing_token, initialize_tracing
|
|
515
|
-
from paid.tracing.wrappers.openai import PaidOpenAI
|
|
495
|
+
from paid.tracing import paid_tracing, signal, generate_tracing_token, initialize_tracing, paid_autoinstrument
|
|
516
496
|
from openai import OpenAI
|
|
517
497
|
|
|
518
498
|
initialize_tracing()
|
|
499
|
+
paid_autoinstrument(libraries=["openai"])
|
|
519
500
|
|
|
520
|
-
openai_client =
|
|
501
|
+
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
521
502
|
|
|
522
503
|
# Process 1: Generate token and do initial work
|
|
523
504
|
token = generate_tracing_token()
|
|
@@ -558,14 +539,13 @@ process_part_2()
|
|
|
558
539
|
Using context manager instead of decorator:
|
|
559
540
|
|
|
560
541
|
```python
|
|
561
|
-
from paid.tracing import paid_tracing, signal, generate_tracing_token, initialize_tracing
|
|
562
|
-
from paid.tracing.wrappers.openai import PaidOpenAI
|
|
542
|
+
from paid.tracing import paid_tracing, signal, generate_tracing_token, initialize_tracing, paid_autoinstrument
|
|
563
543
|
from openai import OpenAI
|
|
564
544
|
|
|
565
545
|
initialize_tracing()
|
|
546
|
+
paid_autoinstrument(libraries=["openai"])
|
|
566
547
|
|
|
567
|
-
|
|
568
|
-
openai_client = PaidOpenAI(OpenAI(api_key="<OPENAI_API_KEY>"))
|
|
548
|
+
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
569
549
|
|
|
570
550
|
# Process 1: Generate token and do initial work
|
|
571
551
|
token = generate_tracing_token()
|
|
@@ -610,7 +590,8 @@ signal = Signal(
|
|
|
610
590
|
"amount": 0.002,
|
|
611
591
|
"currency": "USD"
|
|
612
592
|
},
|
|
613
|
-
"gen_ai.response.model": "<ai_model_name>",
|
|
593
|
+
"gen_ai.response.model": "<ai_model_name>", # optional, but will be displayed on UI
|
|
594
|
+
"start_time": "2024-01-01T11:45:00.000Z", # optional, affects where trace is on the timeline
|
|
614
595
|
}
|
|
615
596
|
}
|
|
616
597
|
)
|
|
@@ -621,7 +602,10 @@ client.signals.create_signals(signals=[signal])
|
|
|
621
602
|
Alternatively the same `costData` payload can be passed to OTLP signaling mechanism:
|
|
622
603
|
|
|
623
604
|
```python
|
|
624
|
-
from paid.tracing import paid_tracing, signal
|
|
605
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
606
|
+
|
|
607
|
+
initialize_tracing()
|
|
608
|
+
paid_autoinstrument()
|
|
625
609
|
|
|
626
610
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
627
611
|
def do_work():
|
|
@@ -635,7 +619,8 @@ def do_work():
|
|
|
635
619
|
"amount": 0.002,
|
|
636
620
|
"currency": "USD"
|
|
637
621
|
},
|
|
638
|
-
"gen_ai.response.model": "<ai_model_name>",
|
|
622
|
+
"gen_ai.response.model": "<ai_model_name>", # optional, but will be displayed on UI
|
|
623
|
+
"start_time": "2024-01-01T11:45:00.000Z", # optional, affects where trace is on the timeline
|
|
639
624
|
}
|
|
640
625
|
}
|
|
641
626
|
)
|
|
@@ -675,7 +660,10 @@ client.signals.create_signals(signals=[signal])
|
|
|
675
660
|
Same but via OTEL signaling:
|
|
676
661
|
|
|
677
662
|
```python
|
|
678
|
-
from paid.tracing import paid_tracing, signal
|
|
663
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
664
|
+
|
|
665
|
+
initialize_tracing()
|
|
666
|
+
paid_autoinstrument()
|
|
679
667
|
|
|
680
668
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
681
669
|
def do_work():
|
|
@@ -721,13 +709,12 @@ The `@paid_tracing` decorator automatically handles both sync and async function
|
|
|
721
709
|
|
|
722
710
|
```python
|
|
723
711
|
from openai import AsyncOpenAI
|
|
724
|
-
from paid.tracing import paid_tracing, initialize_tracing
|
|
725
|
-
from paid.tracing.wrappers.openai import PaidAsyncOpenAI
|
|
712
|
+
from paid.tracing import paid_tracing, initialize_tracing, paid_autoinstrument
|
|
726
713
|
|
|
727
714
|
initialize_tracing()
|
|
715
|
+
paid_autoinstrument(libraries=["openai"])
|
|
728
716
|
|
|
729
|
-
|
|
730
|
-
openai_client = PaidAsyncOpenAI(AsyncOpenAI(api_key="<OPENAI_API_KEY>"))
|
|
717
|
+
openai_client = AsyncOpenAI(api_key="<OPENAI_API_KEY>")
|
|
731
718
|
|
|
732
719
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
733
720
|
async def generate_image():
|
|
@@ -749,13 +736,13 @@ await generate_image()
|
|
|
749
736
|
The `signal()` function works seamlessly in async contexts:
|
|
750
737
|
|
|
751
738
|
```python
|
|
752
|
-
from paid.tracing import paid_tracing, signal, initialize_tracing
|
|
753
|
-
from paid.tracing.wrappers.openai import PaidAsyncOpenAI
|
|
739
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
754
740
|
from openai import AsyncOpenAI
|
|
755
741
|
|
|
756
742
|
initialize_tracing()
|
|
743
|
+
paid_autoinstrument(libraries=["openai"])
|
|
757
744
|
|
|
758
|
-
openai_client =
|
|
745
|
+
openai_client = AsyncOpenAI(api_key="<OPENAI_API_KEY>")
|
|
759
746
|
|
|
760
747
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
761
748
|
async def do_work():
|
|
@@ -107,15 +107,6 @@ Your Paid API key for authentication. This is used as a fallback when you don't
|
|
|
107
107
|
export PAID_API_KEY="your_api_key_here"
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
-
You can then initialize the client without passing the token:
|
|
111
|
-
|
|
112
|
-
```python
|
|
113
|
-
from paid import Paid
|
|
114
|
-
|
|
115
|
-
# API key is read from PAID_API_KEY environment variable
|
|
116
|
-
client = Paid()
|
|
117
|
-
```
|
|
118
|
-
|
|
119
110
|
### `PAID_ENABLED`
|
|
120
111
|
|
|
121
112
|
Controls whether Paid tracing is enabled. Set to `false` (case-insensitive) to disable all tracing functionality.
|
|
@@ -152,14 +143,19 @@ Defaults to `https://collector.agentpaid.io:4318/v1/traces`.
|
|
|
152
143
|
|
|
153
144
|
The easiest way to add cost tracking is using the `@paid_tracing` decorator or context manager:
|
|
154
145
|
|
|
146
|
+
> **Important:** Always call `initialize_tracing()` and `paid_autoinstrument()` once at startup before using `paid_tracing`. `initialize_tracing` also accepts optional arguments like OTEL collector endpoint and api key if you want to reroute your tracing somewhere else.
|
|
147
|
+
|
|
155
148
|
#### As a Decorator
|
|
156
149
|
|
|
157
150
|
```python
|
|
158
|
-
from paid.tracing import paid_tracing
|
|
151
|
+
from paid.tracing import paid_tracing, initialize_tracing, paid_autoinstrument
|
|
152
|
+
|
|
153
|
+
initialize_tracing()
|
|
154
|
+
paid_autoinstrument() # instruments all supported libraries by default
|
|
159
155
|
|
|
160
156
|
@paid_tracing("<external_customer_id>", external_product_id="<optional_external_product_id>")
|
|
161
157
|
def some_agent_workflow(): # your function
|
|
162
|
-
# Your logic - use any AI providers
|
|
158
|
+
# Your logic - use any AI providers and send signals with signal().
|
|
163
159
|
# This function is typically an event processor that should lead to AI calls or events emitted as Paid signals
|
|
164
160
|
```
|
|
165
161
|
|
|
@@ -168,7 +164,10 @@ def some_agent_workflow(): # your function
|
|
|
168
164
|
You can also use `paid_tracing` as a context manager with `with` statements:
|
|
169
165
|
|
|
170
166
|
```python
|
|
171
|
-
from paid.tracing import paid_tracing
|
|
167
|
+
from paid.tracing import paid_tracing, initialize_tracing, paid_autoinstrument
|
|
168
|
+
|
|
169
|
+
initialize_tracing()
|
|
170
|
+
paid_autoinstrument() # instruments all supported libraries by default
|
|
172
171
|
|
|
173
172
|
# Synchronous
|
|
174
173
|
with paid_tracing("customer_123", external_product_id="product_456"):
|
|
@@ -181,52 +180,26 @@ async with paid_tracing("customer_123", external_product_id="product_456"):
|
|
|
181
180
|
|
|
182
181
|
Both approaches:
|
|
183
182
|
|
|
184
|
-
- Initialize tracing using your API key you provided to the Paid client, falls back to `PAID_API_KEY` environment variable.
|
|
185
183
|
- Handle both sync and async functions/code blocks
|
|
186
184
|
- Gracefully fall back to normal execution if tracing fails
|
|
187
185
|
- Support the same parameters: `external_customer_id`, `external_product_id`, `tracing_token`, `store_prompt`, `metadata`
|
|
188
186
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
```python
|
|
192
|
-
from paid.tracing import initialize_tracing
|
|
193
|
-
initialize_tracing()
|
|
194
|
-
```
|
|
187
|
+
### Using AI Provider SDKs
|
|
195
188
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
### Using the Paid wrappers
|
|
199
|
-
|
|
200
|
-
You can track usage costs by using Paid wrappers around your AI provider's SDK.
|
|
201
|
-
As of now, the following SDKs' APIs are wrapped:
|
|
202
|
-
|
|
203
|
-
```
|
|
204
|
-
openai
|
|
205
|
-
openai-agents (as a hook)
|
|
206
|
-
anthropic
|
|
207
|
-
langchain (as a hook)
|
|
208
|
-
bedrock (boto3)
|
|
209
|
-
mistral
|
|
210
|
-
gemini (google-genai)
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
Example usage:
|
|
189
|
+
After calling `initialize_tracing()` and `paid_autoinstrument()`, use your AI provider SDKs directly — no wrapper classes needed:
|
|
214
190
|
|
|
215
191
|
```python
|
|
216
192
|
from openai import OpenAI
|
|
217
|
-
from paid.tracing import paid_tracing, initialize_tracing
|
|
218
|
-
from paid.tracing.wrappers.openai import PaidOpenAI
|
|
193
|
+
from paid.tracing import paid_tracing, initialize_tracing, paid_autoinstrument
|
|
219
194
|
|
|
220
195
|
initialize_tracing()
|
|
196
|
+
paid_autoinstrument(libraries=["openai"])
|
|
221
197
|
|
|
222
|
-
|
|
223
|
-
# This is the default and can be omitted
|
|
224
|
-
api_key="<OPENAI_API_KEY>",
|
|
225
|
-
))
|
|
198
|
+
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
226
199
|
|
|
227
200
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
228
201
|
def image_generate():
|
|
229
|
-
response =
|
|
202
|
+
response = openai_client.images.generate(
|
|
230
203
|
model="dall-e-3",
|
|
231
204
|
prompt="A sunset over mountains",
|
|
232
205
|
size="1024x1024",
|
|
@@ -247,13 +220,13 @@ You can attach custom metadata to your traces by passing a `metadata` dictionary
|
|
|
247
220
|
<summary><strong>Python - Decorator</strong></summary>
|
|
248
221
|
|
|
249
222
|
```python
|
|
250
|
-
from paid.tracing import paid_tracing, signal, initialize_tracing
|
|
251
|
-
from paid.tracing.wrappers import PaidOpenAI
|
|
223
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
252
224
|
from openai import OpenAI
|
|
253
225
|
|
|
254
226
|
initialize_tracing()
|
|
227
|
+
paid_autoinstrument(libraries=["openai"])
|
|
255
228
|
|
|
256
|
-
openai_client =
|
|
229
|
+
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
257
230
|
|
|
258
231
|
@paid_tracing(
|
|
259
232
|
"customer_123",
|
|
@@ -283,13 +256,13 @@ process_event(incoming_event)
|
|
|
283
256
|
<summary><strong>Python - Context Manager</strong></summary>
|
|
284
257
|
|
|
285
258
|
```python
|
|
286
|
-
from paid.tracing import paid_tracing, signal, initialize_tracing
|
|
287
|
-
from paid.tracing.wrappers import PaidOpenAI
|
|
259
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
288
260
|
from openai import OpenAI
|
|
289
261
|
|
|
290
262
|
initialize_tracing()
|
|
263
|
+
paid_autoinstrument(libraries=["openai"])
|
|
291
264
|
|
|
292
|
-
openai_client =
|
|
265
|
+
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
293
266
|
|
|
294
267
|
def process_event(event):
|
|
295
268
|
"""Process event with custom metadata"""
|
|
@@ -340,14 +313,13 @@ For maximum convenience, you can use OpenTelemetry auto-instrumentation to autom
|
|
|
340
313
|
|
|
341
314
|
```python
|
|
342
315
|
from paid import Paid
|
|
343
|
-
from paid.tracing import paid_autoinstrument, initialize_tracing
|
|
316
|
+
from paid.tracing import paid_autoinstrument, initialize_tracing, paid_tracing
|
|
344
317
|
from openai import OpenAI
|
|
345
318
|
|
|
346
319
|
# Initialize Paid SDK
|
|
347
320
|
client = Paid(token="PAID_API_KEY")
|
|
348
321
|
initialize_tracing()
|
|
349
|
-
|
|
350
|
-
paid_autoinstrument() # instruments all available: anthropic, gemini, openai, openai-agents, bedrock, langchain, instructor
|
|
322
|
+
paid_autoinstrument(libraries=["openai"])
|
|
351
323
|
|
|
352
324
|
# Now all OpenAI calls will be automatically traced
|
|
353
325
|
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
@@ -404,7 +376,10 @@ Use the `signal()` function which must be called within an active `@paid_tracing
|
|
|
404
376
|
Here's an example of how to use it:
|
|
405
377
|
|
|
406
378
|
```python
|
|
407
|
-
from paid.tracing import paid_tracing, signal
|
|
379
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
380
|
+
|
|
381
|
+
initialize_tracing()
|
|
382
|
+
paid_autoinstrument()
|
|
408
383
|
|
|
409
384
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
410
385
|
def do_work():
|
|
@@ -420,7 +395,10 @@ do_work()
|
|
|
420
395
|
Same approach with context manager:
|
|
421
396
|
|
|
422
397
|
```python
|
|
423
|
-
from paid.tracing import paid_tracing, signal
|
|
398
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
399
|
+
|
|
400
|
+
initialize_tracing()
|
|
401
|
+
paid_autoinstrument()
|
|
424
402
|
|
|
425
403
|
def do_work():
|
|
426
404
|
# ...do some work...
|
|
@@ -443,19 +421,22 @@ as the wrappers and hooks that recorded those costs.
|
|
|
443
421
|
This will look something like this:
|
|
444
422
|
|
|
445
423
|
```python
|
|
446
|
-
from paid.tracing import paid_tracing, signal
|
|
424
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
425
|
+
|
|
426
|
+
initialize_tracing()
|
|
427
|
+
paid_autoinstrument()
|
|
447
428
|
|
|
448
429
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
449
430
|
def do_work():
|
|
450
431
|
# ... your workflow logic
|
|
451
|
-
# ... your AI calls
|
|
432
|
+
# ... your AI calls (auto-instrumented)
|
|
452
433
|
signal(
|
|
453
434
|
event_name="<your_signal_name>",
|
|
454
435
|
data={ }, # optional data (ex. manual cost tracking data)
|
|
455
436
|
enable_cost_tracing=True, # set this flag to associate it with costs
|
|
456
437
|
)
|
|
457
438
|
# ... your workflow logic
|
|
458
|
-
# ... your AI calls
|
|
439
|
+
# ... your AI calls (auto-instrumented, can be sent after the signal too)
|
|
459
440
|
|
|
460
441
|
do_work()
|
|
461
442
|
```
|
|
@@ -474,13 +455,13 @@ For such cases, you can pass a tracing token directly to `@paid_tracing()` or co
|
|
|
474
455
|
The simplest way to implement distributed tracing is to pass the token directly to the decorator or context manager:
|
|
475
456
|
|
|
476
457
|
```python
|
|
477
|
-
from paid.tracing import paid_tracing, signal, generate_tracing_token, initialize_tracing
|
|
478
|
-
from paid.tracing.wrappers.openai import PaidOpenAI
|
|
458
|
+
from paid.tracing import paid_tracing, signal, generate_tracing_token, initialize_tracing, paid_autoinstrument
|
|
479
459
|
from openai import OpenAI
|
|
480
460
|
|
|
481
461
|
initialize_tracing()
|
|
462
|
+
paid_autoinstrument(libraries=["openai"])
|
|
482
463
|
|
|
483
|
-
openai_client =
|
|
464
|
+
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
484
465
|
|
|
485
466
|
# Process 1: Generate token and do initial work
|
|
486
467
|
token = generate_tracing_token()
|
|
@@ -521,14 +502,13 @@ process_part_2()
|
|
|
521
502
|
Using context manager instead of decorator:
|
|
522
503
|
|
|
523
504
|
```python
|
|
524
|
-
from paid.tracing import paid_tracing, signal, generate_tracing_token, initialize_tracing
|
|
525
|
-
from paid.tracing.wrappers.openai import PaidOpenAI
|
|
505
|
+
from paid.tracing import paid_tracing, signal, generate_tracing_token, initialize_tracing, paid_autoinstrument
|
|
526
506
|
from openai import OpenAI
|
|
527
507
|
|
|
528
508
|
initialize_tracing()
|
|
509
|
+
paid_autoinstrument(libraries=["openai"])
|
|
529
510
|
|
|
530
|
-
|
|
531
|
-
openai_client = PaidOpenAI(OpenAI(api_key="<OPENAI_API_KEY>"))
|
|
511
|
+
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
|
|
532
512
|
|
|
533
513
|
# Process 1: Generate token and do initial work
|
|
534
514
|
token = generate_tracing_token()
|
|
@@ -573,7 +553,8 @@ signal = Signal(
|
|
|
573
553
|
"amount": 0.002,
|
|
574
554
|
"currency": "USD"
|
|
575
555
|
},
|
|
576
|
-
"gen_ai.response.model": "<ai_model_name>",
|
|
556
|
+
"gen_ai.response.model": "<ai_model_name>", # optional, but will be displayed on UI
|
|
557
|
+
"start_time": "2024-01-01T11:45:00.000Z", # optional, affects where trace is on the timeline
|
|
577
558
|
}
|
|
578
559
|
}
|
|
579
560
|
)
|
|
@@ -584,7 +565,10 @@ client.signals.create_signals(signals=[signal])
|
|
|
584
565
|
Alternatively the same `costData` payload can be passed to OTLP signaling mechanism:
|
|
585
566
|
|
|
586
567
|
```python
|
|
587
|
-
from paid.tracing import paid_tracing, signal
|
|
568
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
569
|
+
|
|
570
|
+
initialize_tracing()
|
|
571
|
+
paid_autoinstrument()
|
|
588
572
|
|
|
589
573
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
590
574
|
def do_work():
|
|
@@ -598,7 +582,8 @@ def do_work():
|
|
|
598
582
|
"amount": 0.002,
|
|
599
583
|
"currency": "USD"
|
|
600
584
|
},
|
|
601
|
-
"gen_ai.response.model": "<ai_model_name>",
|
|
585
|
+
"gen_ai.response.model": "<ai_model_name>", # optional, but will be displayed on UI
|
|
586
|
+
"start_time": "2024-01-01T11:45:00.000Z", # optional, affects where trace is on the timeline
|
|
602
587
|
}
|
|
603
588
|
}
|
|
604
589
|
)
|
|
@@ -638,7 +623,10 @@ client.signals.create_signals(signals=[signal])
|
|
|
638
623
|
Same but via OTEL signaling:
|
|
639
624
|
|
|
640
625
|
```python
|
|
641
|
-
from paid.tracing import paid_tracing, signal
|
|
626
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
627
|
+
|
|
628
|
+
initialize_tracing()
|
|
629
|
+
paid_autoinstrument()
|
|
642
630
|
|
|
643
631
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
644
632
|
def do_work():
|
|
@@ -684,13 +672,12 @@ The `@paid_tracing` decorator automatically handles both sync and async function
|
|
|
684
672
|
|
|
685
673
|
```python
|
|
686
674
|
from openai import AsyncOpenAI
|
|
687
|
-
from paid.tracing import paid_tracing, initialize_tracing
|
|
688
|
-
from paid.tracing.wrappers.openai import PaidAsyncOpenAI
|
|
675
|
+
from paid.tracing import paid_tracing, initialize_tracing, paid_autoinstrument
|
|
689
676
|
|
|
690
677
|
initialize_tracing()
|
|
678
|
+
paid_autoinstrument(libraries=["openai"])
|
|
691
679
|
|
|
692
|
-
|
|
693
|
-
openai_client = PaidAsyncOpenAI(AsyncOpenAI(api_key="<OPENAI_API_KEY>"))
|
|
680
|
+
openai_client = AsyncOpenAI(api_key="<OPENAI_API_KEY>")
|
|
694
681
|
|
|
695
682
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
696
683
|
async def generate_image():
|
|
@@ -712,13 +699,13 @@ await generate_image()
|
|
|
712
699
|
The `signal()` function works seamlessly in async contexts:
|
|
713
700
|
|
|
714
701
|
```python
|
|
715
|
-
from paid.tracing import paid_tracing, signal, initialize_tracing
|
|
716
|
-
from paid.tracing.wrappers.openai import PaidAsyncOpenAI
|
|
702
|
+
from paid.tracing import paid_tracing, signal, initialize_tracing, paid_autoinstrument
|
|
717
703
|
from openai import AsyncOpenAI
|
|
718
704
|
|
|
719
705
|
initialize_tracing()
|
|
706
|
+
paid_autoinstrument(libraries=["openai"])
|
|
720
707
|
|
|
721
|
-
openai_client =
|
|
708
|
+
openai_client = AsyncOpenAI(api_key="<OPENAI_API_KEY>")
|
|
722
709
|
|
|
723
710
|
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
|
|
724
711
|
async def do_work():
|
|
@@ -4,7 +4,7 @@ dynamic = ["version"]
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "paid-python"
|
|
7
|
-
version = "1.0
|
|
7
|
+
version = "1.2.0"
|
|
8
8
|
description = ""
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = []
|
|
@@ -37,7 +37,7 @@ Repository = 'https://github.com/paid-ai/paid-python'
|
|
|
37
37
|
python = ">=3.10,<3.14"
|
|
38
38
|
httpx = ">=0.21.2"
|
|
39
39
|
mutagen = ">=1.47.0"
|
|
40
|
-
openinference-instrumentation-anthropic = ">=0.1.20"
|
|
40
|
+
openinference-instrumentation-anthropic = ">=0.1.20,<1.0.0"
|
|
41
41
|
openinference-instrumentation-bedrock = ">=0.1.0"
|
|
42
42
|
openinference-instrumentation-google-genai = ">=0.1.8"
|
|
43
43
|
openinference-instrumentation-instructor = ">=0.1.0"
|