paid-python 0.1.0__py3-none-any.whl → 0.1.1__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.
@@ -62,7 +62,7 @@ class paid_tracing:
62
62
 
63
63
  def __init__(
64
64
  self,
65
- external_customer_id: str,
65
+ external_customer_id: Optional[str] = None,
66
66
  *,
67
67
  external_agent_id: Optional[str] = None,
68
68
  tracing_token: Optional[int] = None,
paid/tracing/tracing.py CHANGED
@@ -258,7 +258,7 @@ def get_paid_tracer() -> trace.Tracer:
258
258
 
259
259
 
260
260
  def trace_sync_(
261
- external_customer_id: str,
261
+ external_customer_id: Optional[str],
262
262
  fn: Callable[..., T],
263
263
  external_agent_id: Optional[str] = None,
264
264
  tracing_token: Optional[int] = None,
@@ -316,9 +316,6 @@ def trace_sync_(
316
316
  tracer = get_paid_tracer()
317
317
  logger.info(f"Creating span for external_customer_id: {external_customer_id}")
318
318
  with tracer.start_as_current_span("parent_span", context=ctx) as span:
319
- span.set_attribute("external_customer_id", external_customer_id)
320
- if external_agent_id:
321
- span.set_attribute("external_agent_id", external_agent_id)
322
319
  try:
323
320
  result = fn(*args, **kwargs)
324
321
  span.set_status(Status(StatusCode.OK))
@@ -335,7 +332,7 @@ def trace_sync_(
335
332
 
336
333
 
337
334
  async def trace_async_(
338
- external_customer_id: str,
335
+ external_customer_id: Optional[str],
339
336
  fn: Callable[..., Union[T, Awaitable[T]]],
340
337
  external_agent_id: Optional[str] = None,
341
338
  tracing_token: Optional[int] = None,
@@ -393,9 +390,6 @@ async def trace_async_(
393
390
  tracer = get_paid_tracer()
394
391
  logger.info(f"Creating span for external_customer_id: {external_customer_id}")
395
392
  with tracer.start_as_current_span("parent_span", context=ctx) as span:
396
- span.set_attribute("external_customer_id", external_customer_id)
397
- if external_agent_id:
398
- span.set_attribute("external_agent_id", external_agent_id)
399
393
  try:
400
394
  if asyncio.iscoroutinefunction(fn):
401
395
  result = await fn(*args, **kwargs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: paid-python
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary:
5
5
  Requires-Python: >=3.9,<3.14
6
6
  Classifier: Intended Audience :: Developers
@@ -205,6 +205,98 @@ def image_generate():
205
205
  image_generate()
206
206
  ```
207
207
 
208
+ ### Passing User Metadata
209
+
210
+ You can attach custom metadata to your traces by passing a `metadata` dictionary to the `paid_tracing()` decorator or context manager. This metadata will be stored with the trace and can be used to filter and query traces later.
211
+
212
+ <Tabs>
213
+ <Tab title="Python - Decorator">
214
+ ```python
215
+ from paid.tracing import paid_tracing, signal
216
+ from paid.tracing.wrappers import PaidOpenAI
217
+ from openai import OpenAI
218
+
219
+ openai_client = PaidOpenAI(OpenAI(api_key="<OPENAI_API_KEY>"))
220
+
221
+ @paid_tracing(
222
+ "customer_123",
223
+ "agent_123",
224
+ metadata={
225
+ "campaign_id": "campaign_456",
226
+ "environment": "production",
227
+ "user_tier": "enterprise"
228
+ }
229
+ )
230
+ def process_event(event):
231
+ """Process event with custom metadata"""
232
+ response = openai_client.chat.completions.create(
233
+ model="gpt-4",
234
+ messages=[{"role": "user", "content": event.content}]
235
+ )
236
+
237
+ signal("event_processed", enable_cost_tracing=True)
238
+ return response
239
+
240
+ process_event(incoming_event)
241
+ ```
242
+ </Tab>
243
+
244
+ <Tab title="Python - Context Manager">
245
+ ```python
246
+ from paid.tracing import paid_tracing, signal
247
+ from paid.tracing.wrappers import PaidOpenAI
248
+ from openai import OpenAI
249
+
250
+ openai_client = PaidOpenAI(OpenAI(api_key="<OPENAI_API_KEY>"))
251
+
252
+ def process_event(event):
253
+ """Process event with custom metadata"""
254
+ response = openai_client.chat.completions.create(
255
+ model="gpt-4",
256
+ messages=[{"role": "user", "content": event.content}]
257
+ )
258
+
259
+ signal("event_processed", enable_cost_tracing=True)
260
+ return response
261
+
262
+ # Pass metadata to context manager
263
+ with paid_tracing(
264
+ "customer_123",
265
+ external_agent_id="agent_123",
266
+ metadata={
267
+ "campaign_id": "campaign_456",
268
+ "environment": "production",
269
+ "user_tier": "enterprise"
270
+ }
271
+ ):
272
+ process_event(incoming_event)
273
+ ```
274
+ </Tab>
275
+
276
+ <Tab title="Node.js">
277
+ ```typescript
278
+ // Metadata support is not yet available in the Node.js SDK.
279
+ // Please use Python for passing custom metadata to traces.
280
+ ```
281
+ </Tab>
282
+ </Tabs>
283
+
284
+ #### Querying Traces by Metadata
285
+
286
+ Once you've added metadata to your traces, you can filter traces using the metadata parameter in the traces API endpoint:
287
+
288
+ ```bash
289
+ # Filter by single metadata field
290
+ curl -G "https://api.paid.ai/api/organizations/{orgId}/traces" \
291
+ --data-urlencode 'metadata={"campaign_id":"campaign_456"}' \
292
+ -H "Authorization: Bearer YOUR_API_KEY"
293
+
294
+ # Filter by multiple metadata fields (all must match)
295
+ curl -G "https://api.paid.ai/api/organizations/{orgId}/traces" \
296
+ --data-urlencode 'metadata={"campaign_id":"campaign_456","environment":"production"}' \
297
+ -H "Authorization: Bearer YOUR_API_KEY"
298
+ ```
299
+
208
300
  ### Auto-Instrumentation (OpenTelemetry Instrumentors)
209
301
 
210
302
  For maximum convenience, you can use OpenTelemetry auto-instrumentation to automatically track costs without modifying your AI library calls. This approach uses official OpenTelemetry instrumentors for supported AI libraries.
@@ -38,10 +38,10 @@ paid/orders/raw_client.py,sha256=650e1Sj2vi9KVJc15M3ENXIKYoth0qMz66dzvXy1Sb4,162
38
38
  paid/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
39
  paid/tracing/__init__.py,sha256=IP6OkV885_xlK1H68RxGTX_IhpVAkY266zsWgnQKKTs,440
40
40
  paid/tracing/autoinstrumentation.py,sha256=p57bU87x1Xi-nb_2C4O56tcgfvN2UYZAd9pJ0Vyh9Nw,6765
41
- paid/tracing/context_manager.py,sha256=ZVsmum4np_Eyub1_D0D5ChhvdBWnkFBFqzZHxSsljdU,9716
41
+ paid/tracing/context_manager.py,sha256=qXWYwUisUnAGUjsGNDRR4b0m8DMiu5IfNVnBhE4bwlE,9733
42
42
  paid/tracing/distributed_tracing.py,sha256=CpUWpHai-4LxLLHbGxz41r9h5wLG-dC83YL5Vg29OBI,3967
43
43
  paid/tracing/signal.py,sha256=PfYxF6EFQS8j7RY5_C5NXrCBVu9Hq2E2tyG4fdQScJk,3252
44
- paid/tracing/tracing.py,sha256=Xtue-_vuAKLnZ1l6d-tSj9o0UWmMPgXggTVgXYb1Zz4,16230
44
+ paid/tracing/tracing.py,sha256=Pqf7A9I0YU_sk8KEZlS1DF8-hdhNmqGtmfumoX_9jvQ,15878
45
45
  paid/tracing/wrappers/__init__.py,sha256=IIleLB_JUbzLw7FshrU2VHZAKF3dZHMGy1O5zCBwwqM,1588
46
46
  paid/tracing/wrappers/anthropic/__init__.py,sha256=_x1fjySAQxuT5cIGO_jU09LiGcZH-WQLqKg8mUFAu2w,115
47
47
  paid/tracing/wrappers/anthropic/anthropicWrapper.py,sha256=pGchbOb41CbTxc7H8xXoM-LjR085spqrzXqCVC_rrFk,4913
@@ -98,7 +98,7 @@ paid/usage/__init__.py,sha256=_VhToAyIt_5axN6CLJwtxg3-CO7THa_23pbUzqhXJa4,85
98
98
  paid/usage/client.py,sha256=280WJuepoovk3BAVbAx2yN2Q_qBdvx3CcPkLu8lXslc,3030
99
99
  paid/usage/raw_client.py,sha256=2acg5C4lxuZodZjepU9QYF0fmBxgG-3ZgXs1zUJG-wM,3709
100
100
  paid/version.py,sha256=QIpDFnOrxMxrs86eL0iNH0mSZ1DO078wWHYY9TYAoew,78
101
- paid_python-0.1.0.dist-info/LICENSE,sha256=Nz4baY1zvv0Qy7lqrQtbaiMhmEeGr2Q7A93aqzpml4c,1071
102
- paid_python-0.1.0.dist-info/METADATA,sha256=liDYbzbDdhe3sBUeAuPaBbD7P99Q3YLYClqGqIu9pYs,18729
103
- paid_python-0.1.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
104
- paid_python-0.1.0.dist-info/RECORD,,
101
+ paid_python-0.1.1.dist-info/LICENSE,sha256=Nz4baY1zvv0Qy7lqrQtbaiMhmEeGr2Q7A93aqzpml4c,1071
102
+ paid_python-0.1.1.dist-info/METADATA,sha256=YMILAQJcALoQrcvdhyNUjn90d8nNGhJX9bJIVyf0tNw,21580
103
+ paid_python-0.1.1.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
104
+ paid_python-0.1.1.dist-info/RECORD,,