netra-sdk 0.1.43__tar.gz → 0.1.44__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 (57) hide show
  1. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/PKG-INFO +1 -1
  2. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/tracer.py +63 -39
  3. netra_sdk-0.1.44/netra/version.py +1 -0
  4. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/pyproject.toml +1 -1
  5. netra_sdk-0.1.43/netra/version.py +0 -1
  6. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/LICENCE +0 -0
  7. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/README.md +0 -0
  8. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/__init__.py +0 -0
  9. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/anonymizer/__init__.py +0 -0
  10. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/anonymizer/anonymizer.py +0 -0
  11. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/anonymizer/base.py +0 -0
  12. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/anonymizer/fp_anonymizer.py +0 -0
  13. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/config.py +0 -0
  14. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/decorators.py +0 -0
  15. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/exceptions/__init__.py +0 -0
  16. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/exceptions/injection.py +0 -0
  17. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/exceptions/pii.py +0 -0
  18. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/input_scanner.py +0 -0
  19. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/__init__.py +0 -0
  20. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/aiohttp/__init__.py +0 -0
  21. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/aiohttp/version.py +0 -0
  22. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/cohere/__init__.py +0 -0
  23. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/cohere/version.py +0 -0
  24. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/fastapi/__init__.py +0 -0
  25. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/fastapi/version.py +0 -0
  26. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/google_genai/__init__.py +0 -0
  27. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/google_genai/config.py +0 -0
  28. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/google_genai/utils.py +0 -0
  29. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/google_genai/version.py +0 -0
  30. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/httpx/__init__.py +0 -0
  31. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/httpx/version.py +0 -0
  32. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/instruments.py +0 -0
  33. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/litellm/__init__.py +0 -0
  34. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/litellm/version.py +0 -0
  35. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/litellm/wrappers.py +0 -0
  36. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/mistralai/__init__.py +0 -0
  37. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/mistralai/config.py +0 -0
  38. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/mistralai/utils.py +0 -0
  39. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/mistralai/version.py +0 -0
  40. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/openai/__init__.py +0 -0
  41. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/openai/version.py +0 -0
  42. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/openai/wrappers.py +0 -0
  43. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/pydantic_ai/__init__.py +0 -0
  44. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/pydantic_ai/utils.py +0 -0
  45. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/pydantic_ai/version.py +0 -0
  46. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/pydantic_ai/wrappers.py +0 -0
  47. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/weaviate/__init__.py +0 -0
  48. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/instrumentation/weaviate/version.py +0 -0
  49. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/pii.py +0 -0
  50. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/processors/__init__.py +0 -0
  51. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/processors/instrumentation_span_processor.py +0 -0
  52. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/processors/scrubbing_span_processor.py +0 -0
  53. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/processors/session_span_processor.py +0 -0
  54. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/scanner.py +0 -0
  55. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/session_manager.py +0 -0
  56. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/span_wrapper.py +0 -0
  57. {netra_sdk-0.1.43 → netra_sdk-0.1.44}/netra/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netra-sdk
3
- Version: 0.1.43
3
+ Version: 0.1.44
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-Expression: Apache-2.0
6
6
  License-File: LICENCE
@@ -57,50 +57,74 @@ class FilteringSpanExporter(SpanExporter): # type: ignore[misc]
57
57
 
58
58
  def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
59
59
  filtered: List[ReadableSpan] = []
60
- for s in spans:
61
- name = getattr(s, "name", None)
62
- if name is None:
63
- filtered.append(s)
60
+ blocked_parent_map: Dict[Any, Any] = {}
61
+ for span in spans:
62
+ name = getattr(span, "name", None)
63
+ if name is None or not self._is_blocked(name):
64
+ filtered.append(span)
64
65
  continue
65
- # Only apply blocked span patterns to root-level spans (no valid parent)
66
- parent = getattr(s, "parent", None)
67
- # Determine if the span has a valid parent. SpanContext.is_valid may be a property or method.
68
- has_valid_parent = False
69
- if parent is not None:
70
- is_valid_attr = getattr(parent, "is_valid", None)
71
- if callable(is_valid_attr):
72
- try:
73
- has_valid_parent = bool(is_valid_attr())
74
- except Exception:
75
- has_valid_parent = False
76
- else:
77
- has_valid_parent = bool(is_valid_attr)
78
-
79
- is_root_span = parent is None or not has_valid_parent
80
-
81
- if is_root_span:
82
- # Apply name-based blocking only for root spans
83
- if name in self._exact:
84
- continue
85
- blocked = False
86
- for pref in self._prefixes:
87
- if name.startswith(pref):
88
- blocked = True
89
- break
90
- if not blocked and self._suffixes:
91
- for suf in self._suffixes:
92
- if name.endswith(suf):
93
- blocked = True
94
- break
95
- if not blocked:
96
- filtered.append(s)
97
- else:
98
- # Do not block child spans based on name
99
- filtered.append(s)
66
+
67
+ span_context = getattr(span, "context", None)
68
+ span_id = getattr(span_context, "span_id", None) if span_context else None
69
+ if span_id is not None:
70
+ blocked_parent_map[span_id] = getattr(span, "parent", None)
71
+ if blocked_parent_map:
72
+ self._reparent_blocked_children(filtered, blocked_parent_map)
100
73
  if not filtered:
101
74
  return SpanExportResult.SUCCESS
102
75
  return self._exporter.export(filtered)
103
76
 
77
+ def _is_blocked(self, name: str) -> bool:
78
+ if name in self._exact:
79
+ return True
80
+ for pref in self._prefixes:
81
+ if name.startswith(pref):
82
+ return True
83
+ for suf in self._suffixes:
84
+ if name.endswith(suf):
85
+ return True
86
+ return False
87
+
88
+ def _reparent_blocked_children(
89
+ self,
90
+ spans: Sequence[ReadableSpan],
91
+ blocked_parent_map: Dict[Any, Any],
92
+ ) -> None:
93
+ if not blocked_parent_map:
94
+ return
95
+
96
+ for span in spans:
97
+ parent_context = getattr(span, "parent", None)
98
+ if parent_context is None:
99
+ continue
100
+
101
+ updated_parent = parent_context
102
+ visited: set[Any] = set()
103
+ changed = False
104
+
105
+ while updated_parent is not None:
106
+ parent_span_id = getattr(updated_parent, "span_id", None)
107
+ if parent_span_id not in blocked_parent_map or parent_span_id in visited:
108
+ break
109
+ visited.add(parent_span_id)
110
+ updated_parent = blocked_parent_map[parent_span_id]
111
+ changed = True
112
+
113
+ if changed:
114
+ self._set_span_parent(span, updated_parent)
115
+
116
+ def _set_span_parent(self, span: ReadableSpan, parent: Any) -> None:
117
+ if hasattr(span, "_parent"):
118
+ try:
119
+ span._parent = parent
120
+ return
121
+ except Exception:
122
+ pass
123
+ try:
124
+ setattr(span, "parent", parent)
125
+ except Exception:
126
+ logger.debug("Failed to reparent span %s", getattr(span, "name", "<unknown>"), exc_info=True)
127
+
104
128
  def shutdown(self) -> None:
105
129
  try:
106
130
  self._exporter.shutdown()
@@ -0,0 +1 @@
1
+ __version__ = "0.1.44"
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [project]
6
6
  name = "netra-sdk"
7
- version = "0.1.43"
7
+ version = "0.1.44"
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.43"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes