netra-sdk 0.1.25__tar.gz → 0.1.27__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.
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/PKG-INFO +17 -3
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/README.md +16 -1
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/__init__.py +6 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/decorators.py +15 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/session_manager.py +13 -2
- netra_sdk-0.1.27/netra/version.py +1 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/pyproject.toml +1 -2
- netra_sdk-0.1.25/netra/version.py +0 -1
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/LICENCE +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/anonymizer/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/anonymizer/anonymizer.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/anonymizer/base.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/anonymizer/fp_anonymizer.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/config.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/exceptions/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/exceptions/injection.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/exceptions/pii.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/input_scanner.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/aiohttp/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/aiohttp/version.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/cohere/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/cohere/version.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/fastapi/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/fastapi/version.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/google_genai/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/google_genai/config.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/google_genai/utils.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/google_genai/version.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/httpx/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/httpx/version.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/instruments.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/mistralai/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/mistralai/config.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/mistralai/utils.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/mistralai/version.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/openai/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/openai/version.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/openai/wrappers.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/pydantic_ai/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/pydantic_ai/utils.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/pydantic_ai/version.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/pydantic_ai/wrappers.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/weaviate/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/instrumentation/weaviate/version.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/pii.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/processors/__init__.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/processors/session_span_processor.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/scanner.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/span_wrapper.py +0 -0
- {netra_sdk-0.1.25 → netra_sdk-0.1.27}/netra/tracer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: netra-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.27
|
|
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
|
|
@@ -72,7 +72,6 @@ Requires-Dist: presidio-anonymizer (==2.2.358) ; extra == "presidio"
|
|
|
72
72
|
Requires-Dist: stanza (>=1.10.1,<2.0.0) ; extra == "presidio"
|
|
73
73
|
Requires-Dist: traceloop-sdk (>=0.40.7,<0.43.0)
|
|
74
74
|
Requires-Dist: transformers (==4.51.3) ; extra == "presidio"
|
|
75
|
-
Requires-Dist: twine (>=6.1.0,<7.0.0)
|
|
76
75
|
Project-URL: Bug Tracker, https://github.com/KeyValueSoftwareSystems/netra-sdk-py/issues
|
|
77
76
|
Project-URL: Documentation, https://github.com/KeyValueSoftwareSystems/netra-sdk-py/blob/main/README.md
|
|
78
77
|
Project-URL: Homepage, https://github.com/KeyValueSoftwareSystems/netra-sdk-py
|
|
@@ -174,7 +173,7 @@ Netra.init(
|
|
|
174
173
|
Use decorators to automatically trace your functions and classes:
|
|
175
174
|
|
|
176
175
|
```python
|
|
177
|
-
from netra.decorators import workflow, agent, task
|
|
176
|
+
from netra.decorators import workflow, agent, task, span
|
|
178
177
|
|
|
179
178
|
@workflow
|
|
180
179
|
def data_processing_workflow(data):
|
|
@@ -192,6 +191,11 @@ def data_validation_task(data):
|
|
|
192
191
|
"""Task for validating input data"""
|
|
193
192
|
return validate_schema(data)
|
|
194
193
|
|
|
194
|
+
@span
|
|
195
|
+
def data_processing_span(data):
|
|
196
|
+
"""Span for processing data"""
|
|
197
|
+
return process_data(data)
|
|
198
|
+
|
|
195
199
|
# Works with async functions too
|
|
196
200
|
@workflow(name="Async Data Pipeline")
|
|
197
201
|
async def async_workflow(data):
|
|
@@ -206,6 +210,16 @@ class CustomerSupportAgent:
|
|
|
206
210
|
|
|
207
211
|
def escalate_issue(self, issue):
|
|
208
212
|
return self.forward_to_human(issue)
|
|
213
|
+
|
|
214
|
+
@task
|
|
215
|
+
async def async_task(data):
|
|
216
|
+
"""Task for processing data"""
|
|
217
|
+
return await process_data_async(data)
|
|
218
|
+
|
|
219
|
+
@span
|
|
220
|
+
async def async_span(data):
|
|
221
|
+
"""Span for processing data"""
|
|
222
|
+
return await process_data_async(data)
|
|
209
223
|
```
|
|
210
224
|
|
|
211
225
|
## 🔍 Supported Instrumentations
|
|
@@ -93,7 +93,7 @@ Netra.init(
|
|
|
93
93
|
Use decorators to automatically trace your functions and classes:
|
|
94
94
|
|
|
95
95
|
```python
|
|
96
|
-
from netra.decorators import workflow, agent, task
|
|
96
|
+
from netra.decorators import workflow, agent, task, span
|
|
97
97
|
|
|
98
98
|
@workflow
|
|
99
99
|
def data_processing_workflow(data):
|
|
@@ -111,6 +111,11 @@ def data_validation_task(data):
|
|
|
111
111
|
"""Task for validating input data"""
|
|
112
112
|
return validate_schema(data)
|
|
113
113
|
|
|
114
|
+
@span
|
|
115
|
+
def data_processing_span(data):
|
|
116
|
+
"""Span for processing data"""
|
|
117
|
+
return process_data(data)
|
|
118
|
+
|
|
114
119
|
# Works with async functions too
|
|
115
120
|
@workflow(name="Async Data Pipeline")
|
|
116
121
|
async def async_workflow(data):
|
|
@@ -125,6 +130,16 @@ class CustomerSupportAgent:
|
|
|
125
130
|
|
|
126
131
|
def escalate_issue(self, issue):
|
|
127
132
|
return self.forward_to_human(issue)
|
|
133
|
+
|
|
134
|
+
@task
|
|
135
|
+
async def async_task(data):
|
|
136
|
+
"""Task for processing data"""
|
|
137
|
+
return await process_data_async(data)
|
|
138
|
+
|
|
139
|
+
@span
|
|
140
|
+
async def async_span(data):
|
|
141
|
+
"""Span for processing data"""
|
|
142
|
+
return await process_data_async(data)
|
|
128
143
|
```
|
|
129
144
|
|
|
130
145
|
## 🔍 Supported Instrumentations
|
|
@@ -89,6 +89,8 @@ class Netra:
|
|
|
89
89
|
Args:
|
|
90
90
|
session_id: Session identifier
|
|
91
91
|
"""
|
|
92
|
+
if not isinstance(session_id, str):
|
|
93
|
+
raise TypeError(f"session_id must be a string, got {type(session_id)}")
|
|
92
94
|
if session_id:
|
|
93
95
|
SessionManager.set_session_context("session_id", session_id)
|
|
94
96
|
else:
|
|
@@ -102,6 +104,8 @@ class Netra:
|
|
|
102
104
|
Args:
|
|
103
105
|
user_id: User identifier
|
|
104
106
|
"""
|
|
107
|
+
if not isinstance(user_id, str):
|
|
108
|
+
raise TypeError(f"user_id must be a string, got {type(user_id)}")
|
|
105
109
|
if user_id:
|
|
106
110
|
SessionManager.set_session_context("user_id", user_id)
|
|
107
111
|
else:
|
|
@@ -115,6 +119,8 @@ class Netra:
|
|
|
115
119
|
Args:
|
|
116
120
|
user_account_id: User account identifier
|
|
117
121
|
"""
|
|
122
|
+
if not isinstance(tenant_id, str):
|
|
123
|
+
raise TypeError(f"tenant_id must be a string, got {type(tenant_id)}")
|
|
118
124
|
if tenant_id:
|
|
119
125
|
SessionManager.set_session_context("tenant_id", tenant_id)
|
|
120
126
|
else:
|
|
@@ -176,3 +176,18 @@ def task(
|
|
|
176
176
|
if target is not None:
|
|
177
177
|
return decorator(target)
|
|
178
178
|
return decorator
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def span(
|
|
182
|
+
target: Union[Callable[P, R], C, None] = None, *, name: Optional[str] = None
|
|
183
|
+
) -> Union[Callable[P, R], C, Callable[[Callable[P, R]], Callable[P, R]]]:
|
|
184
|
+
def decorator(obj: Union[Callable[P, R], C]) -> Union[Callable[P, R], C]:
|
|
185
|
+
if inspect.isclass(obj):
|
|
186
|
+
return _wrap_class_methods(cast(C, obj), "span", name)
|
|
187
|
+
else:
|
|
188
|
+
# When obj is a function, it should be type Callable[P, R]
|
|
189
|
+
return _create_function_wrapper(cast(Callable[P, R], obj), "span", name)
|
|
190
|
+
|
|
191
|
+
if target is not None:
|
|
192
|
+
return decorator(target)
|
|
193
|
+
return decorator
|
|
@@ -26,6 +26,7 @@ class SessionManager:
|
|
|
26
26
|
_workflow_stack: List[str] = []
|
|
27
27
|
_task_stack: List[str] = []
|
|
28
28
|
_agent_stack: List[str] = []
|
|
29
|
+
_span_stack: List[str] = []
|
|
29
30
|
|
|
30
31
|
@classmethod
|
|
31
32
|
def set_current_span(cls, span: Optional[trace.Span]) -> None:
|
|
@@ -53,7 +54,7 @@ class SessionManager:
|
|
|
53
54
|
Push an entity onto the appropriate entity stack.
|
|
54
55
|
|
|
55
56
|
Args:
|
|
56
|
-
entity_type: Type of entity (workflow, task, agent)
|
|
57
|
+
entity_type: Type of entity (workflow, task, agent, span)
|
|
57
58
|
entity_name: Name of the entity
|
|
58
59
|
"""
|
|
59
60
|
if entity_type == "workflow":
|
|
@@ -62,6 +63,8 @@ class SessionManager:
|
|
|
62
63
|
cls._task_stack.append(entity_name)
|
|
63
64
|
elif entity_type == "agent":
|
|
64
65
|
cls._agent_stack.append(entity_name)
|
|
66
|
+
elif entity_type == "span":
|
|
67
|
+
cls._span_stack.append(entity_name)
|
|
65
68
|
|
|
66
69
|
@classmethod
|
|
67
70
|
def pop_entity(cls, entity_type: str) -> Optional[str]:
|
|
@@ -69,7 +72,7 @@ class SessionManager:
|
|
|
69
72
|
Pop the most recent entity from the specified entity stack.
|
|
70
73
|
|
|
71
74
|
Args:
|
|
72
|
-
entity_type: Type of entity (workflow, task, agent)
|
|
75
|
+
entity_type: Type of entity (workflow, task, agent, span)
|
|
73
76
|
|
|
74
77
|
Returns:
|
|
75
78
|
Entity name or None if stack is empty
|
|
@@ -80,6 +83,8 @@ class SessionManager:
|
|
|
80
83
|
return cls._task_stack.pop()
|
|
81
84
|
elif entity_type == "agent" and cls._agent_stack:
|
|
82
85
|
return cls._agent_stack.pop()
|
|
86
|
+
elif entity_type == "span" and cls._span_stack:
|
|
87
|
+
return cls._span_stack.pop()
|
|
83
88
|
return None
|
|
84
89
|
|
|
85
90
|
@classmethod
|
|
@@ -104,6 +109,10 @@ class SessionManager:
|
|
|
104
109
|
if cls._agent_stack:
|
|
105
110
|
attributes[f"{Config.LIBRARY_NAME}.agent.name"] = cls._agent_stack[-1]
|
|
106
111
|
|
|
112
|
+
# Add current span if exists
|
|
113
|
+
if cls._span_stack:
|
|
114
|
+
attributes[f"{Config.LIBRARY_NAME}.span.name"] = cls._span_stack[-1]
|
|
115
|
+
|
|
107
116
|
return attributes
|
|
108
117
|
|
|
109
118
|
@classmethod
|
|
@@ -112,6 +121,7 @@ class SessionManager:
|
|
|
112
121
|
cls._workflow_stack.clear()
|
|
113
122
|
cls._task_stack.clear()
|
|
114
123
|
cls._agent_stack.clear()
|
|
124
|
+
cls._span_stack.clear()
|
|
115
125
|
|
|
116
126
|
@classmethod
|
|
117
127
|
def get_stack_info(cls) -> Dict[str, List[str]]:
|
|
@@ -125,6 +135,7 @@ class SessionManager:
|
|
|
125
135
|
"workflows": cls._workflow_stack.copy(),
|
|
126
136
|
"tasks": cls._task_stack.copy(),
|
|
127
137
|
"agents": cls._agent_stack.copy(),
|
|
138
|
+
"spans": cls._span_stack.copy(),
|
|
128
139
|
}
|
|
129
140
|
|
|
130
141
|
@staticmethod
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.27"
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "netra-sdk"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.27"
|
|
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"}
|
|
@@ -77,7 +77,6 @@ dependencies = [
|
|
|
77
77
|
"opentelemetry-instrumentation-tortoiseorm>=0.55b1,<1.0.0",
|
|
78
78
|
"opentelemetry-instrumentation-urllib>=0.55b1,<1.0.0",
|
|
79
79
|
"opentelemetry-instrumentation-urllib3>=0.55b1,<1.0.0",
|
|
80
|
-
"twine (>=6.1.0,<7.0.0)",
|
|
81
80
|
]
|
|
82
81
|
|
|
83
82
|
[project.urls]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.25"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|