netra-sdk 0.1.46__py3-none-any.whl → 0.1.47__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.
Potentially problematic release.
This version of netra-sdk might be problematic. Click here for more details.
- netra/__init__.py +9 -6
- netra/decorators.py +4 -2
- netra/span_wrapper.py +2 -1
- netra/tracer.py +61 -48
- netra/version.py +1 -1
- {netra_sdk-0.1.46.dist-info → netra_sdk-0.1.47.dist-info}/METADATA +1 -1
- {netra_sdk-0.1.46.dist-info → netra_sdk-0.1.47.dist-info}/RECORD +9 -9
- {netra_sdk-0.1.46.dist-info → netra_sdk-0.1.47.dist-info}/WHEEL +0 -0
- {netra_sdk-0.1.46.dist-info → netra_sdk-0.1.47.dist-info}/licenses/LICENCE +0 -0
netra/__init__.py
CHANGED
|
@@ -183,11 +183,12 @@ class Netra:
|
|
|
183
183
|
session_id: Session identifier
|
|
184
184
|
"""
|
|
185
185
|
if not isinstance(session_id, str):
|
|
186
|
-
|
|
186
|
+
logger.error(f"set_session_id: session_id must be a string, got {type(session_id)}")
|
|
187
|
+
return
|
|
187
188
|
if session_id:
|
|
188
189
|
SessionManager.set_session_context("session_id", session_id)
|
|
189
190
|
else:
|
|
190
|
-
logger.warning("Session ID must be provided for setting session_id.")
|
|
191
|
+
logger.warning("set_session_id: Session ID must be provided for setting session_id.")
|
|
191
192
|
|
|
192
193
|
@classmethod
|
|
193
194
|
def set_user_id(cls, user_id: str) -> None:
|
|
@@ -198,11 +199,12 @@ class Netra:
|
|
|
198
199
|
user_id: User identifier
|
|
199
200
|
"""
|
|
200
201
|
if not isinstance(user_id, str):
|
|
201
|
-
|
|
202
|
+
logger.error(f"set_user_id: user_id must be a string, got {type(user_id)}")
|
|
203
|
+
return
|
|
202
204
|
if user_id:
|
|
203
205
|
SessionManager.set_session_context("user_id", user_id)
|
|
204
206
|
else:
|
|
205
|
-
logger.warning("User ID must be provided for setting user_id.")
|
|
207
|
+
logger.warning("set_user_id: User ID must be provided for setting user_id.")
|
|
206
208
|
|
|
207
209
|
@classmethod
|
|
208
210
|
def set_tenant_id(cls, tenant_id: str) -> None:
|
|
@@ -213,11 +215,12 @@ class Netra:
|
|
|
213
215
|
user_account_id: User account identifier
|
|
214
216
|
"""
|
|
215
217
|
if not isinstance(tenant_id, str):
|
|
216
|
-
|
|
218
|
+
logger.error(f"set_tenant_id: tenant_id must be a string, got {type(tenant_id)}")
|
|
219
|
+
return
|
|
217
220
|
if tenant_id:
|
|
218
221
|
SessionManager.set_session_context("tenant_id", tenant_id)
|
|
219
222
|
else:
|
|
220
|
-
logger.warning("Tenant ID must be provided for setting tenant_id.")
|
|
223
|
+
logger.warning("set_tenant_id: Tenant ID must be provided for setting tenant_id.")
|
|
221
224
|
|
|
222
225
|
@classmethod
|
|
223
226
|
def set_custom_attributes(cls, key: str, value: Any) -> None:
|
netra/decorators.py
CHANGED
|
@@ -285,7 +285,8 @@ def _create_function_wrapper(
|
|
|
285
285
|
# Set span type if provided
|
|
286
286
|
|
|
287
287
|
if not isinstance(as_type, SpanType):
|
|
288
|
-
|
|
288
|
+
logger.error("Invalid span type: %s", as_type)
|
|
289
|
+
return
|
|
289
290
|
try:
|
|
290
291
|
span.set_attribute("netra.span.type", as_type.value)
|
|
291
292
|
except Exception:
|
|
@@ -344,7 +345,8 @@ def _create_function_wrapper(
|
|
|
344
345
|
# Set span type if provided
|
|
345
346
|
if as_type is not None:
|
|
346
347
|
if not isinstance(as_type, SpanType):
|
|
347
|
-
|
|
348
|
+
logger.error("Invalid span type: %s", as_type)
|
|
349
|
+
return
|
|
348
350
|
try:
|
|
349
351
|
span.set_attribute("netra.span.type", as_type.value)
|
|
350
352
|
except Exception:
|
netra/span_wrapper.py
CHANGED
|
@@ -98,7 +98,8 @@ class SpanWrapper:
|
|
|
98
98
|
if isinstance(as_type, SpanType):
|
|
99
99
|
self.attributes["netra.span.type"] = as_type.value
|
|
100
100
|
else:
|
|
101
|
-
|
|
101
|
+
logger.error("Invalid span type: %s", as_type)
|
|
102
|
+
return
|
|
102
103
|
|
|
103
104
|
def __enter__(self) -> "SpanWrapper":
|
|
104
105
|
"""Start the span wrapper, begin time tracking, and create OpenTelemetry span."""
|
netra/tracer.py
CHANGED
|
@@ -5,10 +5,12 @@ including exporter setup and span processor configuration.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import logging
|
|
8
|
+
import threading
|
|
8
9
|
from typing import Any, Dict
|
|
9
10
|
|
|
10
11
|
from opentelemetry import trace
|
|
11
12
|
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
13
|
+
from opentelemetry.sdk import trace as sdk_trace
|
|
12
14
|
from opentelemetry.sdk.resources import DEPLOYMENT_ENVIRONMENT, SERVICE_NAME, Resource
|
|
13
15
|
from opentelemetry.sdk.trace import TracerProvider
|
|
14
16
|
from opentelemetry.sdk.trace.export import (
|
|
@@ -22,6 +24,8 @@ from netra.exporters import FilteringSpanExporter
|
|
|
22
24
|
|
|
23
25
|
logger = logging.getLogger(__name__)
|
|
24
26
|
|
|
27
|
+
_provider_install_lock = threading.Lock()
|
|
28
|
+
|
|
25
29
|
|
|
26
30
|
class Tracer:
|
|
27
31
|
"""
|
|
@@ -55,57 +59,66 @@ class Tracer:
|
|
|
55
59
|
resource = Resource(attributes=resource_attrs)
|
|
56
60
|
|
|
57
61
|
# Build TracerProvider
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
logger.warning("OTLP endpoint not provided, falling back to console exporter")
|
|
63
|
-
exporter = ConsoleSpanExporter()
|
|
62
|
+
current_provider = trace.get_tracer_provider()
|
|
63
|
+
if isinstance(current_provider, sdk_trace.TracerProvider):
|
|
64
|
+
provider = current_provider
|
|
65
|
+
logger.info("Reusing existing TracerProvider. Possible loss of Resource attributes")
|
|
64
66
|
else:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
provider = TracerProvider(resource=resource)
|
|
68
|
+
trace.set_tracer_provider(provider)
|
|
69
|
+
logger.info("Using Netra TracerProvider")
|
|
70
|
+
|
|
71
|
+
with _provider_install_lock:
|
|
72
|
+
if getattr(provider, "_netra_processors_installed", False):
|
|
73
|
+
logger.info("Netra processors already installed on provider; skipping setup")
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
if not self.cfg.otlp_endpoint:
|
|
77
|
+
logger.warning("OTLP endpoint not provided, falling back to console exporter")
|
|
78
|
+
exporter = ConsoleSpanExporter()
|
|
79
|
+
else:
|
|
80
|
+
exporter = OTLPSpanExporter(
|
|
81
|
+
endpoint=self._format_endpoint(self.cfg.otlp_endpoint),
|
|
82
|
+
headers=self.cfg.headers,
|
|
83
|
+
)
|
|
84
|
+
original_exporter = exporter
|
|
85
|
+
try:
|
|
86
|
+
patterns = getattr(self.cfg, "blocked_spans", None) or []
|
|
87
|
+
exporter = FilteringSpanExporter(exporter, patterns)
|
|
88
|
+
if patterns:
|
|
89
|
+
logger.info("Enabled FilteringSpanExporter with %d global pattern(s)", len(patterns))
|
|
90
|
+
else:
|
|
91
|
+
logger.info("Enabled FilteringSpanExporter with local-only rules")
|
|
92
|
+
except (ValueError, TypeError) as e:
|
|
93
|
+
logger.warning("Failed to enable FilteringSpanExporter: %s; using unwrapped exporter", e)
|
|
94
|
+
exporter = original_exporter
|
|
95
|
+
|
|
96
|
+
from netra.processors import (
|
|
97
|
+
InstrumentationSpanProcessor,
|
|
98
|
+
LocalFilteringSpanProcessor,
|
|
99
|
+
ScrubbingSpanProcessor,
|
|
100
|
+
SessionSpanProcessor,
|
|
68
101
|
)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
102
|
+
|
|
103
|
+
provider.add_span_processor(LocalFilteringSpanProcessor())
|
|
104
|
+
provider.add_span_processor(InstrumentationSpanProcessor())
|
|
105
|
+
provider.add_span_processor(SessionSpanProcessor())
|
|
106
|
+
|
|
107
|
+
if self.cfg.enable_scrubbing:
|
|
108
|
+
provider.add_span_processor(ScrubbingSpanProcessor()) # type: ignore[no-untyped-call]
|
|
109
|
+
|
|
110
|
+
if self.cfg.disable_batch:
|
|
111
|
+
provider.add_span_processor(SimpleSpanProcessor(exporter))
|
|
75
112
|
else:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
# Apply local filtering propagation first so later processors and spans see attributes
|
|
88
|
-
provider.add_span_processor(LocalFilteringSpanProcessor())
|
|
89
|
-
provider.add_span_processor(InstrumentationSpanProcessor())
|
|
90
|
-
provider.add_span_processor(SessionSpanProcessor())
|
|
91
|
-
|
|
92
|
-
# Add scrubbing processor if enabled
|
|
93
|
-
if self.cfg.enable_scrubbing:
|
|
94
|
-
provider.add_span_processor(ScrubbingSpanProcessor()) # type: ignore[no-untyped-call]
|
|
95
|
-
|
|
96
|
-
# Install appropriate span processor
|
|
97
|
-
if self.cfg.disable_batch:
|
|
98
|
-
provider.add_span_processor(SimpleSpanProcessor(exporter))
|
|
99
|
-
else:
|
|
100
|
-
provider.add_span_processor(BatchSpanProcessor(exporter))
|
|
101
|
-
|
|
102
|
-
# Set global tracer provider
|
|
103
|
-
trace.set_tracer_provider(provider)
|
|
104
|
-
logger.info(
|
|
105
|
-
"Netra TracerProvider initialized: endpoint=%s, disable_batch=%s",
|
|
106
|
-
self.cfg.otlp_endpoint,
|
|
107
|
-
self.cfg.disable_batch,
|
|
108
|
-
)
|
|
113
|
+
provider.add_span_processor(BatchSpanProcessor(exporter))
|
|
114
|
+
|
|
115
|
+
setattr(provider, "_netra_processors_installed", True)
|
|
116
|
+
|
|
117
|
+
logger.info(
|
|
118
|
+
"Netra initialized: endpoint=%s, disable_batch=%s",
|
|
119
|
+
self.cfg.otlp_endpoint,
|
|
120
|
+
self.cfg.disable_batch,
|
|
121
|
+
)
|
|
109
122
|
|
|
110
123
|
def _format_endpoint(self, endpoint: str) -> str:
|
|
111
124
|
"""Format the OTLP endpoint URL to ensure it ends with '/v1/traces'.
|
netra/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.47"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: netra-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.47
|
|
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
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
netra/__init__.py,sha256=
|
|
1
|
+
netra/__init__.py,sha256=vH9J2iPKtx8j9-dWhDroUqRq10qfqHaBurMl11c4g6Q,10590
|
|
2
2
|
netra/anonymizer/__init__.py,sha256=KeGPPZqKVZbtkbirEKYTYhj6aZHlakjdQhD7QHqBRio,133
|
|
3
3
|
netra/anonymizer/anonymizer.py,sha256=IcrYkdwWrFauGWUeAW-0RwrSUM8VSZCFNtoywZhvIqU,3778
|
|
4
4
|
netra/anonymizer/base.py,sha256=ytPxHCUD2OXlEY6fNTuMmwImNdIjgj294I41FIgoXpU,5946
|
|
5
5
|
netra/anonymizer/fp_anonymizer.py,sha256=_6svIYmE0eejdIMkhKBUWCNjGtGimtrGtbLvPSOp8W4,6493
|
|
6
6
|
netra/config.py,sha256=RqLul2vlNHHKGU31OQIJTUpcKMSmVse9IlGFwImW6sE,7032
|
|
7
|
-
netra/decorators.py,sha256=
|
|
7
|
+
netra/decorators.py,sha256=b6cNRJVUvroGv97NVE-psMZzL-Upl0X2m63_l_-VBdQ,18433
|
|
8
8
|
netra/exceptions/__init__.py,sha256=uDgcBxmC4WhdS7HRYQk_TtJyxH1s1o6wZmcsnSHLAcM,174
|
|
9
9
|
netra/exceptions/injection.py,sha256=ke4eUXRYUFJkMZgdSyPPkPt5PdxToTI6xLEBI0hTWUQ,1332
|
|
10
10
|
netra/exceptions/pii.py,sha256=MT4p_x-zH3VtYudTSxw1Z9qQZADJDspq64WrYqSWlZc,2438
|
|
@@ -49,11 +49,11 @@ netra/processors/scrubbing_span_processor.py,sha256=dJ86Ncmjvmrhm_uAdGTwcGvRpZbV
|
|
|
49
49
|
netra/processors/session_span_processor.py,sha256=qcsBl-LnILWefsftI8NQhXDGb94OWPc8LvzhVA0JS_c,2432
|
|
50
50
|
netra/scanner.py,sha256=kyDpeZiscCPb6pjuhS-sfsVj-dviBFRepdUWh0sLoEY,11554
|
|
51
51
|
netra/session_manager.py,sha256=jxA62zAgiTsuTyV_UuPkVb2W1Uieb7I5jWsYiJ6jSxk,13897
|
|
52
|
-
netra/span_wrapper.py,sha256=
|
|
53
|
-
netra/tracer.py,sha256=
|
|
52
|
+
netra/span_wrapper.py,sha256=x5ejtMwD40eMRbeYOfsE2GQGrqZcjZz_sZOuLIeZ__8,10118
|
|
53
|
+
netra/tracer.py,sha256=BXlEEOQ7ou5zd2Bf5cUFp6vLoMJLgBywtxfUBr9Di-Q,5175
|
|
54
54
|
netra/utils.py,sha256=FblSzI8qMTfEbusakGBKE9CNELW0GEBHl09mPPxgI-w,2521
|
|
55
|
-
netra/version.py,sha256=
|
|
56
|
-
netra_sdk-0.1.
|
|
57
|
-
netra_sdk-0.1.
|
|
58
|
-
netra_sdk-0.1.
|
|
59
|
-
netra_sdk-0.1.
|
|
55
|
+
netra/version.py,sha256=BqdH88p7_x5NtwJCtqUPLKt1fAJF1mVKUoKH7vlX5dQ,23
|
|
56
|
+
netra_sdk-0.1.47.dist-info/METADATA,sha256=JbzzZzE-IzVy2h8fNa0QT5doUkjgpvJXHgnxf44zj0Y,28208
|
|
57
|
+
netra_sdk-0.1.47.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
58
|
+
netra_sdk-0.1.47.dist-info/licenses/LICENCE,sha256=8B_UoZ-BAl0AqiHAHUETCgd3I2B9yYJ1WEQtVb_qFMA,11359
|
|
59
|
+
netra_sdk-0.1.47.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|