openlit 1.34.30__py3-none-any.whl → 1.34.32__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 +19 -14
  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 +113 -6
  15. openlit/instrumentation/ag2/ag2.py +459 -17
  16. openlit/instrumentation/ag2/async_ag2.py +459 -17
  17. openlit/instrumentation/ag2/utils.py +475 -31
  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 +82 -6
  161. {openlit-1.34.30.dist-info → openlit-1.34.32.dist-info}/METADATA +2 -1
  162. openlit-1.34.32.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.32.dist-info}/LICENSE +0 -0
  168. {openlit-1.34.30.dist-info → openlit-1.34.32.dist-info}/WHEEL +0 -0
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Groq OpenTelemetry instrumentation utility functions
3
3
  """
4
+
4
5
  import time
5
6
 
6
7
  from opentelemetry.trace import Status, StatusCode
@@ -15,6 +16,7 @@ from openlit.__helpers import (
15
16
  )
16
17
  from openlit.semcov import SemanticConvention
17
18
 
19
+
18
20
  def format_content(messages):
19
21
  """
20
22
  Process a list of messages to extract content.
@@ -27,8 +29,9 @@ def format_content(messages):
27
29
 
28
30
  if isinstance(content, list):
29
31
  content_str = ", ".join(
30
- f'{item["type"]}: {item["text"] if "text" in item else item["image_url"]}'
31
- if "type" in item else f'text: {item["text"]}'
32
+ f"{item['type']}: {item['text'] if 'text' in item else item['image_url']}"
33
+ if "type" in item
34
+ else f"text: {item['text']}"
32
35
  for item in content
33
36
  )
34
37
  formatted_messages.append(f"{role}: {content_str}")
@@ -37,6 +40,7 @@ def format_content(messages):
37
40
 
38
41
  return "\n".join(formatted_messages)
39
42
 
43
+
40
44
  def process_chunk(scope, chunk):
41
45
  """
42
46
  Process a chunk of response data and update state.
@@ -53,27 +57,41 @@ def process_chunk(scope, chunk):
53
57
  chunked = response_as_dict(chunk)
54
58
 
55
59
  # Collect message IDs and aggregated response from events
56
- if (len(chunked.get("choices", [])) > 0 and
57
- "delta" in chunked.get("choices")[0] and
58
- "content" in chunked.get("choices")[0].get("delta", {})):
59
-
60
+ if (
61
+ len(chunked.get("choices", [])) > 0
62
+ and "delta" in chunked.get("choices")[0]
63
+ and "content" in chunked.get("choices")[0].get("delta", {})
64
+ ):
60
65
  content = chunked.get("choices")[0].get("delta").get("content")
61
66
  if content:
62
67
  scope._llmresponse += content
63
68
 
64
- if chunked.get('x_groq') is not None:
65
- if chunked.get('x_groq').get('usage') is not None:
66
- scope._input_tokens = chunked.get('x_groq').get('usage').get('prompt_tokens')
67
- scope._output_tokens = chunked.get('x_groq').get('usage').get('completion_tokens')
68
- scope._response_id = chunked.get('x_groq').get('id')
69
- scope._response_model = chunked.get('x_groq').get('model')
70
- scope._finish_reason = chunked.get('choices', [{}])[0].get('finish_reason')
71
- scope._system_fingerprint = chunked.get('x_groq').get('system_fingerprint')
69
+ if chunked.get("x_groq") is not None:
70
+ if chunked.get("x_groq").get("usage") is not None:
71
+ scope._input_tokens = (
72
+ chunked.get("x_groq").get("usage").get("prompt_tokens")
73
+ )
74
+ scope._output_tokens = (
75
+ chunked.get("x_groq").get("usage").get("completion_tokens")
76
+ )
77
+ scope._response_id = chunked.get("x_groq").get("id")
78
+ scope._response_model = chunked.get("x_groq").get("model")
79
+ scope._finish_reason = chunked.get("choices", [{}])[0].get("finish_reason")
80
+ scope._system_fingerprint = chunked.get("x_groq").get("system_fingerprint")
72
81
  scope._end_time = time.time()
73
82
 
74
83
 
75
- def common_chat_logic(scope, pricing_info, environment, application_name, metrics,
76
- capture_message_content, disable_metrics, version, is_stream):
84
+ def common_chat_logic(
85
+ scope,
86
+ pricing_info,
87
+ environment,
88
+ application_name,
89
+ metrics,
90
+ capture_message_content,
91
+ disable_metrics,
92
+ version,
93
+ is_stream,
94
+ ):
77
95
  """
78
96
  Process chat request and generate Telemetry
