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.
Files changed (168) hide show
  1. openlit/__helpers.py +235 -86
  2. openlit/__init__.py +16 -13
  3. openlit/_instrumentors.py +2 -1
  4. openlit/evals/all.py +50 -21
  5. openlit/evals/bias_detection.py +47 -20
  6. openlit/evals/hallucination.py +53 -22
  7. openlit/evals/toxicity.py +50 -21
  8. openlit/evals/utils.py +54 -30
  9. openlit/guard/all.py +61 -19
  10. openlit/guard/prompt_injection.py +34 -14
  11. openlit/guard/restrict_topic.py +46 -15
  12. openlit/guard/sensitive_topic.py +34 -14
  13. openlit/guard/utils.py +58 -22
  14. openlit/instrumentation/ag2/__init__.py +24 -8
  15. openlit/instrumentation/ag2/ag2.py +34 -13
  16. openlit/instrumentation/ag2/async_ag2.py +34 -13
  17. openlit/instrumentation/ag2/utils.py +133 -30
  18. openlit/instrumentation/ai21/__init__.py +43 -14
  19. openlit/instrumentation/ai21/ai21.py +47 -21
  20. openlit/instrumentation/ai21/async_ai21.py +47 -21
  21. openlit/instrumentation/ai21/utils.py +299 -78
  22. openlit/instrumentation/anthropic/__init__.py +21 -4
  23. openlit/instrumentation/anthropic/anthropic.py +28 -17
  24. openlit/instrumentation/anthropic/async_anthropic.py +28 -17
  25. openlit/instrumentation/anthropic/utils.py +145 -35
  26. openlit/instrumentation/assemblyai/__init__.py +11 -2
  27. openlit/instrumentation/assemblyai/assemblyai.py +15 -4
  28. openlit/instrumentation/assemblyai/utils.py +120 -25
  29. openlit/instrumentation/astra/__init__.py +43 -10
  30. openlit/instrumentation/astra/astra.py +28 -5
  31. openlit/instrumentation/astra/async_astra.py +28 -5
  32. openlit/instrumentation/astra/utils.py +151 -55
  33. openlit/instrumentation/azure_ai_inference/__init__.py +43 -10
  34. openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py +53 -21
  35. openlit/instrumentation/azure_ai_inference/azure_ai_inference.py +53 -21
  36. openlit/instrumentation/azure_ai_inference/utils.py +307 -83
  37. openlit/instrumentation/bedrock/__init__.py +21 -4
  38. openlit/instrumentation/bedrock/bedrock.py +63 -25
  39. openlit/instrumentation/bedrock/utils.py +139 -30
  40. openlit/instrumentation/chroma/__init__.py +89 -16
  41. openlit/instrumentation/chroma/chroma.py +28 -6
  42. openlit/instrumentation/chroma/utils.py +167 -51
  43. openlit/instrumentation/cohere/__init__.py +63 -18
  44. openlit/instrumentation/cohere/async_cohere.py +63 -24
  45. openlit/instrumentation/cohere/cohere.py +63 -24
  46. openlit/instrumentation/cohere/utils.py +286 -73
  47. openlit/instrumentation/controlflow/__init__.py +35 -9
  48. openlit/instrumentation/controlflow/controlflow.py +66 -33
  49. openlit/instrumentation/crawl4ai/__init__.py +25 -10
  50. openlit/instrumentation/crawl4ai/async_crawl4ai.py +78 -31
  51. openlit/instrumentation/crawl4ai/crawl4ai.py +78 -31
  52. openlit/instrumentation/crewai/__init__.py +40 -15
  53. openlit/instrumentation/crewai/async_crewai.py +32 -7
  54. openlit/instrumentation/crewai/crewai.py +32 -7
  55. openlit/instrumentation/crewai/utils.py +159 -56
  56. openlit/instrumentation/dynamiq/__init__.py +46 -12
  57. openlit/instrumentation/dynamiq/dynamiq.py +74 -33
  58. openlit/instrumentation/elevenlabs/__init__.py +23 -4
  59. openlit/instrumentation/elevenlabs/async_elevenlabs.py +16 -4
  60. openlit/instrumentation/elevenlabs/elevenlabs.py +16 -4
  61. openlit/instrumentation/elevenlabs/utils.py +128 -25
  62. openlit/instrumentation/embedchain/__init__.py +11 -2
  63. openlit/instrumentation/embedchain/embedchain.py +68 -35
  64. openlit/instrumentation/firecrawl/__init__.py +24 -7
  65. openlit/instrumentation/firecrawl/firecrawl.py +46 -20
  66. openlit/instrumentation/google_ai_studio/__init__.py +45 -10
  67. openlit/instrumentation/google_ai_studio/async_google_ai_studio.py +67 -44
  68. openlit/instrumentation/google_ai_studio/google_ai_studio.py +67 -44
  69. openlit/instrumentation/google_ai_studio/utils.py +180 -67
  70. openlit/instrumentation/gpt4all/__init__.py +22 -7
  71. openlit/instrumentation/gpt4all/gpt4all.py +67 -29
  72. openlit/instrumentation/gpt4all/utils.py +285 -61
  73. openlit/instrumentation/gpu/__init__.py +128 -47
  74. openlit/instrumentation/groq/__init__.py +21 -4
  75. openlit/instrumentation/groq/async_groq.py +33 -21
  76. openlit/instrumentation/groq/groq.py +33 -21
  77. openlit/instrumentation/groq/utils.py +192 -55
  78. openlit/instrumentation/haystack/__init__.py +70 -24
  79. openlit/instrumentation/haystack/async_haystack.py +28 -6
  80. openlit/instrumentation/haystack/haystack.py +28 -6
  81. openlit/instrumentation/haystack/utils.py +196 -74
  82. openlit/instrumentation/julep/__init__.py +69 -19
  83. openlit/instrumentation/julep/async_julep.py +53 -27
  84. openlit/instrumentation/julep/julep.py +53 -28
  85. openlit/instrumentation/langchain/__init__.py +74 -63
  86. openlit/instrumentation/langchain/callback_handler.py +1100 -0
  87. openlit/instrumentation/langchain_community/__init__.py +13 -2
  88. openlit/instrumentation/langchain_community/async_langchain_community.py +23 -5
  89. openlit/instrumentation/langchain_community/langchain_community.py +23 -5
  90. openlit/instrumentation/langchain_community/utils.py +35 -9
  91. openlit/instrumentation/letta/__init__.py +68 -15
  92. openlit/instrumentation/letta/letta.py +99 -54
  93. openlit/instrumentation/litellm/__init__.py +43 -14
  94. openlit/instrumentation/litellm/async_litellm.py +51 -26
  95. openlit/instrumentation/litellm/litellm.py +51 -26
  96. openlit/instrumentation/litellm/utils.py +304 -102
  97. openlit/instrumentation/llamaindex/__init__.py +267 -90
  98. openlit/instrumentation/llamaindex/async_llamaindex.py +28 -6
  99. openlit/instrumentation/llamaindex/llamaindex.py +28 -6
  100. openlit/instrumentation/llamaindex/utils.py +204 -91
  101. openlit/instrumentation/mem0/__init__.py +11 -2
  102. openlit/instrumentation/mem0/mem0.py +50 -29
  103. openlit/instrumentation/milvus/__init__.py +10 -2
  104. openlit/instrumentation/milvus/milvus.py +31 -6
  105. openlit/instrumentation/milvus/utils.py +166 -67
  106. openlit/instrumentation/mistral/__init__.py +63 -18
  107. openlit/instrumentation/mistral/async_mistral.py +63 -24
  108. openlit/instrumentation/mistral/mistral.py +63 -24
  109. openlit/instrumentation/mistral/utils.py +277 -69
  110. openlit/instrumentation/multion/__init__.py +69 -19
  111. openlit/instrumentation/multion/async_multion.py +57 -26
  112. openlit/instrumentation/multion/multion.py +57 -26
  113. openlit/instrumentation/ollama/__init__.py +39 -18
  114. openlit/instrumentation/ollama/async_ollama.py +57 -26
  115. openlit/instrumentation/ollama/ollama.py +57 -26
  116. openlit/instrumentation/ollama/utils.py +226 -50
  117. openlit/instrumentation/openai/__init__.py +156 -32
  118. openlit/instrumentation/openai/async_openai.py +147 -67
  119. openlit/instrumentation/openai/openai.py +150 -67
  120. openlit/instrumentation/openai/utils.py +657 -185
  121. openlit/instrumentation/openai_agents/__init__.py +5 -1
  122. openlit/instrumentation/openai_agents/processor.py +110 -90
  123. openlit/instrumentation/phidata/__init__.py +13 -5
  124. openlit/instrumentation/phidata/phidata.py +67 -32
  125. openlit/instrumentation/pinecone/__init__.py +48 -9
  126. openlit/instrumentation/pinecone/async_pinecone.py +27 -5
  127. openlit/instrumentation/pinecone/pinecone.py +27 -5
  128. openlit/instrumentation/pinecone/utils.py +153 -47
  129. openlit/instrumentation/premai/__init__.py +22 -7
  130. openlit/instrumentation/premai/premai.py +51 -26
  131. openlit/instrumentation/premai/utils.py +246 -59
  132. openlit/instrumentation/pydantic_ai/__init__.py +49 -22
  133. openlit/instrumentation/pydantic_ai/pydantic_ai.py +69 -16
  134. openlit/instrumentation/pydantic_ai/utils.py +89 -24
  135. openlit/instrumentation/qdrant/__init__.py +19 -4
  136. openlit/instrumentation/qdrant/async_qdrant.py +33 -7
  137. openlit/instrumentation/qdrant/qdrant.py +33 -7
  138. openlit/instrumentation/qdrant/utils.py +228 -93
  139. openlit/instrumentation/reka/__init__.py +23 -10
  140. openlit/instrumentation/reka/async_reka.py +17 -11
  141. openlit/instrumentation/reka/reka.py +17 -11
  142. openlit/instrumentation/reka/utils.py +138 -36
  143. openlit/instrumentation/together/__init__.py +44 -12
  144. openlit/instrumentation/together/async_together.py +50 -27
  145. openlit/instrumentation/together/together.py +50 -27
  146. openlit/instrumentation/together/utils.py +301 -71
  147. openlit/instrumentation/transformers/__init__.py +2 -1
  148. openlit/instrumentation/transformers/transformers.py +13 -3
  149. openlit/instrumentation/transformers/utils.py +139 -36
  150. openlit/instrumentation/vertexai/__init__.py +81 -16
  151. openlit/instrumentation/vertexai/async_vertexai.py +33 -15
  152. openlit/instrumentation/vertexai/utils.py +123 -27
  153. openlit/instrumentation/vertexai/vertexai.py +33 -15
  154. openlit/instrumentation/vllm/__init__.py +12 -5
  155. openlit/instrumentation/vllm/utils.py +121 -31
  156. openlit/instrumentation/vllm/vllm.py +16 -10
  157. openlit/otel/events.py +35 -10
  158. openlit/otel/metrics.py +32 -24
  159. openlit/otel/tracing.py +24 -9
  160. openlit/semcov/__init__.py +72 -6
  161. {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/METADATA +2 -1
  162. openlit-1.34.31.dist-info/RECORD +166 -0
  163. openlit/instrumentation/langchain/async_langchain.py +0 -102
  164. openlit/instrumentation/langchain/langchain.py +0 -102
  165. openlit/instrumentation/langchain/utils.py +0 -252
  166. openlit-1.34.30.dist-info/RECORD +0 -168
  167. {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/LICENSE +0 -0
  168. {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, '_client'):
81
+ if hasattr(instance, "_client"):
93
82
  client = instance._client
94
- if hasattr(client, 'base_url'):
83
+ if hasattr(client, "base_url"):
95
84
  base_url = str(client.base_url)
96
- if '://' in base_url:
97
- parts = base_url.split('://', 1)[1].split('/', 1)[0]
98
- if ':' in parts:
99
- host, port = parts.rsplit(':', 1)
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, '__len__'):
102
+ if hasattr(obj, "__len__"):
113
103
  return len(obj)
114
- elif hasattr(obj, '__iter__'):
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
- def common_llamaindex_logic(scope, environment, application_name,
197
- metrics, capture_message_content, disable_metrics, version,
198
- instance=None, endpoint=None, **kwargs):
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(scope, SemanticConvention.GEN_AI_SYSTEM_LLAMAINDEX,
207
- scope._server_address, scope._server_port, environment, application_name,
208
- version, endpoint, instance)
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(endpoint, SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK)
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("gen_ai.operation.performance_tier", performance["performance_tier"])
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(SemanticConvention.GEN_AI_FRAMEWORK_DOCUMENTS_COUNT, doc_count)
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 (documents_count[:10] if hasattr(documents_count, '__iter__') else []):
240
- if hasattr(doc, 'metadata'):
241
- source = doc.metadata.get('file_path', 'unknown')
242
- author = doc.metadata.get('author', 'unknown')
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, 'text'):
265
+ if hasattr(doc, "text"):
247
266
  total_content_length += len(doc.text)
