openlit 1.34.30__py3-none-any.whl → 1.34.31__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.
- openlit/__helpers.py +235 -86
- openlit/__init__.py +16 -13
- openlit/_instrumentors.py +2 -1
- openlit/evals/all.py +50 -21
- openlit/evals/bias_detection.py +47 -20
- openlit/evals/hallucination.py +53 -22
- openlit/evals/toxicity.py +50 -21
- openlit/evals/utils.py +54 -30
- openlit/guard/all.py +61 -19
- openlit/guard/prompt_injection.py +34 -14
- openlit/guard/restrict_topic.py +46 -15
- openlit/guard/sensitive_topic.py +34 -14
- openlit/guard/utils.py +58 -22
- openlit/instrumentation/ag2/__init__.py +24 -8
- openlit/instrumentation/ag2/ag2.py +34 -13
- openlit/instrumentation/ag2/async_ag2.py +34 -13
- openlit/instrumentation/ag2/utils.py +133 -30
- openlit/instrumentation/ai21/__init__.py +43 -14
- openlit/instrumentation/ai21/ai21.py +47 -21
- openlit/instrumentation/ai21/async_ai21.py +47 -21
- openlit/instrumentation/ai21/utils.py +299 -78
- openlit/instrumentation/anthropic/__init__.py +21 -4
- openlit/instrumentation/anthropic/anthropic.py +28 -17
- openlit/instrumentation/anthropic/async_anthropic.py +28 -17
- openlit/instrumentation/anthropic/utils.py +145 -35
- openlit/instrumentation/assemblyai/__init__.py +11 -2
- openlit/instrumentation/assemblyai/assemblyai.py +15 -4
- openlit/instrumentation/assemblyai/utils.py +120 -25
- openlit/instrumentation/astra/__init__.py +43 -10
- openlit/instrumentation/astra/astra.py +28 -5
- openlit/instrumentation/astra/async_astra.py +28 -5
- openlit/instrumentation/astra/utils.py +151 -55
- openlit/instrumentation/azure_ai_inference/__init__.py +43 -10
- openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py +53 -21
- openlit/instrumentation/azure_ai_inference/azure_ai_inference.py +53 -21
- openlit/instrumentation/azure_ai_inference/utils.py +307 -83
- openlit/instrumentation/bedrock/__init__.py +21 -4
- openlit/instrumentation/bedrock/bedrock.py +63 -25
- openlit/instrumentation/bedrock/utils.py +139 -30
- openlit/instrumentation/chroma/__init__.py +89 -16
- openlit/instrumentation/chroma/chroma.py +28 -6
- openlit/instrumentation/chroma/utils.py +167 -51
- openlit/instrumentation/cohere/__init__.py +63 -18
- openlit/instrumentation/cohere/async_cohere.py +63 -24
- openlit/instrumentation/cohere/cohere.py +63 -24
- openlit/instrumentation/cohere/utils.py +286 -73
- openlit/instrumentation/controlflow/__init__.py +35 -9
- openlit/instrumentation/controlflow/controlflow.py +66 -33
- openlit/instrumentation/crawl4ai/__init__.py +25 -10
- openlit/instrumentation/crawl4ai/async_crawl4ai.py +78 -31
- openlit/instrumentation/crawl4ai/crawl4ai.py +78 -31
- openlit/instrumentation/crewai/__init__.py +40 -15
- openlit/instrumentation/crewai/async_crewai.py +32 -7
- openlit/instrumentation/crewai/crewai.py +32 -7
- openlit/instrumentation/crewai/utils.py +159 -56
- openlit/instrumentation/dynamiq/__init__.py +46 -12
- openlit/instrumentation/dynamiq/dynamiq.py +74 -33
- openlit/instrumentation/elevenlabs/__init__.py +23 -4
- openlit/instrumentation/elevenlabs/async_elevenlabs.py +16 -4
- openlit/instrumentation/elevenlabs/elevenlabs.py +16 -4
- openlit/instrumentation/elevenlabs/utils.py +128 -25
- openlit/instrumentation/embedchain/__init__.py +11 -2
- openlit/instrumentation/embedchain/embedchain.py +68 -35
- openlit/instrumentation/firecrawl/__init__.py +24 -7
- openlit/instrumentation/firecrawl/firecrawl.py +46 -20
- openlit/instrumentation/google_ai_studio/__init__.py +45 -10
- openlit/instrumentation/google_ai_studio/async_google_ai_studio.py +67 -44
- openlit/instrumentation/google_ai_studio/google_ai_studio.py +67 -44
- openlit/instrumentation/google_ai_studio/utils.py +180 -67
- openlit/instrumentation/gpt4all/__init__.py +22 -7
- openlit/instrumentation/gpt4all/gpt4all.py +67 -29
- openlit/instrumentation/gpt4all/utils.py +285 -61
- openlit/instrumentation/gpu/__init__.py +128 -47
- openlit/instrumentation/groq/__init__.py +21 -4
- openlit/instrumentation/groq/async_groq.py +33 -21
- openlit/instrumentation/groq/groq.py +33 -21
- openlit/instrumentation/groq/utils.py +192 -55
- openlit/instrumentation/haystack/__init__.py +70 -24
- openlit/instrumentation/haystack/async_haystack.py +28 -6
- openlit/instrumentation/haystack/haystack.py +28 -6
- openlit/instrumentation/haystack/utils.py +196 -74
- openlit/instrumentation/julep/__init__.py +69 -19
- openlit/instrumentation/julep/async_julep.py +53 -27
- openlit/instrumentation/julep/julep.py +53 -28
- openlit/instrumentation/langchain/__init__.py +74 -63
- openlit/instrumentation/langchain/callback_handler.py +1100 -0
- openlit/instrumentation/langchain_community/__init__.py +13 -2
- openlit/instrumentation/langchain_community/async_langchain_community.py +23 -5
- openlit/instrumentation/langchain_community/langchain_community.py +23 -5
- openlit/instrumentation/langchain_community/utils.py +35 -9
- openlit/instrumentation/letta/__init__.py +68 -15
- openlit/instrumentation/letta/letta.py +99 -54
- openlit/instrumentation/litellm/__init__.py +43 -14
- openlit/instrumentation/litellm/async_litellm.py +51 -26
- openlit/instrumentation/litellm/litellm.py +51 -26
- openlit/instrumentation/litellm/utils.py +304 -102
- openlit/instrumentation/llamaindex/__init__.py +267 -90
- openlit/instrumentation/llamaindex/async_llamaindex.py +28 -6
- openlit/instrumentation/llamaindex/llamaindex.py +28 -6
- openlit/instrumentation/llamaindex/utils.py +204 -91
- openlit/instrumentation/mem0/__init__.py +11 -2
- openlit/instrumentation/mem0/mem0.py +50 -29
- openlit/instrumentation/milvus/__init__.py +10 -2
- openlit/instrumentation/milvus/milvus.py +31 -6
- openlit/instrumentation/milvus/utils.py +166 -67
- openlit/instrumentation/mistral/__init__.py +63 -18
- openlit/instrumentation/mistral/async_mistral.py +63 -24
- openlit/instrumentation/mistral/mistral.py +63 -24
- openlit/instrumentation/mistral/utils.py +277 -69
- openlit/instrumentation/multion/__init__.py +69 -19
- openlit/instrumentation/multion/async_multion.py +57 -26
- openlit/instrumentation/multion/multion.py +57 -26
- openlit/instrumentation/ollama/__init__.py +39 -18
- openlit/instrumentation/ollama/async_ollama.py +57 -26
- openlit/instrumentation/ollama/ollama.py +57 -26
- openlit/instrumentation/ollama/utils.py +226 -50
- openlit/instrumentation/openai/__init__.py +156 -32
- openlit/instrumentation/openai/async_openai.py +147 -67
- openlit/instrumentation/openai/openai.py +150 -67
- openlit/instrumentation/openai/utils.py +657 -185
- openlit/instrumentation/openai_agents/__init__.py +5 -1
- openlit/instrumentation/openai_agents/processor.py +110 -90
- openlit/instrumentation/phidata/__init__.py +13 -5
- openlit/instrumentation/phidata/phidata.py +67 -32
- openlit/instrumentation/pinecone/__init__.py +48 -9
- openlit/instrumentation/pinecone/async_pinecone.py +27 -5
- openlit/instrumentation/pinecone/pinecone.py +27 -5
- openlit/instrumentation/pinecone/utils.py +153 -47
- openlit/instrumentation/premai/__init__.py +22 -7
- openlit/instrumentation/premai/premai.py +51 -26
- openlit/instrumentation/premai/utils.py +246 -59
- openlit/instrumentation/pydantic_ai/__init__.py +49 -22
- openlit/instrumentation/pydantic_ai/pydantic_ai.py +69 -16
- openlit/instrumentation/pydantic_ai/utils.py +89 -24
- openlit/instrumentation/qdrant/__init__.py +19 -4
- openlit/instrumentation/qdrant/async_qdrant.py +33 -7
- openlit/instrumentation/qdrant/qdrant.py +33 -7
- openlit/instrumentation/qdrant/utils.py +228 -93
- openlit/instrumentation/reka/__init__.py +23 -10
- openlit/instrumentation/reka/async_reka.py +17 -11
- openlit/instrumentation/reka/reka.py +17 -11
- openlit/instrumentation/reka/utils.py +138 -36
- openlit/instrumentation/together/__init__.py +44 -12
- openlit/instrumentation/together/async_together.py +50 -27
- openlit/instrumentation/together/together.py +50 -27
- openlit/instrumentation/together/utils.py +301 -71
- openlit/instrumentation/transformers/__init__.py +2 -1
- openlit/instrumentation/transformers/transformers.py +13 -3
- openlit/instrumentation/transformers/utils.py +139 -36
- openlit/instrumentation/vertexai/__init__.py +81 -16
- openlit/instrumentation/vertexai/async_vertexai.py +33 -15
- openlit/instrumentation/vertexai/utils.py +123 -27
- openlit/instrumentation/vertexai/vertexai.py +33 -15
- openlit/instrumentation/vllm/__init__.py +12 -5
- openlit/instrumentation/vllm/utils.py +121 -31
- openlit/instrumentation/vllm/vllm.py +16 -10
- openlit/otel/events.py +35 -10
- openlit/otel/metrics.py +32 -24
- openlit/otel/tracing.py +24 -9
- openlit/semcov/__init__.py +72 -6
- {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/METADATA +2 -1
- openlit-1.34.31.dist-info/RECORD +166 -0
- openlit/instrumentation/langchain/async_langchain.py +0 -102
- openlit/instrumentation/langchain/langchain.py +0 -102
- openlit/instrumentation/langchain/utils.py +0 -252
- openlit-1.34.30.dist-info/RECORD +0 -168
- {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/LICENSE +0 -0
- {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/WHEEL +0 -0
@@ -1,6 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
LlamaIndex OpenTelemetry Instrumentation
|
3
3
|
"""
|
4
|
+
|
4
5
|
import time
|
5
6
|
import hashlib
|
6
7
|
from opentelemetry.trace import Status, StatusCode
|
@@ -15,29 +16,24 @@ from openlit.semcov import SemanticConvention
|
|
15
16
|
# Simplified semantic conventions for efficient processing
|
16
17
|
OPERATION_MAP = {
|
17
18
|
# === WORKFLOW OPERATIONS (Business-level spans) ===
|
18
|
-
|
19
19
|
# Document Loading & Processing Pipeline
|
20
20
|
"document_load": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
21
21
|
"document_load_async": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
22
22
|
"document_transform": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
23
23
|
"document_split": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
24
|
-
|
25
24
|
# Index Construction & Management
|
26
25
|
"index_construct": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
27
26
|
"index_insert": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
28
27
|
"index_delete": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
29
28
|
"index_build": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
30
|
-
|
31
29
|
# Query Engine Operations
|
32
30
|
"query_engine_create": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
33
31
|
"query_engine_query": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
34
32
|
"query_engine_query_async": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
35
|
-
|
36
33
|
# Retriever Operations
|
37
34
|
"retriever_create": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
38
35
|
"retriever_retrieve": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
39
36
|
"retriever_retrieve_async": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
40
|
-
|
41
37
|
# LLM & Embedding Operations
|
42
38
|
"llm_complete": SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
|
43
39
|
"llm_complete_async": SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
|
@@ -46,39 +42,31 @@ OPERATION_MAP = {
|
|
46
42
|
"llm_stream_async": SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
|
47
43
|
"embedding_generate": SemanticConvention.GEN_AI_OPERATION_TYPE_EMBEDDING,
|
48
44
|
"embedding_generate_async": SemanticConvention.GEN_AI_OPERATION_TYPE_EMBEDDING,
|
49
|
-
|
50
45
|
# Response Generation Operations
|
51
46
|
"response_generate_async": SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
|
52
|
-
|
53
47
|
# === COMPONENT OPERATIONS (Technical-level spans) ===
|
54
|
-
|
55
48
|
# Text Processing Components
|
56
49
|
"text_splitter_split": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
57
50
|
"text_splitter_postprocess": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
58
51
|
"node_parser_parse": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
59
|
-
|
60
52
|
# Embedding Processing Components
|
61
53
|
"embedding_encode": SemanticConvention.GEN_AI_OPERATION_TYPE_EMBEDDING,
|
62
54
|
"embedding_embed_nodes": SemanticConvention.GEN_AI_OPERATION_TYPE_EMBEDDING,
|
63
55
|
"embedding_similarity": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
64
56
|
"embedding_metadata": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
65
|
-
|
66
57
|
# Retrieval Processing Components
|
67
58
|
"retrieval_retrieve_nodes": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
68
59
|
"retrieval_get_nodes": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
69
60
|
"retrieval_build_nodes": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
70
61
|
"postprocessor_process": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
71
|
-
|
72
62
|
# Response Generation Components
|
73
63
|
"response_synthesize": SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
|
74
64
|
"response_compact_refine": SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
|
75
65
|
"response_tree_summarize": SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
|
76
|
-
|
77
66
|
# Vector Store Components
|
78
67
|
"vector_store_add": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
79
68
|
"vector_store_delete": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
80
69
|
"vector_store_query": SemanticConvention.GEN_AI_OPERATION_TYPE_RETRIEVE,
|
81
|
-
|
82
70
|
# Document & Node Components
|
83
71
|
"document_get_content": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
84
72
|
"node_get_content": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
@@ -87,16 +75,17 @@ OPERATION_MAP = {
|
|
87
75
|
"query_prepare_response": SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
|
88
76
|
}
|
89
77
|
|
78
|
+
|
90
79
|
def set_server_address_and_port(instance, default_host="localhost", default_port=8000):
|
91
80
|
"""Extract server address and port with enhanced detection"""
|
92
|
-
if hasattr(instance,
|
81
|
+
if hasattr(instance, "_client"):
|
93
82
|
client = instance._client
|
94
|
-
if hasattr(client,
|
83
|
+
if hasattr(client, "base_url"):
|
95
84
|
base_url = str(client.base_url)
|
96
|
-
if
|
97
|
-
parts = base_url.split(
|
98
|
-
if
|
99
|
-
host, port = parts.rsplit(
|
85
|
+
if "://" in base_url:
|
86
|
+
parts = base_url.split("://", 1)[1].split("/", 1)[0]
|
87
|
+
if ":" in parts:
|
88
|
+
host, port = parts.rsplit(":", 1)
|
100
89
|
try:
|
101
90
|
return host, int(port)
|
102
91
|
except ValueError:
|
@@ -104,20 +93,22 @@ def set_server_address_and_port(instance, default_host="localhost", default_port
|
|
104
93
|
return parts, default_port
|
105
94
|
return default_host, default_port
|
106
95
|
|
96
|
+
|
107
97
|
def object_count(obj):
|
108
98
|
"""Enhanced object counting with type detection"""
|
109
99
|
if obj is None:
|
110
100
|
return 0
|
111
101
|
try:
|
112
|
-
if hasattr(obj,
|
102
|
+
if hasattr(obj, "__len__"):
|
113
103
|
return len(obj)
|
114
|
-
elif hasattr(obj,
|
104
|
+
elif hasattr(obj, "__iter__"):
|
115
105
|
return sum(1 for _ in obj)
|
116
106
|
else:
|
117
107
|
return 1 if obj else 0
|
118
108
|
except Exception:
|
119
109
|
return 0
|
120
110
|
|
111
|
+
|
121
112
|
def extract_performance_metrics(scope):
|
122
113
|
"""Extract comprehensive performance metrics"""
|
123
114
|
duration = scope._end_time - scope._start_time
|
@@ -137,9 +128,10 @@ def extract_performance_metrics(scope):
|
|
137
128
|
"performance_tier": performance_tier,
|
138
129
|
"latency_ms": duration * 1000,
|
139
130
|
"is_fast": duration < 0.5,
|
140
|
-
"needs_optimization": duration > 2.0
|
131
|
+
"needs_optimization": duration > 2.0,
|
141
132
|
}
|
142
133
|
|
134
|
+
|
143
135
|
def extract_content_metrics(content):
|
144
136
|
"""Extract advanced content analysis metrics"""
|
145
137
|
if not content:
|
@@ -161,9 +153,10 @@ def extract_content_metrics(content):
|
|
161
153
|
"complexity_score": complexity_score,
|
162
154
|
"content_hash": hashlib.md5(content_str.encode()).hexdigest()[:8],
|
163
155
|
"is_lengthy": char_count > 1000,
|
164
|
-
"is_complex": complexity_score > 50
|
156
|
+
"is_complex": complexity_score > 50,
|
165
157
|
}
|
166
158
|
|
159
|
+
|
167
160
|
def extract_business_intelligence(scope, endpoint):
|
168
161
|
"""Extract superior business intelligence attributes"""
|
169
162
|
bi_attrs = {}
|
@@ -193,9 +186,19 @@ def extract_business_intelligence(scope, endpoint):
|
|
193
186
|
|
194
187
|
return bi_attrs
|
195
188
|
|
196
|
-
|
197
|
-
|
198
|
-
|
189
|
+
|
190
|
+
def common_llamaindex_logic(
|
191
|
+
scope,
|
192
|
+
environment,
|
193
|
+
application_name,
|
194
|
+
metrics,
|
195
|
+
capture_message_content,
|
196
|
+
disable_metrics,
|
197
|
+
version,
|
198
|
+
instance=None,
|
199
|
+
endpoint=None,
|
200
|
+
**kwargs,
|
201
|
+
):
|
199
202
|
"""
|
200
203
|
DOMINANCE EDITION: Process LlamaIndex with superior attribute richness
|
201
204
|
Enhanced to beat OpenInference with 5+ attributes per span vs their 2.3
|
@@ -203,18 +206,30 @@ def common_llamaindex_logic(scope, environment, application_name,
|
|
203
206
|
scope._end_time = time.time()
|
204
207
|
|
205
208
|
# Set common framework span attributes using centralized helper
|
206
|
-
common_framework_span_attributes(
|
207
|
-
scope
|
208
|
-
|
209
|
+
common_framework_span_attributes(
|
210
|
+
scope,
|
211
|
+
SemanticConvention.GEN_AI_SYSTEM_LLAMAINDEX,
|
212
|
+
scope._server_address,
|
213
|
+
scope._server_port,
|
214
|
+
environment,
|
215
|
+
application_name,
|
216
|
+
version,
|
217
|
+
endpoint,
|
218
|
+
instance,
|
219
|
+
)
|
209
220
|
|
210
221
|
# === CORE SEMANTIC ATTRIBUTES ===
|
211
|
-
operation_type = OPERATION_MAP.get(
|
222
|
+
operation_type = OPERATION_MAP.get(
|
223
|
+
endpoint, SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK
|
224
|
+
)
|
212
225
|
scope._span.set_attribute(SemanticConvention.GEN_AI_OPERATION, operation_type)
|
213
226
|
|
214
227
|
# === PERFORMANCE INTELLIGENCE ===
|
215
228
|
performance = extract_performance_metrics(scope)
|
216
229
|
scope._span.set_attribute("gen_ai.operation.duration_ms", performance["latency_ms"])
|
217
|
-
scope._span.set_attribute(
|
230
|
+
scope._span.set_attribute(
|
231
|
+
"gen_ai.operation.performance_tier", performance["performance_tier"]
|
232
|
+
)
|
218
233
|
scope._span.set_attribute("gen_ai.operation.is_fast", performance["is_fast"])
|
219
234
|
|
220
235
|
# === BUSINESS INTELLIGENCE ===
|
@@ -229,115 +244,179 @@ def common_llamaindex_logic(scope, environment, application_name,
|
|
229
244
|
documents_count = scope._kwargs.get("documents", [])
|
230
245
|
if documents_count:
|
231
246
|
doc_count = object_count(documents_count)
|
232
|
-
scope._span.set_attribute(
|
247
|
+
scope._span.set_attribute(
|
248
|
+
SemanticConvention.GEN_AI_FRAMEWORK_DOCUMENTS_COUNT, doc_count
|
249
|
+
)
|
233
250
|
|
234
251
|
# Document source analysis
|
235
252
|
document_sources = []
|
236
253
|
total_content_length = 0
|
237
254
|
unique_authors = set()
|
238
255
|
|
239
|
-
for doc in (
|
240
|
-
if hasattr(
|
241
|
-
|
242
|
-
|
256
|
+
for doc in (
|
257
|
+
documents_count[:10] if hasattr(documents_count, "__iter__") else []
|
258
|
+
):
|
259
|
+
if hasattr(doc, "metadata"):
|
260
|
+
source = doc.metadata.get("file_path", "unknown")
|
261
|
+
author = doc.metadata.get("author", "unknown")
|
243
262
|
document_sources.append(source)
|
244
263
|
unique_authors.add(author)
|
245
264
|
|
246
|
-
if hasattr(doc,
|
265
|
+
if hasattr(doc, "text"):
|
247
266
|
total_content_length += len(doc.text)
|
248
267
|
|
249
|
-
scope._span.set_attribute(
|
250
|
-
|
251
|
-
|
252
|
-
scope._span.set_attribute(
|
253
|
-
|
254
|
-
|
268
|
+
scope._span.set_attribute(
|
269
|
+
"gen_ai.index.document_sources", str(document_sources[:5])
|
270
|
+
)
|
271
|
+
scope._span.set_attribute(
|
272
|
+
"gen_ai.index.total_content_length", total_content_length
|
273
|
+
)
|
274
|
+
scope._span.set_attribute(
|
275
|
+
"gen_ai.index.unique_authors", len(unique_authors)
|
276
|
+
)
|
277
|
+
scope._span.set_attribute(
|
278
|
+
"gen_ai.index.avg_document_size",
|
279
|
+
total_content_length // max(doc_count, 1),
|
280
|
+
)
|
281
|
+
|
282
|
+
elif endpoint in (
|
283
|
+
"framework.query_engine.query",
|
284
|
+
"framework.query_engine.query_async",
|
285
|
+
):
|
255
286
|
# Enhanced query processing telemetry
|
256
|
-
query_text =
|
287
|
+
query_text = (
|
288
|
+
scope._args[0] if scope._args else scope._kwargs.get("query", "unknown")
|
289
|
+
)
|
257
290
|
if capture_message_content:
|
258
|
-
scope._span.set_attribute(
|
291
|
+
scope._span.set_attribute(
|
292
|
+
SemanticConvention.GEN_AI_CONTENT_PROMPT, str(query_text)
|
293
|
+
)
|
259
294
|
|
260
295
|
# Query analysis
|
261
296
|
query_length = len(str(query_text))
|
262
297
|
query_words = len(str(query_text).split())
|
263
298
|
scope._span.set_attribute("gen_ai.query.length", query_length)
|
264
299
|
scope._span.set_attribute("gen_ai.query.word_count", query_words)
|
265
|
-
scope._span.set_attribute(
|
300
|
+
scope._span.set_attribute(
|
301
|
+
SemanticConvention.GEN_AI_FRAMEWORK_QUERY_TYPE, "query_engine"
|
302
|
+
)
|
266
303
|
|
267
304
|
# Process index operations using helper function
|
268
305
|
_process_index_operations(scope, endpoint, capture_message_content)
|
269
306
|
|
270
|
-
elif endpoint in (
|
307
|
+
elif endpoint in (
|
308
|
+
"framework.retriever.retrieve",
|
309
|
+
"framework.retriever.retrieve_async",
|
310
|
+
):
|
271
311
|
# Enhanced retrieval telemetry
|
272
|
-
query_text =
|
312
|
+
query_text = (
|
313
|
+
scope._args[0] if scope._args else scope._kwargs.get("query", "unknown")
|
314
|
+
)
|
273
315
|
if capture_message_content:
|
274
|
-
scope._span.set_attribute(
|
316
|
+
scope._span.set_attribute(
|
317
|
+
SemanticConvention.GEN_AI_CONTENT_PROMPT, str(query_text)
|
318
|
+
)
|
275
319
|
|
276
320
|
# Retrieval configuration analysis
|
277
321
|
similarity_top_k = scope._kwargs.get("similarity_top_k", 2)
|
278
322
|
scope._span.set_attribute("gen_ai.retrieval.top_k", similarity_top_k)
|
279
323
|
scope._span.set_attribute("gen_ai.retrieval.strategy", "vector_similarity")
|
280
|
-
scope._span.set_attribute(
|
324
|
+
scope._span.set_attribute(
|
325
|
+
SemanticConvention.GEN_AI_FRAMEWORK_QUERY_TYPE, "retriever"
|
326
|
+
)
|
281
327
|
|
282
328
|
elif endpoint == "framework.document.split":
|
283
329
|
# Enhanced document splitting telemetry
|
284
330
|
show_progress = scope._kwargs.get("show_progress", False)
|
285
|
-
scope._span.set_attribute(
|
331
|
+
scope._span.set_attribute(
|
332
|
+
SemanticConvention.GEN_AI_FRAMEWORK_SHOW_PROGRESS, show_progress
|
333
|
+
)
|
286
334
|
|
287
335
|
# Extract enhanced node creation info
|
288
|
-
if scope._response and hasattr(scope._response,
|
336
|
+
if scope._response and hasattr(scope._response, "__len__"):
|
289
337
|
nodes_created = len(scope._response)
|
290
|
-
scope._span.set_attribute(
|
338
|
+
scope._span.set_attribute(
|
339
|
+
SemanticConvention.GEN_AI_FRAMEWORK_NODES_CREATED, nodes_created
|
340
|
+
)
|
291
341
|
|
292
342
|
# Extract comprehensive chunk configuration
|
293
|
-
chunk_size = getattr(instance,
|
294
|
-
chunk_overlap = getattr(instance,
|
295
|
-
separator = getattr(instance,
|
296
|
-
|
297
|
-
scope._span.set_attribute(
|
298
|
-
|
343
|
+
chunk_size = getattr(instance, "chunk_size", 1024) if instance else 1024
|
344
|
+
chunk_overlap = getattr(instance, "chunk_overlap", 200) if instance else 200
|
345
|
+
separator = getattr(instance, "separator", "\\n\\n") if instance else "\\n\\n"
|
346
|
+
|
347
|
+
scope._span.set_attribute(
|
348
|
+
SemanticConvention.GEN_AI_FRAMEWORK_CHUNK_SIZE, chunk_size
|
349
|
+
)
|
350
|
+
scope._span.set_attribute(
|
351
|
+
SemanticConvention.GEN_AI_FRAMEWORK_CHUNK_OVERLAP, chunk_overlap
|
352
|
+
)
|
299
353
|
scope._span.set_attribute("gen_ai.splitter.separator", separator)
|
300
|
-
scope._span.set_attribute(
|
354
|
+
scope._span.set_attribute(
|
355
|
+
"gen_ai.splitter.efficiency", nodes_created / max(1, chunk_size // 100)
|
356
|
+
)
|
301
357
|
|
302
358
|
# === COMPONENT-LEVEL ENHANCED PROCESSING ===
|
303
359
|
|
304
360
|
elif endpoint.startswith("component.text_splitter"):
|
305
361
|
if endpoint == "component.text_splitter.split":
|
306
|
-
text_input =
|
362
|
+
text_input = (
|
363
|
+
scope._args[0] if scope._args else scope._kwargs.get("text", "")
|
364
|
+
)
|
307
365
|
text_metrics = extract_content_metrics(text_input)
|
308
|
-
scope._span.set_attribute(
|
309
|
-
|
310
|
-
|
311
|
-
|
366
|
+
scope._span.set_attribute(
|
367
|
+
"gen_ai.component.input_length", text_metrics.get("char_count", 0)
|
368
|
+
)
|
369
|
+
scope._span.set_attribute(
|
370
|
+
"gen_ai.component.input_complexity",
|
371
|
+
text_metrics.get("complexity_score", 0),
|
372
|
+
)
|
373
|
+
|
374
|
+
if scope._response and hasattr(scope._response, "__len__"):
|
312
375
|
chunks_created = len(scope._response)
|
313
|
-
scope._span.set_attribute(
|
314
|
-
|
315
|
-
|
376
|
+
scope._span.set_attribute(
|
377
|
+
"gen_ai.component.chunks_created", chunks_created
|
378
|
+
)
|
379
|
+
scope._span.set_attribute(
|
380
|
+
"gen_ai.component.compression_ratio",
|
381
|
+
chunks_created / max(1, text_metrics.get("word_count", 1) // 100),
|
382
|
+
)
|
316
383
|
|
317
384
|
elif endpoint.startswith("component.embedding"):
|
318
385
|
if endpoint == "component.embedding.encode":
|
319
386
|
texts = scope._args[0] if scope._args else scope._kwargs.get("texts", [])
|
320
387
|
embedding_count = object_count(texts)
|
321
|
-
scope._span.set_attribute(
|
388
|
+
scope._span.set_attribute(
|
389
|
+
"gen_ai.component.embedding_count", embedding_count
|
390
|
+
)
|
322
391
|
|
323
|
-
if embedding_count > 0 and hasattr(texts,
|
392
|
+
if embedding_count > 0 and hasattr(texts, "__iter__"):
|
324
393
|
total_chars = sum(len(str(text)) for text in texts)
|
325
394
|
scope._span.set_attribute("gen_ai.component.total_chars", total_chars)
|
326
|
-
scope._span.set_attribute(
|
395
|
+
scope._span.set_attribute(
|
396
|
+
"gen_ai.component.avg_text_length", total_chars // embedding_count
|
397
|
+
)
|
327
398
|
|
328
399
|
elif endpoint.startswith("component.retrieval"):
|
329
400
|
if endpoint == "component.retrieval.retrieve_nodes":
|
330
401
|
# Enhanced retrieval component analysis
|
331
|
-
query_embedding =
|
332
|
-
|
333
|
-
|
402
|
+
query_embedding = (
|
403
|
+
scope._args[0] if scope._args else scope._kwargs.get("query_embedding")
|
404
|
+
)
|
405
|
+
if query_embedding and hasattr(query_embedding, "__len__"):
|
406
|
+
scope._span.set_attribute(
|
407
|
+
"gen_ai.component.embedding_dimension", len(query_embedding)
|
408
|
+
)
|
334
409
|
|
335
410
|
similarity_threshold = scope._kwargs.get("similarity_threshold", 0.0)
|
336
|
-
scope._span.set_attribute(
|
411
|
+
scope._span.set_attribute(
|
412
|
+
"gen_ai.component.similarity_threshold", similarity_threshold
|
413
|
+
)
|
337
414
|
|
338
415
|
# === UNIVERSAL ATTRIBUTES ===
|
339
|
-
scope._span.set_attribute(
|
340
|
-
|
416
|
+
scope._span.set_attribute(
|
417
|
+
SemanticConvention.GEN_AI_CLIENT_OPERATION_DURATION,
|
418
|
+
scope._end_time - scope._start_time,
|
419
|
+
)
|
341
420
|
scope._span.set_attribute("gen_ai.operation.endpoint", endpoint)
|
342
421
|
scope._span.set_attribute("gen_ai.framework.version", version)
|
343
422
|
scope._span.set_attribute("gen_ai.operation.success", True)
|
@@ -346,14 +425,37 @@ def common_llamaindex_logic(scope, environment, application_name,
|
|
346
425
|
|
347
426
|
# Record enhanced metrics
|
348
427
|
if not disable_metrics:
|
349
|
-
record_framework_metrics(
|
350
|
-
|
351
|
-
scope.
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
428
|
+
record_framework_metrics(
|
429
|
+
metrics,
|
430
|
+
scope._operation_type,
|
431
|
+
SemanticConvention.GEN_AI_SYSTEM_LLAMAINDEX,
|
432
|
+
scope._server_address,
|
433
|
+
scope._server_port,
|
434
|
+
environment,
|
435
|
+
application_name,
|
436
|
+
scope._start_time,
|
437
|
+
scope._end_time,
|
438
|
+
)
|
439
|
+
|
440
|
+
|
441
|
+
def process_llamaindex_response(
|
442
|
+
response,
|
443
|
+
operation_type,
|
444
|
+
server_address,
|
445
|
+
server_port,
|
446
|
+
environment,
|
447
|
+
application_name,
|
448
|
+
metrics,
|
449
|
+
start_time,
|
450
|
+
span,
|
451
|
+
capture_message_content,
|
452
|
+
disable_metrics,
|
453
|
+
version,
|
454
|
+
instance=None,
|
455
|
+
args=None,
|
456
|
+
endpoint=None,
|
457
|
+
**kwargs,
|
458
|
+
):
|
357
459
|
"""
|
358
460
|
DOMINANCE EDITION: Process LlamaIndex response with superior observability
|
359
461
|
"""
|
@@ -370,16 +472,23 @@ def process_llamaindex_response(response, operation_type, server_address, server
|
|
370
472
|
|
371
473
|
# Process with enhanced telemetry
|
372
474
|
common_llamaindex_logic(
|
373
|
-
scope,
|
374
|
-
|
375
|
-
|
475
|
+
scope,
|
476
|
+
environment,
|
477
|
+
application_name,
|
478
|
+
metrics,
|
479
|
+
capture_message_content,
|
480
|
+
disable_metrics,
|
481
|
+
version,
|
482
|
+
instance,
|
483
|
+
endpoint,
|
376
484
|
)
|
377
485
|
|
378
486
|
return response
|
379
487
|
|
488
|
+
|
380
489
|
def _process_index_operations(scope, endpoint, capture_message_content):
|
381
490
|
"""Helper function to process index operations and reduce nesting"""
|
382
|
-
if not hasattr(scope,
|
491
|
+
if not hasattr(scope, "_result") or not scope._result:
|
383
492
|
return
|
384
493
|
|
385
494
|
try:
|
@@ -405,8 +514,12 @@ def _process_index_operations(scope, endpoint, capture_message_content):
|
|
405
514
|
if hasattr(node, "text"):
|
406
515
|
total_content_length += len(str(node.text))
|
407
516
|
|
408
|
-
scope._span.set_attribute(
|
517
|
+
scope._span.set_attribute(
|
518
|
+
"gen_ai.index.total_content_length", total_content_length
|
519
|
+
)
|
409
520
|
scope._span.set_attribute("gen_ai.index.unique_authors", len(unique_authors))
|
410
|
-
scope._span.set_attribute(
|
521
|
+
scope._span.set_attribute(
|
522
|
+
"gen_ai.index.avg_document_size", total_content_length // max(doc_count, 1)
|
523
|
+
)
|
411
524
|
except Exception:
|
412
525
|
pass # Don't fail on metadata extraction
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# pylint: disable=useless-return, bad-staticmethod-argument, disable=duplicate-code
|
2
2
|
"""Initializer of Auto Instrumentation of mem0 Functions"""
|
3
|
+
|
3
4
|
from typing import Collection
|
4
5
|
import importlib.metadata
|
5
6
|
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
@@ -48,6 +49,7 @@ WRAPPED_METHODS = [
|
|
48
49
|
},
|
49
50
|
]
|
50
51
|
|
52
|
+
|
51
53
|
class Mem0Instrumentor(BaseInstrumentor):
|
52
54
|
"""An instrumentor for mem0's client library."""
|
53
55
|
|
@@ -70,8 +72,15 @@ class Mem0Instrumentor(BaseInstrumentor):
|
|
70
72
|
wrap_function_wrapper(
|
71
73
|
wrap_package,
|
72
74
|
wrap_object,
|
73
|
-
wrapper(
|
74
|
-
|
75
|
+
wrapper(
|
76
|
+
gen_ai_endpoint,
|
77
|
+
version,
|
78
|
+
environment,
|
79
|
+
application_name,
|
80
|
+
tracer,
|
81
|
+
pricing_info,
|
82
|
+
capture_message_content,
|
83
|
+
),
|
75
84
|
)
|
76
85
|
|
77
86
|
@staticmethod
|