netra-sdk 0.1.0__py3-none-any.whl → 0.1.1__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/config.py +1 -1
- netra/instrumentation/__init__.py +898 -0
- netra/instrumentation/instruments.py +92 -0
- netra/session.py +49 -17
- netra/version.py +1 -1
- {netra_sdk-0.1.0.dist-info → netra_sdk-0.1.1.dist-info}/LICENCE +1 -1
- {netra_sdk-0.1.0.dist-info → netra_sdk-0.1.1.dist-info}/METADATA +164 -30
- {netra_sdk-0.1.0.dist-info → netra_sdk-0.1.1.dist-info}/RECORD +9 -9
- {netra_sdk-0.1.0.dist-info → netra_sdk-0.1.1.dist-info}/WHEEL +0 -0
|
@@ -13,6 +13,54 @@ class CustomInstruments(Enum):
|
|
|
13
13
|
WEAVIATEDB = "weaviate_db"
|
|
14
14
|
GOOGLE_GENERATIVEAI = "google_genai"
|
|
15
15
|
FASTAPI = "fastapi"
|
|
16
|
+
AIO_PIKA = "aio_pika"
|
|
17
|
+
AIOHTTP_SERVER = "aiohttp_server"
|
|
18
|
+
AIOKAFKA = "aiokafka"
|
|
19
|
+
AIOPG = "aiopg"
|
|
20
|
+
ASGI = "asgi"
|
|
21
|
+
ASYNCCLICK = "asyncclick"
|
|
22
|
+
ASYNCIO = "asyncio"
|
|
23
|
+
ASYNCPG = "asyncpg"
|
|
24
|
+
AWS_LAMBDA = "aws_lambda"
|
|
25
|
+
BOTO = "boto"
|
|
26
|
+
BOTO3SQS = "boto3sqs"
|
|
27
|
+
BOTOCORE = "botocore"
|
|
28
|
+
CASSANDRA = "cassandra"
|
|
29
|
+
CELERY = "celery"
|
|
30
|
+
CLICK = "click"
|
|
31
|
+
CONFLUENT_KAFKA = "confluent_kafka"
|
|
32
|
+
DBAPI = "dbapi"
|
|
33
|
+
DJANGO = "django"
|
|
34
|
+
ELASTICSEARCH = "elasticsearch"
|
|
35
|
+
FALCON = "falcon"
|
|
36
|
+
FLASK = "flask"
|
|
37
|
+
GRPC = "grpc"
|
|
38
|
+
JINJA2 = "jinja2"
|
|
39
|
+
KAFKA_PYTHON = "kafka_python"
|
|
40
|
+
LOGGING = "logging"
|
|
41
|
+
MYSQL = "mysql"
|
|
42
|
+
MYSQLCLIENT = "mysqlclient"
|
|
43
|
+
PIKA = "pika"
|
|
44
|
+
PSYCOPG = "psycopg"
|
|
45
|
+
PSYCOPG2 = "psycopg2"
|
|
46
|
+
PYMEMCACHE = "pymemcache"
|
|
47
|
+
PYMONGO = "pymongo"
|
|
48
|
+
PYMSSQL = "pymssql"
|
|
49
|
+
PYMYSQL = "pymysql"
|
|
50
|
+
PYRAMID = "pyramid"
|
|
51
|
+
REDIS = "redis"
|
|
52
|
+
REMOULADE = "remoulade"
|
|
53
|
+
REQUESTS = "requests"
|
|
54
|
+
SQLALCHEMY = "sqlalchemy"
|
|
55
|
+
SQLITE3 = "sqlite3"
|
|
56
|
+
STARLETTE = "starlette"
|
|
57
|
+
SYSTEM_METRICS = "system_metrics"
|
|
58
|
+
THREADING = "threading"
|
|
59
|
+
TORNADO = "tornado"
|
|
60
|
+
TORTOISEORM = "tortoiseorm"
|
|
61
|
+
URLLIB = "urllib"
|
|
62
|
+
URLLIB3 = "urllib3"
|
|
63
|
+
WSGI = "wsgi"
|
|
16
64
|
|
|
17
65
|
|
|
18
66
|
class NetraInstruments(Enum):
|
|
@@ -42,37 +90,81 @@ NetraInstruments follows the given structure. Refer this for usage within Netra
|
|
|
42
90
|
|
|
43
91
|
class InstrumentSet(Enum):
|
|
44
92
|
AIOHTTP = "aiohttp"
|
|
93
|
+
AIOHTTP_SERVER = "aiohttp_server"
|
|
94
|
+
AIO_PIKA = "aio_pika"
|
|
95
|
+
AIOKAFKA = "aiokafka"
|
|
96
|
+
AIOPG = "aiopg"
|
|
45
97
|
ALEPHALPHA = "alephalpha"
|
|
46
98
|
ANTHROPIC = "anthropic"
|
|
99
|
+
ASGI = "asgi"
|
|
100
|
+
ASYNCCLICK = "asyncclick"
|
|
101
|
+
ASYNCIO = "asyncio"
|
|
102
|
+
ASYNCPG = "asyncpg"
|
|
103
|
+
AWS_LAMBDA = "aws_lambda"
|
|
47
104
|
BEDROCK = "bedrock"
|
|
105
|
+
BOTO = "boto"
|
|
106
|
+
BOTO3SQS = "boto3sqs"
|
|
107
|
+
BOTOCORE = "botocore"
|
|
108
|
+
CASSANDRA = "cassandra"
|
|
109
|
+
CELERY = "celery"
|
|
48
110
|
CHROMA = "chroma"
|
|
111
|
+
CLICK = "click"
|
|
49
112
|
COHEREAI = "cohere_ai"
|
|
113
|
+
CONFLUENT_KAFKA = "confluent_kafka"
|
|
50
114
|
CREW = "crew"
|
|
115
|
+
DBAPI = "dbapi"
|
|
116
|
+
DJANGO = "django"
|
|
117
|
+
ELASTICSEARCH = "elasticsearch"
|
|
118
|
+
FALCON = "falcon"
|
|
51
119
|
FASTAPI = "fastapi"
|
|
120
|
+
FLASK = "flask"
|
|
52
121
|
GOOGLE_GENERATIVEAI = "google_genai"
|
|
53
122
|
GROQ = "groq"
|
|
123
|
+
GRPC = "grpc"
|
|
54
124
|
HAYSTACK = "haystack"
|
|
55
125
|
HTTPX = "httpx"
|
|
126
|
+
JINJA2 = "jinja2"
|
|
127
|
+
KAFKA_PYTHON = "kafka_python"
|
|
56
128
|
LANCEDB = "lancedb"
|
|
57
129
|
LANGCHAIN = "langchain"
|
|
58
130
|
LLAMA_INDEX = "llama_index"
|
|
131
|
+
LOGGING = "logging"
|
|
59
132
|
MARQO = "marqo"
|
|
60
133
|
MCP = "mcp"
|
|
61
134
|
MILVUS = "milvus"
|
|
62
135
|
MISTRALAI = "mistral_ai"
|
|
136
|
+
MYSQL = "mysql"
|
|
137
|
+
MYSQLCLIENT = "mysqlclient"
|
|
63
138
|
OLLAMA = "ollama"
|
|
64
139
|
OPENAI = "openai"
|
|
140
|
+
PIKA = "pika"
|
|
65
141
|
PINECONE = "pinecone"
|
|
142
|
+
PSYCOPG = "psycopg"
|
|
143
|
+
PSYCOPG2 = "psycopg2"
|
|
144
|
+
PYMEMCACHE = "pymemcache"
|
|
145
|
+
PYMONGO = "pymongo"
|
|
146
|
+
PYMSSQL = "pymssql"
|
|
66
147
|
PYMYSQL = "pymysql"
|
|
148
|
+
PYRAMID = "pyramid"
|
|
67
149
|
QDRANTDB = "qdrant_db"
|
|
68
150
|
REDIS = "redis"
|
|
151
|
+
REMOULADE = "remoulade"
|
|
69
152
|
REPLICATE = "replicate"
|
|
70
153
|
REQUESTS = "requests"
|
|
71
154
|
SAGEMAKER = "sagemaker"
|
|
155
|
+
SQLALCHEMY = "sqlalchemy"
|
|
156
|
+
SQLITE3 = "sqlite3"
|
|
157
|
+
STARLETTE = "starlette"
|
|
158
|
+
SYSTEM_METRICS = "system_metrics"
|
|
159
|
+
THREADING = "threading"
|
|
72
160
|
TOGETHER = "together"
|
|
161
|
+
TORNADO = "tornado"
|
|
162
|
+
TORTOISEORM = "tortoiseorm"
|
|
73
163
|
TRANSFORMERS = "transformers"
|
|
164
|
+
URLLIB = "urllib"
|
|
74
165
|
URLLIB3 = "urllib3"
|
|
75
166
|
VERTEXAI = "vertexai"
|
|
76
167
|
WATSONX = "watsonx"
|
|
77
168
|
WEAVIATEDB = "weaviate_db"
|
|
169
|
+
WSGI = "wsgi"
|
|
78
170
|
"""
|
netra/session.py
CHANGED
|
@@ -7,6 +7,8 @@ from opentelemetry import trace
|
|
|
7
7
|
from opentelemetry.trace import SpanKind, Status, StatusCode
|
|
8
8
|
from opentelemetry.trace.propagation import set_span_in_context
|
|
9
9
|
|
|
10
|
+
from netra.config import Config
|
|
11
|
+
|
|
10
12
|
# Configure logging
|
|
11
13
|
logging.basicConfig(level=logging.INFO)
|
|
12
14
|
logger = logging.getLogger(__name__)
|
|
@@ -19,9 +21,15 @@ class ATTRIBUTE:
|
|
|
19
21
|
NEGATIVE_PROMPT = "negative_prompt"
|
|
20
22
|
IMAGE_HEIGHT = "image_height"
|
|
21
23
|
IMAGE_WIDTH = "image_width"
|
|
22
|
-
TOKENS = "tokens"
|
|
23
24
|
CREDITS = "credits"
|
|
24
|
-
|
|
25
|
+
TOTAL_COST = "total_cost"
|
|
26
|
+
TOTAL_TOKENS = "total_tokens"
|
|
27
|
+
PROMPT_TOKENS_COST = "prompt_tokens_cost"
|
|
28
|
+
PROMPT_TOKENS = "prompt_tokens"
|
|
29
|
+
COMPLETION_TOKENS_COST = "completion_tokens_cost"
|
|
30
|
+
COMPLETION_TOKENS = "completion_tokens"
|
|
31
|
+
CACHED_TOKENS_COST = "cached_tokens_cost"
|
|
32
|
+
CACHED_TOKENS = "cached_tokens"
|
|
25
33
|
STATUS = "status"
|
|
26
34
|
DURATION_MS = "duration_ms"
|
|
27
35
|
ERROR_MESSAGE = "error_message"
|
|
@@ -76,7 +84,7 @@ class Session:
|
|
|
76
84
|
|
|
77
85
|
# Set duration
|
|
78
86
|
if duration_ms is not None:
|
|
79
|
-
self.set_attribute(ATTRIBUTE.DURATION_MS, str(round(duration_ms, 2)))
|
|
87
|
+
self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.DURATION_MS}", str(round(duration_ms, 2)))
|
|
80
88
|
|
|
81
89
|
# Handle status and errors
|
|
82
90
|
if exc_type is None and self.status == "pending":
|
|
@@ -86,14 +94,14 @@ class Session:
|
|
|
86
94
|
elif exc_type is not None:
|
|
87
95
|
self.status = "error"
|
|
88
96
|
self.error_message = str(exc_val)
|
|
89
|
-
self.set_attribute(ATTRIBUTE.ERROR_MESSAGE, self.error_message)
|
|
97
|
+
self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.ERROR_MESSAGE}", self.error_message)
|
|
90
98
|
if self.span:
|
|
91
99
|
self.span.set_status(Status(StatusCode.ERROR, self.error_message))
|
|
92
100
|
if exc_val is not None:
|
|
93
101
|
self.span.record_exception(exc_val)
|
|
94
102
|
logger.error(f"Session {self.name} failed: {self.error_message}")
|
|
95
103
|
|
|
96
|
-
self.set_attribute(ATTRIBUTE.STATUS, self.status)
|
|
104
|
+
self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.STATUS}", self.status)
|
|
97
105
|
|
|
98
106
|
# Update span attributes with final values
|
|
99
107
|
if self.span:
|
|
@@ -125,39 +133,63 @@ class Session:
|
|
|
125
133
|
|
|
126
134
|
def set_prompt(self, prompt: str) -> "Session":
|
|
127
135
|
"""Set the input prompt."""
|
|
128
|
-
return self.set_attribute(ATTRIBUTE.PROMPT, prompt)
|
|
136
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.PROMPT}", prompt)
|
|
129
137
|
|
|
130
138
|
def set_negative_prompt(self, negative_prompt: str) -> "Session":
|
|
131
139
|
"""Set the negative prompt."""
|
|
132
|
-
return self.set_attribute(ATTRIBUTE.NEGATIVE_PROMPT, negative_prompt)
|
|
140
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.NEGATIVE_PROMPT}", negative_prompt)
|
|
133
141
|
|
|
134
142
|
def set_image_height(self, height: str) -> "Session":
|
|
135
143
|
"""Set the image height."""
|
|
136
|
-
return self.set_attribute(ATTRIBUTE.IMAGE_HEIGHT, height)
|
|
144
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.IMAGE_HEIGHT}", height)
|
|
137
145
|
|
|
138
146
|
def set_image_width(self, width: str) -> "Session":
|
|
139
147
|
"""Set the image width."""
|
|
140
|
-
return self.set_attribute(ATTRIBUTE.IMAGE_WIDTH, width)
|
|
148
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.IMAGE_WIDTH}", width)
|
|
149
|
+
|
|
150
|
+
def set_total_tokens(self, tokens: str) -> "Session":
|
|
151
|
+
"""Set the number of tokens used."""
|
|
152
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.TOTAL_TOKENS}", tokens)
|
|
153
|
+
|
|
154
|
+
def set_prompt_tokens_cost(self, cost: str) -> "Session":
|
|
155
|
+
"""Set the number of tokens used."""
|
|
156
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.PROMPT_TOKENS_COST}", cost)
|
|
157
|
+
|
|
158
|
+
def set_prompt_tokens(self, tokens: str) -> "Session":
|
|
159
|
+
"""Set the number of tokens used."""
|
|
160
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.PROMPT_TOKENS}", tokens)
|
|
161
|
+
|
|
162
|
+
def set_completion_tokens_cost(self, cost: str) -> "Session":
|
|
163
|
+
"""Set the number of tokens used."""
|
|
164
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.COMPLETION_TOKENS_COST}", cost)
|
|
165
|
+
|
|
166
|
+
def set_completion_tokens(self, tokens: str) -> "Session":
|
|
167
|
+
"""Set the number of tokens used."""
|
|
168
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.COMPLETION_TOKENS}", tokens)
|
|
169
|
+
|
|
170
|
+
def set_cached_tokens_cost(self, cost: str) -> "Session":
|
|
171
|
+
"""Set the number of tokens used."""
|
|
172
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.CACHED_TOKENS_COST}", cost)
|
|
141
173
|
|
|
142
|
-
def
|
|
174
|
+
def set_cached_tokens(self, tokens: str) -> "Session":
|
|
143
175
|
"""Set the number of tokens used."""
|
|
144
|
-
return self.set_attribute(ATTRIBUTE.
|
|
176
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.CACHED_TOKENS}", tokens)
|
|
145
177
|
|
|
146
178
|
def set_credits(self, credits: str) -> "Session":
|
|
147
179
|
"""Set the number of credits used."""
|
|
148
|
-
return self.set_attribute(ATTRIBUTE.CREDITS, credits)
|
|
180
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.CREDITS}", credits)
|
|
149
181
|
|
|
150
|
-
def
|
|
182
|
+
def set_total_cost(self, cost: str) -> "Session":
|
|
151
183
|
"""Set the cost of the operation."""
|
|
152
|
-
return self.set_attribute(ATTRIBUTE.
|
|
184
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.TOTAL_COST}", cost)
|
|
153
185
|
|
|
154
186
|
def set_model(self, model: str) -> "Session":
|
|
155
187
|
"""Set the model used."""
|
|
156
|
-
return self.set_attribute(ATTRIBUTE.MODEL, model)
|
|
188
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.MODEL}", model)
|
|
157
189
|
|
|
158
190
|
def set_llm_system(self, system: str) -> "Session":
|
|
159
191
|
"""Set the LLM system used."""
|
|
160
|
-
return self.set_attribute(ATTRIBUTE.LLM_SYSTEM, system)
|
|
192
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.LLM_SYSTEM}", system)
|
|
161
193
|
|
|
162
194
|
def set_error(self, error_message: str) -> "Session":
|
|
163
195
|
"""Manually set an error message."""
|
|
@@ -165,7 +197,7 @@ class Session:
|
|
|
165
197
|
self.error_message = error_message
|
|
166
198
|
if self.span:
|
|
167
199
|
self.span.set_status(Status(StatusCode.ERROR, error_message))
|
|
168
|
-
return self.set_attribute(ATTRIBUTE.ERROR_MESSAGE, error_message)
|
|
200
|
+
return self.set_attribute(f"{Config.LIBRARY_NAME}.{ATTRIBUTE.ERROR_MESSAGE}", error_message)
|
|
169
201
|
|
|
170
202
|
def set_success(self) -> "Session":
|
|
171
203
|
"""Manually mark the session as successful."""
|
netra/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.1"
|
|
@@ -198,4 +198,4 @@
|
|
|
198
198
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
199
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
200
|
See the License for the specific language governing permissions and
|
|
201
|
-
limitations under the License.
|
|
201
|
+
limitations under the License.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: netra-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
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
|
|
@@ -20,9 +20,54 @@ Classifier: Typing :: Typed
|
|
|
20
20
|
Provides-Extra: llm-guard
|
|
21
21
|
Requires-Dist: llm-guard (>=0.3.16,<0.4.0) ; extra == "llm-guard"
|
|
22
22
|
Requires-Dist: opentelemetry-api (>=1.34.0,<2.0.0)
|
|
23
|
+
Requires-Dist: opentelemetry-instrumentation-aio-pika (>=0.55b1,<1.0.0)
|
|
23
24
|
Requires-Dist: opentelemetry-instrumentation-aiohttp-client (>=0.55b1,<1.0.0)
|
|
25
|
+
Requires-Dist: opentelemetry-instrumentation-aiohttp-server (>=0.55b1,<1.0.0)
|
|
26
|
+
Requires-Dist: opentelemetry-instrumentation-aiokafka (>=0.55b1,<1.0.0)
|
|
27
|
+
Requires-Dist: opentelemetry-instrumentation-aiopg (>=0.55b1,<1.0.0)
|
|
28
|
+
Requires-Dist: opentelemetry-instrumentation-asyncclick (>=0.55b1,<1.0.0)
|
|
29
|
+
Requires-Dist: opentelemetry-instrumentation-asyncio (>=0.55b1,<1.0.0)
|
|
30
|
+
Requires-Dist: opentelemetry-instrumentation-asyncpg (>=0.55b1,<1.0.0)
|
|
31
|
+
Requires-Dist: opentelemetry-instrumentation-aws-lambda (>=0.55b1,<1.0.0)
|
|
32
|
+
Requires-Dist: opentelemetry-instrumentation-boto (>=0.55b1,<1.0.0)
|
|
33
|
+
Requires-Dist: opentelemetry-instrumentation-boto3sqs (>=0.55b1,<1.0.0)
|
|
34
|
+
Requires-Dist: opentelemetry-instrumentation-botocore (>=0.55b1,<1.0.0)
|
|
35
|
+
Requires-Dist: opentelemetry-instrumentation-cassandra (>=0.55b1,<1.0.0)
|
|
36
|
+
Requires-Dist: opentelemetry-instrumentation-celery (>=0.55b1,<1.0.0)
|
|
37
|
+
Requires-Dist: opentelemetry-instrumentation-click (>=0.55b1,<1.0.0)
|
|
38
|
+
Requires-Dist: opentelemetry-instrumentation-confluent-kafka (>=0.55b1,<1.0.0)
|
|
39
|
+
Requires-Dist: opentelemetry-instrumentation-django (>=0.55b1,<1.0.0)
|
|
40
|
+
Requires-Dist: opentelemetry-instrumentation-elasticsearch (>=0.55b1,<1.0.0)
|
|
41
|
+
Requires-Dist: opentelemetry-instrumentation-falcon (>=0.55b1,<1.0.0)
|
|
24
42
|
Requires-Dist: opentelemetry-instrumentation-fastapi (>=0.55b1,<1.0.0)
|
|
43
|
+
Requires-Dist: opentelemetry-instrumentation-flask (>=0.55b1,<1.0.0)
|
|
44
|
+
Requires-Dist: opentelemetry-instrumentation-grpc (>=0.55b1,<1.0.0)
|
|
25
45
|
Requires-Dist: opentelemetry-instrumentation-httpx (>=0.55b1,<1.0.0)
|
|
46
|
+
Requires-Dist: opentelemetry-instrumentation-jinja2 (>=0.55b1,<1.0.0)
|
|
47
|
+
Requires-Dist: opentelemetry-instrumentation-kafka-python (>=0.55b1,<1.0.0)
|
|
48
|
+
Requires-Dist: opentelemetry-instrumentation-logging (>=0.55b1,<1.0.0)
|
|
49
|
+
Requires-Dist: opentelemetry-instrumentation-mysql (>=0.55b1,<1.0.0)
|
|
50
|
+
Requires-Dist: opentelemetry-instrumentation-mysqlclient (>=0.55b1,<1.0.0)
|
|
51
|
+
Requires-Dist: opentelemetry-instrumentation-pika (>=0.55b1,<1.0.0)
|
|
52
|
+
Requires-Dist: opentelemetry-instrumentation-psycopg (>=0.55b1,<1.0.0)
|
|
53
|
+
Requires-Dist: opentelemetry-instrumentation-psycopg2 (>=0.55b1,<1.0.0)
|
|
54
|
+
Requires-Dist: opentelemetry-instrumentation-pymemcache (>=0.55b1,<1.0.0)
|
|
55
|
+
Requires-Dist: opentelemetry-instrumentation-pymongo (>=0.55b1,<1.0.0)
|
|
56
|
+
Requires-Dist: opentelemetry-instrumentation-pymssql (>=0.55b1,<1.0.0)
|
|
57
|
+
Requires-Dist: opentelemetry-instrumentation-pymysql (>=0.55b1,<1.0.0)
|
|
58
|
+
Requires-Dist: opentelemetry-instrumentation-pyramid (>=0.55b1,<1.0.0)
|
|
59
|
+
Requires-Dist: opentelemetry-instrumentation-redis (>=0.55b1,<1.0.0)
|
|
60
|
+
Requires-Dist: opentelemetry-instrumentation-remoulade (>=0.55b1,<1.0.0)
|
|
61
|
+
Requires-Dist: opentelemetry-instrumentation-requests (>=0.55b1,<1.0.0)
|
|
62
|
+
Requires-Dist: opentelemetry-instrumentation-sqlalchemy (>=0.55b1,<1.0.0)
|
|
63
|
+
Requires-Dist: opentelemetry-instrumentation-sqlite3 (>=0.55b1,<1.0.0)
|
|
64
|
+
Requires-Dist: opentelemetry-instrumentation-starlette (>=0.55b1,<1.0.0)
|
|
65
|
+
Requires-Dist: opentelemetry-instrumentation-system-metrics (>=0.55b1,<1.0.0)
|
|
66
|
+
Requires-Dist: opentelemetry-instrumentation-threading (>=0.55b1,<1.0.0)
|
|
67
|
+
Requires-Dist: opentelemetry-instrumentation-tornado (>=0.55b1,<1.0.0)
|
|
68
|
+
Requires-Dist: opentelemetry-instrumentation-tortoiseorm (>=0.55b1,<1.0.0)
|
|
69
|
+
Requires-Dist: opentelemetry-instrumentation-urllib (>=0.55b1,<1.0.0)
|
|
70
|
+
Requires-Dist: opentelemetry-instrumentation-urllib3 (>=0.55b1,<1.0.0)
|
|
26
71
|
Requires-Dist: opentelemetry-sdk (>=1.34.0,<2.0.0)
|
|
27
72
|
Requires-Dist: presidio-analyzer (>=2.2.358,<3.0.0)
|
|
28
73
|
Requires-Dist: traceloop-sdk (>=0.40.7,<0.41.0)
|
|
@@ -180,16 +225,47 @@ class CustomerSupportAgent:
|
|
|
180
225
|
- **AIOHTTP** - Asynchronous HTTP client/server
|
|
181
226
|
- **FastAPI** - Modern web framework for APIs
|
|
182
227
|
- **Requests** - Popular HTTP library for Python
|
|
183
|
-
- **
|
|
228
|
+
- **Django** - High-level Python web framework
|
|
229
|
+
- **Flask** - Lightweight WSGI web application framework
|
|
230
|
+
- **Falcon** - High-performance Python web framework
|
|
231
|
+
- **Pyramid** - Small, fast, down-to-earth Python web framework
|
|
232
|
+
- **Starlette** - Lightweight ASGI framework/toolkit
|
|
233
|
+
- **Tornado** - Asynchronous networking library and web framework
|
|
234
|
+
- **gRPC** - High-performance, open-source universal RPC framework
|
|
235
|
+
- **Urllib** - Standard Python HTTP client library
|
|
236
|
+
- **Urllib3** - Powerful, user-friendly HTTP client for Python
|
|
184
237
|
|
|
185
238
|
### 🗄️ Database Clients
|
|
186
239
|
|
|
187
240
|
- **PyMySQL** - Pure Python MySQL client
|
|
188
241
|
- **Redis** - In-memory data structure store
|
|
242
|
+
- **SQLAlchemy** - SQL toolkit and Object-Relational Mapper
|
|
243
|
+
- **Psycopg** - Modern PostgreSQL database adapter for Python
|
|
244
|
+
- **Pymongo** - Python driver for MongoDB
|
|
245
|
+
- **Elasticsearch** - Distributed, RESTful search and analytics engine
|
|
246
|
+
- **Cassandra** - Distributed NoSQL database
|
|
247
|
+
- **PyMSSQL** - Simple Microsoft SQL Server client
|
|
248
|
+
- **MySQL Connector** - Official MySQL driver
|
|
249
|
+
- **Sqlite3** - Built-in SQL database engine
|
|
250
|
+
- **Aiopg** - Asynchronous PostgreSQL client
|
|
251
|
+
- **Asyncpg** - Fast asynchronous PostgreSQL client
|
|
252
|
+
- **Pymemcache** - Comprehensive Memcached client
|
|
253
|
+
- **Tortoise ORM** - Easy-to-use asyncio ORM
|
|
254
|
+
|
|
255
|
+
### 📨 Messaging & Task Queues
|
|
256
|
+
|
|
257
|
+
- **Celery** - Distributed task queue
|
|
258
|
+
- **Pika** - Pure-Python implementation of the AMQP 0-9-1 protocol
|
|
259
|
+
- **AIO Pika** - Asynchronous AMQP client
|
|
260
|
+
- **Kafka-Python** - Python client for Apache Kafka
|
|
261
|
+
- **AIOKafka** - Asynchronous Python client for Kafka
|
|
262
|
+
- **Confluent-Kafka** - Confluent's Python client for Apache Kafka
|
|
263
|
+
- **Boto3 SQS** - Amazon SQS client via Boto3
|
|
189
264
|
|
|
190
265
|
### 🔧 AI Frameworks & Orchestration
|
|
191
266
|
|
|
192
267
|
- **LangChain** - Framework for developing LLM applications
|
|
268
|
+
- **LangGraph** - Modern framework for LLM applications
|
|
193
269
|
- **LlamaIndex** - Data framework for LLM applications
|
|
194
270
|
- **Haystack** - End-to-end NLP framework
|
|
195
271
|
- **CrewAI** - Multi-agent AI systems
|
|
@@ -364,6 +440,72 @@ with Netra.start_session("video_generation_task") as session:
|
|
|
364
440
|
|
|
365
441
|
## 🔧 Advanced Configuration
|
|
366
442
|
|
|
443
|
+
### Environment Variables
|
|
444
|
+
|
|
445
|
+
Netra SDK can be configured using the following environment variables:
|
|
446
|
+
|
|
447
|
+
#### Netra-specific Variables
|
|
448
|
+
|
|
449
|
+
| Variable Name | Description | Default |
|
|
450
|
+
|---------------|-------------|---------|
|
|
451
|
+
| `NETRA_APP_NAME` | Logical name for your service | Falls back to `OTEL_SERVICE_NAME` or `llm_tracing_service` |
|
|
452
|
+
| `NETRA_OTLP_ENDPOINT` | URL for OTLP collector | Falls back to `OTEL_EXPORTER_OTLP_ENDPOINT` |
|
|
453
|
+
| `NETRA_API_KEY` | API key for authentication | `None` |
|
|
454
|
+
| `NETRA_HEADERS` | Additional headers in W3C Correlation-Context format | `None` |
|
|
455
|
+
| `NETRA_DISABLE_BATCH` | Disable batch span processor (`true`/`false`) | `false` |
|
|
456
|
+
| `NETRA_TRACE_CONTENT` | Whether to capture prompt/completion content (`true`/`false`) | `true` |
|
|
457
|
+
| `NETRA_ENV` | Deployment environment (e.g., `prod`, `staging`, `dev`) | `local` |
|
|
458
|
+
| `NETRA_RESOURCE_ATTRS` | JSON string of custom resource attributes | `{}` |
|
|
459
|
+
|
|
460
|
+
#### Standard OpenTelemetry Variables
|
|
461
|
+
|
|
462
|
+
| Variable Name | Description | Used When |
|
|
463
|
+
|---------------|-------------|-----------|
|
|
464
|
+
| `OTEL_SERVICE_NAME` | Logical name for your service | When `NETRA_APP_NAME` is not set |
|
|
465
|
+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | URL for OTLP collector | When `NETRA_OTLP_ENDPOINT` is not set |
|
|
466
|
+
| `OTEL_EXPORTER_OTLP_HEADERS` | Additional headers for OTLP exporter | When `NETRA_HEADERS` is not set |
|
|
467
|
+
| `OTEL_RESOURCE_ATTRIBUTES` | Additional resource attributes | When `NETRA_RESOURCE_ATTRS` is not set |
|
|
468
|
+
|
|
469
|
+
### Configuration Precedence
|
|
470
|
+
|
|
471
|
+
Configuration values are resolved in the following order (highest to lowest precedence):
|
|
472
|
+
|
|
473
|
+
1. **Code Parameters**: Values passed directly to `Netra.init()`
|
|
474
|
+
2. **Netra Environment Variables**: `NETRA_*` variables
|
|
475
|
+
3. **OpenTelemetry Environment Variables**: Standard `OTEL_*` variables
|
|
476
|
+
4. **Default Values**: Fallback values defined in the SDK
|
|
477
|
+
|
|
478
|
+
This allows you to:
|
|
479
|
+
- Override any setting directly in code for maximum control
|
|
480
|
+
- Use Netra-specific environment variables for Netra-specific settings
|
|
481
|
+
- Fall back to standard OpenTelemetry variables for compatibility
|
|
482
|
+
- Rely on sensible defaults when no other configuration is provided
|
|
483
|
+
|
|
484
|
+
**Example**:
|
|
485
|
+
```bash
|
|
486
|
+
export NETRA_APP_NAME="my-ai-service"
|
|
487
|
+
export NETRA_OTLP_ENDPOINT="https://collector.example.com:4318"
|
|
488
|
+
export NETRA_API_KEY="your-api-key-here"
|
|
489
|
+
export NETRA_ENV="production"
|
|
490
|
+
export NETRA_RESOURCE_ATTRS='{"team":"ai", "version":"1.0.0"}'
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### Programmatic Configuration
|
|
494
|
+
|
|
495
|
+
You can also configure the SDK programmatically when initializing:
|
|
496
|
+
|
|
497
|
+
```python
|
|
498
|
+
from netra import Netra
|
|
499
|
+
|
|
500
|
+
Netra.init(
|
|
501
|
+
app_name="my-ai-service",
|
|
502
|
+
environment="production",
|
|
503
|
+
resource_attributes={"team": "ai", "version": "1.0.0"},
|
|
504
|
+
trace_content=True,
|
|
505
|
+
disable_batch=False
|
|
506
|
+
)
|
|
507
|
+
```
|
|
508
|
+
|
|
367
509
|
### Custom Instrumentation Selection
|
|
368
510
|
|
|
369
511
|
Control which instrumentations are enabled:
|
|
@@ -434,6 +576,7 @@ Netra.init(app_name="Your App")
|
|
|
434
576
|
- **📈 Rich Ecosystem**: Leverage the entire OpenTelemetry ecosystem
|
|
435
577
|
|
|
436
578
|
|
|
579
|
+
|
|
437
580
|
## 📚 Examples
|
|
438
581
|
|
|
439
582
|
The SDK includes comprehensive examples in the `examples/` directory:
|
|
@@ -446,61 +589,52 @@ The SDK includes comprehensive examples in the `examples/` directory:
|
|
|
446
589
|
|
|
447
590
|
## 🧪 Tests
|
|
448
591
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
### Test Structure
|
|
452
|
-
|
|
453
|
-
- **conftest.py**: Contains shared fixtures, test utilities, and configuration for all tests
|
|
454
|
-
- **test_netra_init.py**: Tests for the main Netra SDK initialization and configuration
|
|
455
|
-
- **test_decorators.py**: Tests for workflow, agent, and task decorators
|
|
456
|
-
- **test_input_scanner.py**: Tests for prompt injection scanning and security features
|
|
592
|
+
Our test suite is built on `pytest` and is designed to ensure the reliability and stability of the Netra SDK. We follow comprehensive testing standards, including unit, integration, and thread-safety tests.
|
|
457
593
|
|
|
458
594
|
### Running Tests
|
|
459
595
|
|
|
460
|
-
To run the
|
|
596
|
+
To run the complete test suite, use the following command from the root of the project:
|
|
461
597
|
|
|
462
598
|
```bash
|
|
463
599
|
poetry run pytest
|
|
464
600
|
```
|
|
465
601
|
|
|
466
|
-
To run specific test modules:
|
|
467
602
|
|
|
603
|
+
### Run Specific Test File
|
|
604
|
+
To run a specific test file, use the following command from the root of the project:
|
|
468
605
|
```bash
|
|
469
606
|
poetry run pytest tests/test_netra_init.py
|
|
470
|
-
poetry run pytest tests/test_decorators.py
|
|
471
607
|
```
|
|
472
608
|
|
|
473
|
-
|
|
609
|
+
### Test Coverage
|
|
610
|
+
|
|
611
|
+
To generate a test coverage report, you can run:
|
|
474
612
|
|
|
475
613
|
```bash
|
|
476
614
|
poetry run pytest --cov=netra --cov-report=html
|
|
477
615
|
```
|
|
478
616
|
|
|
479
|
-
|
|
617
|
+
This will create an `htmlcov` directory with a detailed report.
|
|
480
618
|
|
|
481
|
-
|
|
619
|
+
### Running Specific Test Categories
|
|
482
620
|
|
|
483
|
-
|
|
484
|
-
- **clean_environment**: Provides a clean environment by temporarily clearing relevant environment variables
|
|
485
|
-
- **mock_config**, **mock_tracer**, **mock_init_instrumentations**: Mock objects for testing components in isolation
|
|
486
|
-
- **sample_config_params**, **sample_session_data**: Sample data for testing configuration and sessions
|
|
487
|
-
|
|
488
|
-
### Test Categories
|
|
489
|
-
|
|
490
|
-
Tests are organized using pytest markers:
|
|
491
|
-
|
|
492
|
-
- **unit**: Unit tests for individual components
|
|
493
|
-
- **integration**: Integration tests for component interactions
|
|
494
|
-
- **thread_safety**: Tests for thread safety and concurrency
|
|
495
|
-
|
|
496
|
-
To run tests by category:
|
|
621
|
+
Tests are organized using `pytest` markers. You can run specific categories of tests as follows:
|
|
497
622
|
|
|
498
623
|
```bash
|
|
624
|
+
# Run only unit tests (default)
|
|
499
625
|
poetry run pytest -m unit
|
|
626
|
+
|
|
627
|
+
# Run only integration tests
|
|
500
628
|
poetry run pytest -m integration
|
|
629
|
+
|
|
630
|
+
# Run only thread-safety tests
|
|
501
631
|
poetry run pytest -m thread_safety
|
|
502
632
|
```
|
|
503
633
|
|
|
634
|
+
For more detailed information on our testing strategy, fixtures, and best practices, please refer to the `README.md` file in the `tests` directory.
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
|
|
504
638
|
## 🛠️ Development Setup
|
|
505
639
|
|
|
506
640
|
To set up your development environment for the Netra SDK, run the provided setup script:
|
|
@@ -3,13 +3,13 @@ netra/anonymizer/__init__.py,sha256=KeGPPZqKVZbtkbirEKYTYhj6aZHlakjdQhD7QHqBRio,
|
|
|
3
3
|
netra/anonymizer/anonymizer.py,sha256=1VeYAsFpF_tYDlqJF-Q82-ZXGOR4YWBqrKUsRw3qOrA,3539
|
|
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=6aUG-BWWDOyptnTlEjOpB41n9xLmuo-XBAgs5GE5Tbg,4761
|
|
7
7
|
netra/decorators.py,sha256=WX3EAvcZ_b-wUHO6UFXN07_J4H9shmrLSYPidYvTL5w,6257
|
|
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
|
|
11
11
|
netra/input_scanner.py,sha256=bzP3s7YudGHQrIbUgQGrcIBEJ6CmOewzuYNSu75cVXM,4988
|
|
12
|
-
netra/instrumentation/__init__.py,sha256=
|
|
12
|
+
netra/instrumentation/__init__.py,sha256=LLLd4oC62m4fbgS5vqjmu1SNeqYk78A-sb_lc9WTSiM,41009
|
|
13
13
|
netra/instrumentation/aiohttp/__init__.py,sha256=M1kuF0R3gKY5rlbhEC1AR13UWHelmfokluL2yFysKWc,14398
|
|
14
14
|
netra/instrumentation/aiohttp/version.py,sha256=Zy-0Aukx-HS_Mo3NKPWg-hlUoWKDzS0w58gLoVtJec8,24
|
|
15
15
|
netra/instrumentation/cohere/__init__.py,sha256=3XwmCAZwZiMkHdNN3YvcBOLsNCx80ymbU31TyMzv1IY,17685
|
|
@@ -20,7 +20,7 @@ netra/instrumentation/google_genai/utils.py,sha256=2OeSN5jUaMKF4x5zWiW65R1LB_a44
|
|
|
20
20
|
netra/instrumentation/google_genai/version.py,sha256=Hww1duZrC8kYK7ThBSQVyz0HNOb0ys_o8Pln-wVQ1hI,23
|
|
21
21
|
netra/instrumentation/httpx/__init__.py,sha256=w1su_eQP_w5ZJHq0Lf-4miF5zM4OOW0ItmRp0wi85Ew,19388
|
|
22
22
|
netra/instrumentation/httpx/version.py,sha256=ZRQKbgDaGz_yuLk-cUKuk6ZBKCSRKZC8nQd041NRNXk,23
|
|
23
|
-
netra/instrumentation/instruments.py,sha256=
|
|
23
|
+
netra/instrumentation/instruments.py,sha256=5U4r9XMMfjccd9BWHAbHMo1WcCUClnbU2oWTLAAqMw4,4345
|
|
24
24
|
netra/instrumentation/mistralai/__init__.py,sha256=RE0b-rS6iXdoynJMFKHL9s97eYo5HghrJa013fR4ZhI,18910
|
|
25
25
|
netra/instrumentation/mistralai/config.py,sha256=XCyo3mk30qkvqyCqeTrKwROahu0gcOEwmbDLOo53J5k,121
|
|
26
26
|
netra/instrumentation/mistralai/utils.py,sha256=nhdIer5gJFxuGwg8FCT222hggDHeMQDhJctnDSwLqcc,894
|
|
@@ -32,11 +32,11 @@ netra/processors/__init__.py,sha256=f8Ck-uCdDwNgEvm3hm6I9wFSVlnRYjmSfrEIQkdBaZQ,
|
|
|
32
32
|
netra/processors/session_span_processor.py,sha256=uv-KL5lwil3C3wQGdYWiYQMHLBsXrt8hTy_ql6kUWXE,2171
|
|
33
33
|
netra/processors/span_aggregation_processor.py,sha256=eOBAHTi5pgBCrnNthWGby0IY6b7iSUPAIFkDDmwLKOY,15579
|
|
34
34
|
netra/scanner.py,sha256=wqjMZnEbVvrGMiUSI352grUyHpkk94oBfHfMiXPhpGU,3866
|
|
35
|
-
netra/session.py,sha256=
|
|
35
|
+
netra/session.py,sha256=Lsd7yps2YtjN7P10HsGN3bRZxufoeUnGxAH6Us8_l-Y,8734
|
|
36
36
|
netra/session_manager.py,sha256=UusP3MRZlLeU4NtBVlXQ_sCgRg-LGleVdYPq5MwLvi8,3555
|
|
37
37
|
netra/tracer.py,sha256=WZDBIpPp3oL8MkKBhlw0gxAXXSd1FY3bicLUKt2GNxc,3540
|
|
38
|
-
netra/version.py,sha256=
|
|
39
|
-
netra_sdk-0.1.
|
|
40
|
-
netra_sdk-0.1.
|
|
41
|
-
netra_sdk-0.1.
|
|
42
|
-
netra_sdk-0.1.
|
|
38
|
+
netra/version.py,sha256=rnObPjuBcEStqSO0S6gsdS_ot8ITOQjVj_-P1LUUYpg,22
|
|
39
|
+
netra_sdk-0.1.1.dist-info/LICENCE,sha256=8B_UoZ-BAl0AqiHAHUETCgd3I2B9yYJ1WEQtVb_qFMA,11359
|
|
40
|
+
netra_sdk-0.1.1.dist-info/METADATA,sha256=ivXMgn4GzpCeQzZ29zGygcJlSfKnk5WSDsQu1pE4BLQ,24630
|
|
41
|
+
netra_sdk-0.1.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
42
|
+
netra_sdk-0.1.1.dist-info/RECORD,,
|
|
File without changes
|