248
267
 
249
- scope._span.set_attribute("gen_ai.index.document_sources", str(document_sources[:5]))
250
- scope._span.set_attribute("gen_ai.index.total_content_length", total_content_length)
251
- scope._span.set_attribute("gen_ai.index.unique_authors", len(unique_authors))
252
- scope._span.set_attribute("gen_ai.index.avg_document_size", total_content_length // max(doc_count, 1))
253
-
254
- elif endpoint in ("framework.query_engine.query", "framework.query_engine.query_async"):
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 = scope._args[0] if scope._args else scope._kwargs.get("query", "unknown")
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(SemanticConvention.GEN_AI_CONTENT_PROMPT, str(query_text))
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(SemanticConvention.GEN_AI_FRAMEWORK_QUERY_TYPE, "query_engine")
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 ("framework.retriever.retrieve", "framework.retriever.retrieve_async"):
307
+ elif endpoint in (
308
+ "framework.retriever.retrieve",
309
+ "framework.retriever.retrieve_async",
310
+ ):
271
311
  # Enhanced retrieval telemetry
272
- query_text = scope._args[0] if scope._args else scope._kwargs.get("query", "unknown")
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(SemanticConvention.GEN_AI_CONTENT_PROMPT, str(query_text))
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(SemanticConvention.GEN_AI_FRAMEWORK_QUERY_TYPE, "retriever")
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(SemanticConvention.GEN_AI_FRAMEWORK_SHOW_PROGRESS, show_progress)
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, '__len__'):
336
+ if scope._response and hasattr(scope._response, "__len__"):
289
337
  nodes_created = len(scope._response)