79
97
  """
@@ -84,47 +102,107 @@ def common_chat_logic(scope, pricing_info, environment, application_name, metric
84
102
  prompt = format_content(scope._kwargs.get("messages", []))
85
103
  request_model = scope._kwargs.get("model", "mixtral-8x7b-32768")
86
104
 
87
- cost = get_chat_model_cost(request_model, pricing_info, scope._input_tokens, scope._output_tokens)
105
+ cost = get_chat_model_cost(
106
+ request_model, pricing_info, scope._input_tokens, scope._output_tokens
107
+ )
88
108
 
89
109
  # Common Span Attributes
90
- common_span_attributes(scope,
91
- SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_GROQ,
92
- scope._server_address, scope._server_port, request_model, scope._response_model,
93
- environment, application_name, is_stream, scope._tbt, scope._ttft, version)
110
+ common_span_attributes(
111
+ scope,
112
+ SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
113
+ SemanticConvention.GEN_AI_SYSTEM_GROQ,
114
+ scope._server_address,
115
+ scope._server_port,
116
+ request_model,
117
+ scope._response_model,
118
+ environment,
119
+ application_name,
120
+ is_stream,
121
+ scope._tbt,
122
+ scope._ttft,
123
+ version,
124
+ )
94
125
 
95
126
  # Span Attributes for Request parameters
96
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SEED, scope._kwargs.get("seed", ""))
97
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_FREQUENCY_PENALTY, scope._kwargs.get("frequency_penalty", 0.0))
98
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS, scope._kwargs.get("max_completion_tokens", -1))
99
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_PRESENCE_PENALTY, scope._kwargs.get("presence_penalty", 0.0))
100
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_STOP_SEQUENCES, scope._kwargs.get("stop", []))
101
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, scope._kwargs.get("temperature", 1.0))
102
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_P, scope._kwargs.get("top_p", 1.0))
103
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_USER, scope._kwargs.get("user", ""))
104
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SERVICE_TIER, scope._kwargs.get("service_tier", "on_demand"))
127
+ scope._span.set_attribute(
128
+ SemanticConvention.GEN_AI_REQUEST_SEED, scope._kwargs.get("seed", "")
129
+ )
130
+ scope._span.set_attribute(
131
+ SemanticConvention.GEN_AI_REQUEST_FREQUENCY_PENALTY,
132
+ scope._kwargs.get("frequency_penalty", 0.0),
133
+ )
134
+ scope._span.set_attribute(
135
+ SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS,
136
+ scope._kwargs.get("max_completion_tokens", -1),
137
+ )
138
+ scope._span.set_attribute(
139
+ SemanticConvention.GEN_AI_REQUEST_PRESENCE_PENALTY,
140
+ scope._kwargs.get("presence_penalty", 0.0),
141
+ )
142
+ scope._span.set_attribute(
143
+ SemanticConvention.GEN_AI_REQUEST_STOP_SEQUENCES, scope._kwargs.get("stop", [])
144
+ )
145
+ scope._span.set_attribute(
146
+ SemanticConvention.GEN_AI_REQUEST_TEMPERATURE,
147
+ scope._kwargs.get("temperature", 1.0),
148
+ )
149
+ scope._span.set_attribute(
150
+ SemanticConvention.GEN_AI_REQUEST_TOP_P, scope._kwargs.get("top_p", 1.0)
151
+ )
152
+ scope._span.set_attribute(
153
+ SemanticConvention.GEN_AI_REQUEST_USER, scope._kwargs.get("user", "")
154
+ )
155
+ scope._span.set_attribute(
156
+ SemanticConvention.GEN_AI_REQUEST_SERVICE_TIER,
157
+ scope._kwargs.get("service_tier", "on_demand"),
158
+ )
105
159
 
106
160
  # Span Attributes for Response parameters
107
161
  scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_ID, scope._response_id)
108
- scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_FINISH_REASON, [scope._finish_reason])
109
- scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_SYSTEM_FINGERPRINT, scope._system_fingerprint)
110
- scope._span.set_attribute(SemanticConvention.GEN_AI_OUTPUT_TYPE, "text" if isinstance(scope._llmresponse, str) else "json")
162
+ scope._span.set_attribute(
163
+ SemanticConvention.GEN_AI_RESPONSE_FINISH_REASON, [scope._finish_reason]
164
+ )
165
+ scope._span.set_attribute(
166
+ SemanticConvention.GEN_AI_RESPONSE_SYSTEM_FINGERPRINT, scope._system_fingerprint
167
+ )
168
+ scope._span.set_attribute(
169
+ SemanticConvention.GEN_AI_OUTPUT_TYPE,
170
+ "text" if isinstance(scope._llmresponse, str) else "json",
171
+ )
111
172
 
112
173
  # Span Attributes for Cost and Tokens
113
- scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens)
114
- scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, scope._output_tokens)
115
- scope._span.set_attribute(SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, scope._input_tokens + scope._output_tokens)
174
+ scope._span.set_attribute(
175
+ SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens
176
+ )
177
+ scope._span.set_attribute(
178
+ SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, scope._output_tokens
179
+ )
180
+ scope._span.set_attribute(
181
+ SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE,
182
+ scope._input_tokens + scope._output_tokens,
183
+ )
116
184
  scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
117
185
 
118
186
  # Span Attributes for Tools
119
187
  if scope._tools:
120
- scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_NAME, scope._tools.get("function", {}).get("name", ""))
121
- scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_CALL_ID, str(scope._tools.get("id", "")))
122
- scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_ARGS, str(scope._tools.get("function", {}).get("arguments", "")))
188
+ scope._span.set_attribute(
189
+ SemanticConvention.GEN_AI_TOOL_NAME,
190
+ scope._tools.get("function", {}).get("name", ""),
191
+ )
192
+ scope._span.set_attribute(
193
+ SemanticConvention.GEN_AI_TOOL_CALL_ID, str(scope._tools.get("id", ""))
194
+ )
195
+ scope._span.set_attribute(
196
+ SemanticConvention.GEN_AI_TOOL_ARGS,
197
+ str(scope._tools.get("function", {}).get("arguments", "")),
198
+ )
123
199
 
124
200
  # Span Attributes for Content
125
201
  if capture_message_content:
126
202
  scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_PROMPT, prompt)
127
- scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_COMPLETION, scope._llmresponse)
203
+ scope._span.set_attribute(
204
+ SemanticConvention.GEN_AI_CONTENT_COMPLETION, scope._llmresponse
205
+ )
128
206
 
129
207
  # To be removed one the change to span_attributes (from span events) is complete
130
208
  scope._span.add_event(
@@ -144,23 +222,69 @@ def common_chat_logic(scope, pricing_info, environment, application_name, metric
144
222
 
145
223
  # Metrics
146
224
  if not disable_metrics:
147
- record_completion_metrics(metrics, SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_GROQ,
148
- scope._server_address, scope._server_port, request_model, scope._response_model, environment,
149
- application_name, scope._start_time, scope._end_time, scope._input_tokens, scope._output_tokens,
150
- cost, scope._tbt, scope._ttft)
225
+ record_completion_metrics(
226
+ metrics,
227
+ SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
228
+ SemanticConvention.GEN_AI_SYSTEM_GROQ,
229
+ scope._server_address,
230
+ scope._server_port,
231
+ request_model,
232
+ scope._response_model,
233
+ environment,
234
+ application_name,
235
+ scope._start_time,
236
+ scope._end_time,
237
+ scope._input_tokens,
238
+ scope._output_tokens,
239
+ cost,
240
+ scope._tbt,
241
+ scope._ttft,
242
+ )
151
243
 
152
- def process_streaming_chat_response(scope, pricing_info, environment, application_name, metrics,
153
- capture_message_content=False, disable_metrics=False, version=""):
244
+
245
+ def process_streaming_chat_response(
246
+ scope,
247
+ pricing_info,
248
+ environment,
249
+ application_name,
250
+ metrics,
251
+ capture_message_content=False,
252
+ disable_metrics=False,
253
+ version="",
254
+ ):
154
255
  """
