netra-sdk 0.1.28__py3-none-any.whl → 0.1.29__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 +64 -0
- netra/config.py +9 -0
- netra/version.py +1 -1
- {netra_sdk-0.1.28.dist-info → netra_sdk-0.1.29.dist-info}/METADATA +1 -1
- {netra_sdk-0.1.28.dist-info → netra_sdk-0.1.29.dist-info}/RECORD +7 -7
- {netra_sdk-0.1.28.dist-info → netra_sdk-0.1.29.dist-info}/LICENCE +0 -0
- {netra_sdk-0.1.28.dist-info → netra_sdk-0.1.29.dist-info}/WHEEL +0 -0
netra/__init__.py
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import atexit
|
|
1
2
|
import logging
|
|
2
3
|
import threading
|
|
3
4
|
from typing import Any, Dict, Optional, Set
|
|
4
5
|
|
|
6
|
+
from opentelemetry import context as context_api
|
|
7
|
+
from opentelemetry import trace
|
|
8
|
+
from opentelemetry.trace import SpanKind
|
|
9
|
+
|
|
5
10
|
from netra.instrumentation.instruments import InstrumentSet, NetraInstruments
|
|
6
11
|
|
|
7
12
|
from .config import Config
|
|
@@ -27,6 +32,8 @@ class Netra:
|
|
|
27
32
|
_initialized = False
|
|
28
33
|
# Use RLock so the thread that already owns the lock can re-acquire it safely
|
|
29
34
|
_init_lock = threading.RLock()
|
|
35
|
+
_root_span = None
|
|
36
|
+
_root_ctx_token = None
|
|
30
37
|
|
|
31
38
|
@classmethod
|
|
32
39
|
def is_initialized(cls) -> bool:
|
|
@@ -46,6 +53,7 @@ class Netra:
|
|
|
46
53
|
disable_batch: Optional[bool] = None,
|
|
47
54
|
trace_content: Optional[bool] = None,
|
|
48
55
|
debug_mode: Optional[bool] = None,
|
|
56
|
+
enable_root_span: Optional[bool] = None,
|
|
49
57
|
resource_attributes: Optional[Dict[str, Any]] = None,
|
|
50
58
|
environment: Optional[str] = None,
|
|
51
59
|
instruments: Optional[Set[NetraInstruments]] = None,
|
|
@@ -66,6 +74,7 @@ class Netra:
|
|
|
66
74
|
disable_batch=disable_batch,
|
|
67
75
|
trace_content=trace_content,
|
|
68
76
|
debug_mode=debug_mode,
|
|
77
|
+
enable_root_span=enable_root_span,
|
|
69
78
|
resource_attributes=resource_attributes,
|
|
70
79
|
environment=environment,
|
|
71
80
|
)
|
|
@@ -106,6 +115,61 @@ class Netra:
|
|
|
106
115
|
cls._initialized = True
|
|
107
116
|
logger.info("Netra successfully initialized.")
|
|
108
117
|
|
|
118
|
+
# Create and attach a long-lived root span if enabled
|
|
119
|
+
if cfg.enable_root_span:
|
|
120
|
+
tracer = trace.get_tracer("netra.root.span")
|
|
121
|
+
root_name = f"{Config.LIBRARY_NAME}.root.span"
|
|
122
|
+
root_span = tracer.start_span(root_name, kind=SpanKind.INTERNAL)
|
|
123
|
+
# Add useful attributes
|
|
124
|
+
if cfg.app_name:
|
|
125
|
+
root_span.set_attribute("service.name", cfg.app_name)
|
|
126
|
+
root_span.set_attribute("netra.environment", cfg.environment)
|
|
127
|
+
root_span.set_attribute("netra.library.version", Config.LIBRARY_VERSION)
|
|
128
|
+
|
|
129
|
+
# Attach span to current context so subsequent spans become its children
|
|
130
|
+
ctx = trace.set_span_in_context(root_span)
|
|
131
|
+
token = context_api.attach(ctx)
|
|
132
|
+
|
|
133
|
+
# Save for potential shutdown/cleanup and session tracking
|
|
134
|
+
cls._root_span = root_span
|
|
135
|
+
cls._root_ctx_token = token
|
|
136
|
+
try:
|
|
137
|
+
SessionManager.set_current_span(root_span)
|
|
138
|
+
except Exception:
|
|
139
|
+
pass
|
|
140
|
+
logger.info("Netra root span created and attached to context.")
|
|
141
|
+
|
|
142
|
+
# Ensure cleanup at process exit
|
|
143
|
+
atexit.register(cls.shutdown)
|
|
144
|
+
|
|
145
|
+
@classmethod
|
|
146
|
+
def shutdown(cls) -> None:
|
|
147
|
+
"""Optional cleanup to end the root span and detach context."""
|
|
148
|
+
with cls._init_lock:
|
|
149
|
+
if cls._root_ctx_token is not None:
|
|
150
|
+
try:
|
|
151
|
+
context_api.detach(cls._root_ctx_token)
|
|
152
|
+
except Exception:
|
|
153
|
+
pass
|
|
154
|
+
finally:
|
|
155
|
+
cls._root_ctx_token = None
|
|
156
|
+
if cls._root_span is not None:
|
|
157
|
+
try:
|
|
158
|
+
cls._root_span.end()
|
|
159
|
+
except Exception:
|
|
160
|
+
pass
|
|
161
|
+
finally:
|
|
162
|
+
cls._root_span = None
|
|
163
|
+
# Try to flush and shutdown the tracer provider to ensure export
|
|
164
|
+
try:
|
|
165
|
+
provider = trace.get_tracer_provider()
|
|
166
|
+
if hasattr(provider, "force_flush"):
|
|
167
|
+
provider.force_flush()
|
|
168
|
+
if hasattr(provider, "shutdown"):
|
|
169
|
+
provider.shutdown()
|
|
170
|
+
except Exception:
|
|
171
|
+
pass
|
|
172
|
+
|
|
109
173
|
@classmethod
|
|
110
174
|
def set_session_id(cls, session_id: str) -> None:
|
|
111
175
|
"""
|
netra/config.py
CHANGED
|
@@ -17,6 +17,7 @@ class Config:
|
|
|
17
17
|
- disable_batch: Whether to disable batch span processor (bool)
|
|
18
18
|
- trace_content: Whether to capture prompt/completion content (bool)
|
|
19
19
|
- debug_mode: Whether to enable SDK logging; default False (bool)
|
|
20
|
+
- enable_root_span: Whether to create a process root span; default False (bool)
|
|
20
21
|
- resource_attributes: Custom resource attributes dict (e.g., {'env': 'prod', 'version': '1.0.0'})
|
|
21
22
|
"""
|
|
22
23
|
|
|
@@ -32,6 +33,7 @@ class Config:
|
|
|
32
33
|
disable_batch: Optional[bool] = None,
|
|
33
34
|
trace_content: Optional[bool] = None,
|
|
34
35
|
debug_mode: Optional[bool] = None,
|
|
36
|
+
enable_root_span: Optional[bool] = None,
|
|
35
37
|
resource_attributes: Optional[Dict[str, Any]] = None,
|
|
36
38
|
environment: Optional[str] = None,
|
|
37
39
|
):
|
|
@@ -106,6 +108,13 @@ class Config:
|
|
|
106
108
|
else:
|
|
107
109
|
self.environment = os.getenv("NETRA_ENV", "local")
|
|
108
110
|
|
|
111
|
+
# Enable a long-lived root span for the process? Default False.
|
|
112
|
+
if enable_root_span is not None:
|
|
113
|
+
self.enable_root_span = enable_root_span
|
|
114
|
+
else:
|
|
115
|
+
env_root = os.getenv("NETRA_ENABLE_ROOT_SPAN")
|
|
116
|
+
self.enable_root_span = True if (env_root is not None and env_root.lower() in ("1", "true")) else False
|
|
117
|
+
|
|
109
118
|
# Resource attributes: param override, else parse JSON from env, else empty dict
|
|
110
119
|
if resource_attributes is not None:
|
|
111
120
|
self.resource_attributes = resource_attributes
|
netra/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.29"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: netra-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.29
|
|
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
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
netra/__init__.py,sha256=
|
|
1
|
+
netra/__init__.py,sha256=EIMbq0ycEIolmyk7uGXkmgvydfWArNk-soBIEQijsiY,9612
|
|
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
|
-
netra/config.py,sha256=
|
|
6
|
+
netra/config.py,sha256=zmTssfUExG8viSMKN9Yfd8i--7S4oUQT8IyvwAI4C2U,5950
|
|
7
7
|
netra/decorators.py,sha256=TqORBs0Xv_CZHOAwrWkpvscMj4FgOJsgo1CRYoG6C7Y,7435
|
|
8
8
|
netra/exceptions/__init__.py,sha256=uDgcBxmC4WhdS7HRYQk_TtJyxH1s1o6wZmcsnSHLAcM,174
|
|
9
9
|
netra/exceptions/injection.py,sha256=ke4eUXRYUFJkMZgdSyPPkPt5PdxToTI6xLEBI0hTWUQ,1332
|
|
@@ -43,8 +43,8 @@ netra/scanner.py,sha256=kyDpeZiscCPb6pjuhS-sfsVj-dviBFRepdUWh0sLoEY,11554
|
|
|
43
43
|
netra/session_manager.py,sha256=Ks8A6B9RYe0tV8PeWYuN0M-UMZqa47uquuw6D7C1vCE,6701
|
|
44
44
|
netra/span_wrapper.py,sha256=ec2WLYTRLZ02WSSCYEsMn1PgUGVji9rFyq_CRCV9rog,7388
|
|
45
45
|
netra/tracer.py,sha256=In5QPVLz_6BxrolWpav9EuR9_hirD2UUIlyY75QUaKk,3450
|
|
46
|
-
netra/version.py,sha256=
|
|
47
|
-
netra_sdk-0.1.
|
|
48
|
-
netra_sdk-0.1.
|
|
49
|
-
netra_sdk-0.1.
|
|
50
|
-
netra_sdk-0.1.
|
|
46
|
+
netra/version.py,sha256=A-lFHZ4YpCrWZ6nw3tlt_yurFJ00mInm3gR6hz51Eww,23
|
|
47
|
+
netra_sdk-0.1.29.dist-info/LICENCE,sha256=8B_UoZ-BAl0AqiHAHUETCgd3I2B9yYJ1WEQtVb_qFMA,11359
|
|
48
|
+
netra_sdk-0.1.29.dist-info/METADATA,sha256=XKGT69ygEEA6hbSinO1heKikakeIngiMqotgwQbFyeQ,28151
|
|
49
|
+
netra_sdk-0.1.29.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
50
|
+
netra_sdk-0.1.29.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|