290
- scope._span.set_attribute(SemanticConvention.GEN_AI_FRAMEWORK_NODES_CREATED, nodes_created)
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, 'chunk_size', 1024) if instance else 1024
294
- chunk_overlap = getattr(instance, 'chunk_overlap', 200) if instance else 200
295
- separator = getattr(instance, 'separator', '\\n\\n') if instance else '\\n\\n'
296
-
297
- scope._span.set_attribute(SemanticConvention.GEN_AI_FRAMEWORK_CHUNK_SIZE, chunk_size)
298
- scope._span.set_attribute(SemanticConvention.GEN_AI_FRAMEWORK_CHUNK_OVERLAP, chunk_overlap)
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("gen_ai.splitter.efficiency", nodes_created / max(1, chunk_size // 100))
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 = scope._args[0] if scope._args else scope._kwargs.get("text", "")
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("gen_ai.component.input_length", text_metrics.get("char_count", 0))
309
- scope._span.set_attribute("gen_ai.component.input_complexity", text_metrics.get("complexity_score", 0))
310
-
311
- if scope._response and hasattr(scope._response, '__len__'):
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("gen_ai.component.chunks_created", chunks_created)
314
- scope._span.set_attribute("gen_ai.component.compression_ratio",
315
- chunks_created / max(1, text_metrics.get("word_count", 1) // 100))
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("gen_ai.component.embedding_count", embedding_count)
388
+ scope._span.set_attribute(
389
+ "gen_ai.component.embedding_count", embedding_count
390
+ )
322
391
 
323
- if embedding_count > 0 and hasattr(texts, '__iter__'):
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("gen_ai.component.avg_text_length", total_chars // embedding_count)
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 = scope._args[0] if scope._args else scope._kwargs.get("query_embedding")
332
- if query_embedding and hasattr(query_embedding, '__len__'):
333
- scope._span.set_attribute("gen_ai.component.embedding_dimension", len(query_embedding))
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("gen_ai.component.similarity_threshold", similarity_threshold)
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(SemanticConvention.GEN_AI_CLIENT_OPERATION_DURATION,
340
- scope._end_time - scope._start_time)
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(metrics, scope._operation_type, SemanticConvention.GEN_AI_SYSTEM_LLAMAINDEX,
350
- scope._server_address, scope._server_port, environment, application_name,
351
- scope._start_time, scope._end_time)
352
-
353
- def process_llamaindex_response(response, operation_type, server_address, server_port,
354
- environment, application_name, metrics, start_time, span,
355
- capture_message_content, disable_metrics, version, instance=None,
356
- args=None, endpoint=None, **kwargs):
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, environment, application_name, metrics,
374
- capture_message_content, disable_metrics, version,
375
- instance, endpoint
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, '_result') or not scope._result:
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("gen_ai.index.total_content_length", total_content_length)
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("gen_ai.index.avg_document_size", total_content_length // max(doc_count, 1))
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(gen_ai_endpoint, version, environment, application_name,
74
- tracer, pricing_info, capture_message_content),
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