netra-sdk 0.1.6__tar.gz → 0.1.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.

Potentially problematic release.


This version of netra-sdk might be problematic. Click here for more details.

Files changed (43) hide show
  1. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/PKG-INFO +20 -22
  2. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/README.md +19 -21
  3. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/__init__.py +5 -5
  4. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/config.py +5 -0
  5. netra_sdk-0.1.6/netra/session.py → netra_sdk-0.1.7/netra/span_wrapper.py +23 -38
  6. netra_sdk-0.1.7/netra/version.py +1 -0
  7. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/pyproject.toml +1 -1
  8. netra_sdk-0.1.6/netra/version.py +0 -1
  9. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/LICENCE +0 -0
  10. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/anonymizer/__init__.py +0 -0
  11. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/anonymizer/anonymizer.py +0 -0
  12. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/anonymizer/base.py +0 -0
  13. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/anonymizer/fp_anonymizer.py +0 -0
  14. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/decorators.py +0 -0
  15. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/exceptions/__init__.py +0 -0
  16. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/exceptions/injection.py +0 -0
  17. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/exceptions/pii.py +0 -0
  18. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/input_scanner.py +0 -0
  19. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/__init__.py +0 -0
  20. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/aiohttp/__init__.py +0 -0
  21. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/aiohttp/version.py +0 -0
  22. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/cohere/__init__.py +0 -0
  23. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/cohere/version.py +0 -0
  24. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/google_genai/__init__.py +0 -0
  25. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/google_genai/config.py +0 -0
  26. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/google_genai/utils.py +0 -0
  27. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/google_genai/version.py +0 -0
  28. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/httpx/__init__.py +0 -0
  29. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/httpx/version.py +0 -0
  30. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/instruments.py +0 -0
  31. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/mistralai/__init__.py +0 -0
  32. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/mistralai/config.py +0 -0
  33. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/mistralai/utils.py +0 -0
  34. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/mistralai/version.py +0 -0
  35. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/weaviate/__init__.py +0 -0
  36. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/instrumentation/weaviate/version.py +0 -0
  37. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/pii.py +0 -0
  38. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/processors/__init__.py +0 -0
  39. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/processors/error_detection_processor.py +0 -0
  40. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/processors/session_span_processor.py +0 -0
  41. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/scanner.py +0 -0
  42. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/session_manager.py +0 -0
  43. {netra_sdk-0.1.6 → netra_sdk-0.1.7}/netra/tracer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: netra-sdk
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Summary: A Python SDK for AI application observability that provides OpenTelemetry-based monitoring, tracing, and PII protection for LLM and vector database applications. Enables easy instrumentation, session tracking, and privacy-focused data collection for AI systems in production environments.
5
5
  License: Apache-2.0
6
6
  Keywords: netra,tracing,observability,sdk,ai,llm,vector,database
@@ -402,46 +402,44 @@ Netra.set_custom_event(event_name="conversion", attributes={
402
402
  "value": 99.99
403
403
  })
404
404
  ```
405
- ## 🔄 Custom Session Tracking
405
+ ## 🔄 Custom Span Tracking
406
406
 
407
- Use the custom session tracking utility to track external API calls with detailed observability:
407
+ Use the custom span tracking utility to track external API calls with detailed observability:
408
408
 
409
409
  ```python
410
- from netra import Netra, Session
411
- from netra.session import UsageModel
412
-
413
- # Start a new session
414
- with Netra.start_session("image_generation") as session:
415
- # Set session attributes
416
- session.set_prompt("A beautiful sunset over mountains")
417
- session.set_negative_prompt("blurry, low quality")
418
- session.set_height("1024")
419
- session.set_width("1024")
420
- session.set_model("dall-e-3")
421
- session.set_llm_system("openai")
410
+ from netra import Netra, UsageModel
411
+
412
+ # Start a new span
413
+ with Netra.start_span("image_generation") as span:
414
+ # Set span attributes
415
+ span.set_prompt("A beautiful sunset over mountains")
416
+ span.set_negative_prompt("blurry, low quality")
417
+ span.set_model("dall-e-3")
418
+ span.set_llm_system("openai")
422
419
 
423
420
  # Set usage data with UsageModel
424
421
  usage_data = [
425
422
  UsageModel(
426
423
  model="dall-e-3",
427
- type="image_generation",
428
- unit_used=1,
424
+ usage_type="image_generation",
425
+ units_used=1,
429
426
  cost_in_usd=0.02
430
427
  )
431
428
  ]