155
256
  Process chat request and generate Telemetry
156
257
  """
157
258
 
158
- common_chat_logic(scope, pricing_info, environment, application_name, metrics,
159
- capture_message_content, disable_metrics, version, is_stream=True)
259
+ common_chat_logic(
260
+ scope,
261
+ pricing_info,
262
+ environment,
263
+ application_name,
264
+ metrics,
265
+ capture_message_content,
266
+ disable_metrics,
267
+ version,
268
+ is_stream=True,
269
+ )
270
+
160
271
 
161
- def process_chat_response(response, request_model, pricing_info, server_port, server_address,
162
- environment, application_name, metrics, start_time, span, capture_message_content=False,
163
- disable_metrics=False, version="1.0.0", **kwargs):
272
+ def process_chat_response(
273
+ response,
274
+ request_model,
275
+ pricing_info,
276
+ server_port,
277
+ server_address,
278
+ environment,
279
+ application_name,
280
+ metrics,
281
+ start_time,
282
+ span,
283
+ capture_message_content=False,
284
+ disable_metrics=False,
285
+ version="1.0.0",
286
+ **kwargs,
287
+ ):
164
288
  """
165
289
  Process chat request and generate Telemetry
166
290
  """
@@ -185,15 +309,28 @@ def process_chat_response(response, request_model, pricing_info, server_port, se
185
309
  scope._server_address, scope._server_port = server_address, server_port
186
310
  scope._kwargs = kwargs
187
311
  scope._system_fingerprint = response_dict.get("system_fingerprint")
188
- scope._finish_reason = str(response_dict.get("choices", [])[0].get("finish_reason", ""))
312
+ scope._finish_reason = str(
313
+ response_dict.get("choices", [])[0].get("finish_reason", "")
314
+ )
189
315
 
190
316
  # Handle tool calls
191
317
  if scope._kwargs.get("tools"):
192
- scope._tools = response_dict.get("choices", [{}])[0].get("message", {}).get("tool_calls")
318
+ scope._tools = (
319
+ response_dict.get("choices", [{}])[0].get("message", {}).get("tool_calls")
320
+ )
193
321
  else:
194
322
  scope._tools = None
195
323
 
196
- common_chat_logic(scope, pricing_info, environment, application_name, metrics,
197
- capture_message_content, disable_metrics, version, is_stream=False)
324
+ common_chat_logic(
325
+ scope,
326
+ pricing_info,
327
+ environment,
328
+ application_name,
329
+ metrics,
330
+ capture_message_content,
331
+ disable_metrics,
332
+ version,
333
+ is_stream=False,
334
+ )
198
335
 
199
336
  return response
@@ -12,6 +12,7 @@ from openlit.instrumentation.haystack.async_haystack import async_general_wrap
12
12
 
13
13
  _instruments = ("haystack-ai >= 2.0.0",)
14
14
 
15
+
15
16
  class HaystackInstrumentor(BaseInstrumentor):
16
17
  """Optimized instrumentor for Haystack with minimal overhead"""
17
18
 
@@ -32,16 +33,34 @@ class HaystackInstrumentor(BaseInstrumentor):
32
33
  # Pipeline operations (always enabled)
33
34
  try:
34
35
  wrap_function_wrapper(
35
- "haystack", "Pipeline.run",
36
- general_wrap("pipeline", version, environment, application_name,
37
- tracer, pricing_info, capture_message_content,
38
- metrics, disable_metrics)
36
+ "haystack",
37
+ "Pipeline.run",
38
+ general_wrap(
39
+ "pipeline",
40
+ version,
41
+ environment,
42
+ application_name,
43
+ tracer,
44
+ pricing_info,
45
+ capture_message_content,
46
+ metrics,
47
+ disable_metrics,
48
+ ),
39
49
  )
40
50
  wrap_function_wrapper(
41
- "haystack", "AsyncPipeline.run_async",
42
- async_general_wrap("pipeline", version, environment,
43
- application_name, tracer, pricing_info,
44
- capture_message_content, metrics, disable_metrics)
51
+ "haystack",
52
+ "AsyncPipeline.run_async",
53
+ async_general_wrap(
54
+ "pipeline",
55
+ version,
56
+ environment,
57
+ application_name,
58
+ tracer,
59
+ pricing_info,
60
+ capture_message_content,
61
+ metrics,
62
+ disable_metrics,
63
+ ),
45
64
  )
46
65
  except Exception:
47
66
  pass
@@ -49,27 +68,54 @@ class HaystackInstrumentor(BaseInstrumentor):
49
68
  # Component operations (only if detailed_tracing enabled)
50
69
  if detailed_tracing:
51
70
  components = [
52
- ("haystack.components.retrievers.in_memory",
53
- "InMemoryBM25Retriever.run", "bm25_retriever"),
54
- ("haystack.components.builders.prompt_builder",
55
- "PromptBuilder.run", "prompt_builder"),
56
- ("haystack.components.generators.openai",
57
- "OpenAIGenerator.run", "openai_generator"),
58
- ("haystack.components.generators.chat.openai",
59
- "OpenAIChatGenerator.run", "openai_chat_generator"),
60
- ("haystack.components.embedders.openai_text_embedder",
61
- "OpenAITextEmbedder.run", "text_embedder"),
62
- ("haystack.components.embedders.openai_document_embedder",
63
- "OpenAIDocumentEmbedder.run", "document_embedder"),
71
+ (
72
+ "haystack.components.retrievers.in_memory",
73
+ "InMemoryBM25Retriever.run",
74
+ "bm25_retriever",
75
+ ),
76
+ (
77
+ "haystack.components.builders.prompt_builder",
78
+ "PromptBuilder.run",
79
+ "prompt_builder",
80
+ ),
81
+ (
82
+ "haystack.components.generators.openai",
83
+ "OpenAIGenerator.run",
84
+ "openai_generator",
85
+ ),
86
+ (
87
+ "haystack.components.generators.chat.openai",
88
+ "OpenAIChatGenerator.run",
89
+ "openai_chat_generator",
90
+ ),
91
+ (
92
+ "haystack.components.embedders.openai_text_embedder",
93
+ "OpenAITextEmbedder.run",
94
+ "text_embedder",
95
+ ),
96
+ (
97
+ "haystack.components.embedders.openai_document_embedder",
98
+ "OpenAIDocumentEmbedder.run",
99
+ "document_embedder",
100
+ ),
64
101
  ]
65
102
 
66
103
  for module, method, component_type in components:
67
104
  try:
68
105
  wrap_function_wrapper(
69
- module, method,
70
- general_wrap(component_type, version, environment,
71
- application_name, tracer, pricing_info,
72
- capture_message_content, metrics, disable_metrics)
106
+ module,
107
+ method,
108
+ general_wrap(
109
+ component_type,
110
+ version,
111
+ environment,
112
+ application_name,
113
+ tracer,
114
+ pricing_info,
115
+ capture_message_content,
116
+ metrics,
117
+ disable_metrics,
118
+ ),
73
119
  )
74
120
  except Exception:
75
121
  pass
@@ -12,8 +12,18 @@ from openlit.instrumentation.haystack.utils import (
12
12
  set_server_address_and_port,
13
13
  )
14
14
 
15
- def async_general_wrap(endpoint, version, environment, application_name,
16
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
15
+
16
+ def async_general_wrap(
17
+ endpoint,
18
+ version,
19
+ environment,
20
+ application_name,
21
+ tracer,
22
+ pricing_info,
23
+ capture_message_content,
24
+ metrics,
25
+ disable_metrics,
26
+ ):
17
27
  """Optimized async wrapper for Haystack operations"""
18
28
 
19
29
  async def wrapper(wrapped, instance, args, kwargs):
@@ -41,10 +51,22 @@ def async_general_wrap(endpoint, version, environment, application_name,
41
51
 
42
52
  try:
43
53
  response = process_haystack_response(
44
- response, operation_type, server_address, server_port,
45
- environment, application_name, metrics, start_time, span,
46
- capture_message_content, disable_metrics, version,
47
- instance, args, endpoint=endpoint, **kwargs
54
+ response,
55
+ operation_type,
56
+ server_address,
57
+ server_port,
58
+ environment,
59
+ application_name,
60
+ metrics,
61
+ start_time,
62
+ span,
63
+ capture_message_content,
64
+ disable_metrics,
65
+ version,
66
+ instance,
67
+ args,
68
+ endpoint=endpoint,
69
+ **kwargs,
48
70
  )
49
71
  except Exception as e:
50
72
  handle_exception(span, e)
@@ -12,8 +12,18 @@ from openlit.instrumentation.haystack.utils import (
12
12
  set_server_address_and_port,
13
13
  )
14
14
 
15
- def general_wrap(endpoint, version, environment, application_name,
16
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
15
+
16
+ def general_wrap(
17
+ endpoint,
18
+ version,
19
+ environment,
20
+ application_name,
21
+ tracer,
22
+ pricing_info,
23
+ capture_message_content,
24
+ metrics,
25
+ disable_metrics,
26
+ ):
17
27
  """Optimized wrapper for Haystack operations"""
18
28
 
19
29
  def wrapper(wrapped, instance, args, kwargs):
@@ -41,10 +51,22 @@ def general_wrap(endpoint, version, environment, application_name,
41
51
 
42
52
  try:
43
53
  response = process_haystack_response(
44
- response, operation_type, server_address, server_port,
45
- environment, application_name, metrics, start_time, span,
46
- capture_message_content, disable_metrics, version,
47
- instance, args, endpoint=endpoint, **kwargs
54
+ response,
55
+ operation_type,
56
+ server_address,
57
+ server_port,
58
+ environment,
59
+ application_name,
60
+ metrics,
61
+ start_time,
62
+ span,
63
+ capture_message_content,
64
+ disable_metrics,
65
+ version,
66
+ instance,
67
+ args,
68
+ endpoint=endpoint,
69
+ **kwargs,
48
70
  )
49
71
  except Exception as e:
50
72
  handle_exception(span, e)