432
- session.set_usage(usage_data)
429
+ span.set_usage(usage_data)
433
430
 
434
431
  # Your API calls here
435
432
  # ...
436
433
 
437
434
  # Set custom attributes
438
- session.set_attribute("custom_key", "custom_value")
435
+ span.set_attribute("custom_key", "custom_value")
439
436
 
440
437
  # Add events
441
- session.add_event("generation_started", {"step": 1, "status": "processing"})
442
- session.add_event("processing_completed", {"step": "rendering"})
438
+ span.add_event("generation_started", {"step": "1", "status": "processing"})
439
+ span.add_event("processing_completed", {"step": "rendering"})
443
440
 
444
- # Session automatically captures duration, status, and any errors
441
+ # Get the current active open telemetry span
442
+ current_span = span.get_current_span()
445
443
  ```
446
444
 
447
445
  ## 🔧 Advanced Configuration
@@ -326,46 +326,44 @@ Netra.set_custom_event(event_name="conversion", attributes={
326
326
  "value": 99.99
327
327
  })
328
328
  ```
329
- ## 🔄 Custom Session Tracking
329
+ ## 🔄 Custom Span Tracking
330
330
 
331
- Use the custom session tracking utility to track external API calls with detailed observability:
331
+ Use the custom span tracking utility to track external API calls with detailed observability:
332
332
 
333
333
  ```python
334
- from netra import Netra, Session
335
- from netra.session import UsageModel
336
-
337
- # Start a new session
338
- with Netra.start_session("image_generation") as session:
339
- # Set session attributes
340
- session.set_prompt("A beautiful sunset over mountains")
341
- session.set_negative_prompt("blurry, low quality")
342
- session.set_height("1024")
343
- session.set_width("1024")
344
- session.set_model("dall-e-3")
345
- session.set_llm_system("openai")
334
+ from netra import Netra, UsageModel
335
+
336
+ # Start a new span
337
+ with Netra.start_span("image_generation") as span:
338
+ # Set span attributes
339
+ span.set_prompt("A beautiful sunset over mountains")
340
+ span.set_negative_prompt("blurry, low quality")
341
+ span.set_model("dall-e-3")
342
+ span.set_llm_system("openai")
346
343
 
347
344
  # Set usage data with UsageModel
348
345
  usage_data = [
349
346
  UsageModel(
350
347
  model="dall-e-3",
351
- type="image_generation",
352
- unit_used=1,
348
+ usage_type="image_generation",
349
+ units_used=1,
353
350
  cost_in_usd=0.02
354
351
  )
355
352
  ]
356
- session.set_usage(usage_data)
353
+ span.set_usage(usage_data)
357
354
 
358
355
  # Your API calls here
359
356
  # ...
360
357
 
361
358
  # Set custom attributes
362
- session.set_attribute("custom_key", "custom_value")
359
+ span.set_attribute("custom_key", "custom_value")
363
360
 
364
361
  # Add events
365
- session.add_event("generation_started", {"step": 1, "status": "processing"})
366
- session.add_event("processing_completed", {"step": "rendering"})
362
+ span.add_event("generation_started", {"step": "1", "status": "processing"})
363
+ span.add_event("processing_completed", {"step": "rendering"})
367
364
 
368
- # Session automatically captures duration, status, and any errors
365
+ # Get the current active open telemetry span
366
+ current_span = span.get_current_span()
369
367
  ```
370
368
 
371
369
  ## 🔧 Advanced Configuration
@@ -8,8 +8,8 @@ from .config import Config
8
8
 
9
9
  # Instrumentor functions
10
10
  from .instrumentation import init_instrumentations
11
- from .session import Session
12
11
  from .session_manager import SessionManager
12
+ from .span_wrapper import SpanWrapper, UsageModel
13
13
  from .tracer import Tracer
14
14
 
15
15
  logger = logging.getLogger(__name__)
@@ -133,16 +133,16 @@ class Netra:
133
133
  SessionManager.set_custom_event(event_name, attributes)
134
134
 
135
135
  @classmethod
136
- def start_session(
136
+ def start_span(
137
137
  cls,
138
138
  name: str,
139
139
  attributes: Optional[Dict[str, str]] = None,
140
140
  module_name: str = "combat_sdk",
141
- ) -> Session:
141
+ ) -> SpanWrapper:
142
142
  """
143
143
  Start a new session.
144
144
  """
145
- return Session(name, attributes, module_name)
145
+ return SpanWrapper(name, attributes, module_name)
146
146
 
147
147
 
148
- __all__ = ["Netra"]
148
+ __all__ = ["Netra", "UsageModel"]
@@ -86,6 +86,11 @@ class Config:
86
86
  env_tc = os.getenv("NETRA_TRACE_CONTENT")
87
87
  self.trace_content = False if (env_tc is not None and env_tc.lower() in ("0", "false")) else True
88
88
 
89
+ if not self.trace_content:
90
+ os.environ["TRACELOOP_TRACE_CONTENT"] = "false"
91
+ else:
92
+ os.environ["TRACELOOP_TRACE_CONTENT"] = "true"
93
+
89
94
  # 7. Environment: param override, else env
90
95
  if environment is not None:
91
96
  self.environment = environment
@@ -18,8 +18,8 @@ logger = logging.getLogger(__name__)
18
18
 
19
19
  class UsageModel(BaseModel): # type: ignore[misc]
20
20
  model: str
21
- type: str
22
- unit_used: Optional[int] = None
21
+ usage_type: str
22
+ units_used: Optional[int] = None
23
23
  cost_in_usd: Optional[float] = None
24
24
 
25
25
 
@@ -28,27 +28,24 @@ class ATTRIBUTE:
28
28
  MODEL = "model"
29
29
  PROMPT = "prompt"
30
30
  NEGATIVE_PROMPT = "negative_prompt"
31
- HEIGHT = "height"
32
- WIDTH = "width"
33
- OUTPUT_TYPE = "output_type"
34
31
  USAGE = "usage"
35
32
  STATUS = "status"
36
33
  DURATION_MS = "duration_ms"
37
34
  ERROR_MESSAGE = "error_message"
38
35
 
39
36
 
40
- class Session:
37
+ class SpanWrapper:
41
38
  """
42
39
  Context manager for tracking observability data for external API calls.
43
40
 
44
41
  Usage:
45
- with combat.start_session("video_gen_task") as session:
46
- session.set_prompt("A cat playing piano").set_image_height("1024")
42
+ with combat.start_span("video_gen_task") as span:
43
+ span.set_prompt("A cat playing piano").set_image_height("1024")
47
44
 
48
45
  # External API call
49
46
  result = external_api.generate_video(...)
50
47
 
51
- session.set_usage(usage_data)
48
+ span.set_usage(usage_data)
52
49
  """
53
50
 
54
51
  def __init__(self, name: str, attributes: Optional[Dict[str, str]] = None, module_name: str = "combat_sdk"):
@@ -65,8 +62,8 @@ class Session:
65
62
  self.span: Optional[trace.Span] = None
66
63
  self.context_token: Optional[Any] = None
67
64
 
68
- def __enter__(self) -> "Session":
69
- """Start the session, begin time tracking, and create OpenTelemetry span."""
65
+ def __enter__(self) -> "SpanWrapper":
66
+ """Start the span wrapper, begin time tracking, and create OpenTelemetry span."""
70
67
  self.start_time = time.time()
71
68
 
72
69
  # Create OpenTelemetry span
@@ -76,11 +73,11 @@ class Session:
76
73
  ctx = set_span_in_context(self.span)
77
74
  self.context_token = context_api.attach(ctx)
78
75
 
79
- logger.info(f"Started session: {self.name}")
76
+ logger.info(f"Started span wrapper: {self.name}")
80
77
  return self
81
78
 
82
79
  def __exit__(self, exc_type: Optional[type], exc_val: Optional[Exception], exc_tb: Any) -> Literal[False]:
83
- """End the session, calculate duration, handle errors, and close OpenTelemetry span."""
80
+ """End the span wrapper, calculate duration, handle errors, and close OpenTelemetry span."""
84
81
  self.end_time = time.time()
85
82
  duration_ms = (self.end_time - self.start_time) * 1000 if self.start_time is not None else None
86
83
 
@@ -101,7 +98,7 @@ class Session:
101
98
  self.span.set_status(Status(StatusCode.ERROR, self.error_message))
102
99
  if exc_val is not None:
103
100
  self.span.record_exception(exc_val)
104
- logger.error(f"Session {self.name} failed: {self.error_message}")
101
+ logger.error(f"Span wrapper {self.name} failed: {self.error_message}")
105
102
 
106
103
  self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.STATUS}", self.status)
107
104
 
@@ -117,15 +114,15 @@ class Session:
117
114
  context_api.detach(self.context_token)
118
115
 
119
116
  logger.info(
120
- f"Ended session: {self.name} (Status: {self.status}, Duration: {duration_ms:.2f}ms)"
117
+ f"Ended span wrapper: {self.name} (Status: {self.status}, Duration: {duration_ms:.2f}ms)"
121
118
  if duration_ms is not None
122
- else f"Ended session: {self.name} (Status: {self.status})"
119
+ else f"Ended span wrapper: {self.name} (Status: {self.status})"
123
120
  )
124
121
 
125
122
  # Don't suppress exceptions
126
123
  return False
127
124
 
128
- def set_attribute(self, key: str, value: str) -> "Session":
125
+ def set_attribute(self, key: str, value: str) -> "SpanWrapper":
129
126
  """Set a single attribute and return self for method chaining."""
130
127
  self.attributes[key] = value
131
128
  # Also set on the span if it exists
@@ -133,41 +130,29 @@ class Session:
133
130
  self.span.set_attribute(key, value)
134
131
  return self
135
132
 
136
- def set_prompt(self, prompt: str) -> "Session":
133
+ def set_prompt(self, prompt: str) -> "SpanWrapper":
137
134
  """Set the input prompt."""
138
135
  return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.PROMPT}", prompt)
139
136
 
140
- def set_negative_prompt(self, negative_prompt: str) -> "Session":
137
+ def set_negative_prompt(self, negative_prompt: str) -> "SpanWrapper":
141
138
  """Set the negative prompt."""
142
139
  return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.NEGATIVE_PROMPT}", negative_prompt)
143
140
 
144
- def set_height(self, height: str) -> "Session":
145
- """Set the height."""
146
- return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.HEIGHT}", height)
147
-
148
- def set_width(self, width: str) -> "Session":
149
- """Set the width."""
150
- return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.WIDTH}", width)
151
-
152
- def set_output_type(self, output_type: str) -> "Session":
153
- """Set the output type."""
154
- return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.OUTPUT_TYPE}", output_type)
155
-
156
- def set_usage(self, usage: List[UsageModel]) -> "Session":
141
+ def set_usage(self, usage: List[UsageModel]) -> "SpanWrapper":
157
142
  """Set the usage data as a JSON string."""
158
143
  usage_dict = [u.model_dump() for u in usage]
159
144
  usage_json = json.dumps(usage_dict)
160
145
  return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.USAGE}", usage_json)
161
146
 
162
- def set_model(self, model: str) -> "Session":
147
+ def set_model(self, model: str) -> "SpanWrapper":
163
148
  """Set the model used."""
164
149
  return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.MODEL}", model)
165
150
 
166
- def set_llm_system(self, system: str) -> "Session":
151
+ def set_llm_system(self, system: str) -> "SpanWrapper":
167
152
  """Set the LLM system used."""
168
153
  return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.LLM_SYSTEM}", system)
169
154
 
170
- def set_error(self, error_message: str) -> "Session":
155
+ def set_error(self, error_message: str) -> "SpanWrapper":
171
156
  """Manually set an error message."""
172
157
  self.status = "error"
173
158
  self.error_message = error_message
@@ -175,14 +160,14 @@ class Session:
175
160
  self.span.set_status(Status(StatusCode.ERROR, error_message))
176
161
  return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.ERROR_MESSAGE}", error_message)
177
162
 
178
- def set_success(self) -> "Session":
179
- """Manually mark the session as successful."""
163
+ def set_success(self) -> "SpanWrapper":
164
+ """Manually mark the span wrapper as successful."""
180
165
  self.status = "success"
181
166
  if self.span:
182
167
  self.span.set_status(Status(StatusCode.OK))
183
168
  return self
184
169
 
185
- def add_event(self, name: str, attributes: Optional[Dict[str, str]] = None) -> "Session":
170
+ def add_event(self, name: str, attributes: Optional[Dict[str, str]] = None) -> "SpanWrapper":
186
171
  """Add an event to the span."""
187
172
  if self.span:
188
173
  self.span.add_event(name, attributes or {})
@@ -0,0 +1 @@
1
+ __version__ = "0.1.7"
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [project]
6
6
  name = "netra-sdk"
7
- version = "0.1.6"
7
+ version = "0.1.7"
8
8
  description = "A Python SDK for AI application observability that provides OpenTelemetry-based monitoring, tracing, and PII protection for LLM and vector database applications. Enables easy instrumentation, session tracking, and privacy-focused data collection for AI systems in production environments."
9
9
  authors = [
10
10
  {name = "Sooraj Thomas",email = "sooraj@keyvalue.systems"}
@@ -1 +0,0 @@
1
- __version__ = "0.1.6"
File without changes
File without changes
File without changes
File without changes
File without changes