openlit 1.34.29__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 +111 -24
- openlit/instrumentation/crewai/async_crewai.py +114 -0
- openlit/instrumentation/crewai/crewai.py +104 -131
- openlit/instrumentation/crewai/utils.py +615 -0
- 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 +312 -101
- 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 +660 -186
- openlit/instrumentation/openai_agents/__init__.py +6 -2
- openlit/instrumentation/openai_agents/processor.py +409 -537
- 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 +101 -7
- {openlit-1.34.29.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.29.dist-info/RECORD +0 -166
- {openlit-1.34.29.dist-info → openlit-1.34.31.dist-info}/LICENSE +0 -0
- {openlit-1.34.29.dist-info → openlit-1.34.31.dist-info}/WHEEL +0 -0
@@ -5,13 +5,18 @@ from typing import Collection, Iterable
|
|
5
5
|
import logging
|
6
6
|
from functools import partial
|
7
7
|
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
8
|
-
from opentelemetry.sdk.resources import
|
8
|
+
from opentelemetry.sdk.resources import (
|
9
|
+
SERVICE_NAME,
|
10
|
+
TELEMETRY_SDK_NAME,
|
11
|
+
DEPLOYMENT_ENVIRONMENT,
|
12
|
+
)
|
9
13
|
from opentelemetry.metrics import get_meter, CallbackOptions, Observation
|
10
14
|
from openlit.semcov import SemanticConvention
|
11
15
|
|
12
16
|
# Initialize logger for logging potential issues and operations
|
13
17
|
logger = logging.getLogger(__name__)
|
14
18
|
|
19
|
+
|
15
20
|
class GPUInstrumentor(BaseInstrumentor):
|
16
21
|
"""
|
17
22
|
An instrumentor for collecting GPU metrics.
|
@@ -55,8 +60,14 @@ class GPUInstrumentor(BaseInstrumentor):
|
|
55
60
|
for semantic_name, internal_name in metric_names:
|
56
61
|
meter.create_observable_gauge(
|
57
62
|
name=getattr(SemanticConvention, semantic_name),
|
58
|
-
callbacks=[
|
59
|
-
|
63
|
+
callbacks=[
|
64
|
+
partial(
|
65
|
+
self._collect_metric,
|
66
|
+
environment,
|
67
|
+
application_name,
|
68
|
+
internal_name,
|
69
|
+
)
|
70
|
+
],
|
60
71
|
description=f"GPU {internal_name.replace('_', ' ').title()}",
|
61
72
|
)
|
62
73
|
|
@@ -67,32 +78,38 @@ class GPUInstrumentor(BaseInstrumentor):
|
|
67
78
|
def _get_gpu_type(self) -> str:
|
68
79
|
try:
|
69
80
|
import pynvml
|
81
|
+
|
70
82
|
pynvml.nvmlInit()
|
71
83
|
return "nvidia"
|
72
84
|
except Exception:
|
73
85
|
try:
|
74
86
|
import amdsmi
|
87
|
+
|
75
88
|
amdsmi.amdsmi_init()
|
76
89
|
return "amd"
|
77
90
|
except Exception:
|
78
91
|
return None
|
79
92
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
options: CallbackOptions) -> Iterable[Observation]:
|
93
|
+
def _collect_metric(
|
94
|
+
self, environment, application_name, metric_name, options: CallbackOptions
|
95
|
+
) -> Iterable[Observation]:
|
84
96
|
# pylint: disable=no-else-return
|
85
97
|
if self.gpu_type == "nvidia":
|
86
|
-
return self._collect_nvidia_metrics(
|
98
|
+
return self._collect_nvidia_metrics(
|
99
|
+
environment, application_name, metric_name, options
|
100
|
+
)
|
87
101
|
elif self.gpu_type == "amd":
|
88
|
-
return self._collect_amd_metrics(
|
102
|
+
return self._collect_amd_metrics(
|
103
|
+
environment, application_name, metric_name, options
|
104
|
+
)
|
89
105
|
return []
|
90
106
|
|
91
|
-
def _collect_nvidia_metrics(
|
92
|
-
|
93
|
-
|
107
|
+
def _collect_nvidia_metrics(
|
108
|
+
self, environment, application_name, metric_name, options: CallbackOptions
|
109
|
+
) -> Iterable[Observation]:
|
94
110
|
try:
|
95
111
|
import pynvml
|
112
|
+
|
96
113
|
gpu_count = pynvml.nvmlDeviceGetCount()
|
97
114
|
mega_bytes = 1024 * 1024
|
98
115
|
gpu_index = 0
|
@@ -103,8 +120,9 @@ class GPUInstrumentor(BaseInstrumentor):
|
|
103
120
|
try:
|
104
121
|
# pylint: disable=no-else-return
|
105
122
|
if metric_name == "temperature":
|
106
|
-
return pynvml.nvmlDeviceGetTemperature(
|
107
|
-
|
123
|
+
return pynvml.nvmlDeviceGetTemperature(
|
124
|
+
handle, pynvml.NVML_TEMPERATURE_GPU
|
125
|
+
)
|
108
126
|
elif metric_name == "utilization":
|
109
127
|
return pynvml.nvmlDeviceGetUtilizationRates(handle).gpu
|
110
128
|
elif metric_name == "utilization_enc":
|
@@ -115,26 +133,43 @@ class GPUInstrumentor(BaseInstrumentor):
|
|
115
133
|
return 0
|
116
134
|
elif metric_name == "memory_available":
|
117
135
|
memory_info = pynvml.nvmlDeviceGetMemoryInfo(handle)
|
118
|
-
return (
|
136
|
+
return (
|
137
|
+
memory_info.free // mega_bytes
|
138
|
+
) # Assuming reserved memory is 0
|
119
139
|
elif metric_name == "memory_total":
|
120
|
-
return (
|
140
|
+
return (
|
141
|
+
pynvml.nvmlDeviceGetMemoryInfo(handle).total
|
142
|
+
// mega_bytes
|
143
|
+
)
|
121
144
|
elif metric_name == "memory_used":
|
122
|
-
return (
|
145
|
+
return (
|
146
|
+
pynvml.nvmlDeviceGetMemoryInfo(handle).used
|
147
|
+
// mega_bytes
|
148
|
+
)
|
123
149
|
elif metric_name == "memory_free":
|
124
|
-
return (
|
150
|
+
return (
|
151
|
+
pynvml.nvmlDeviceGetMemoryInfo(handle).free
|
152
|
+
// mega_bytes
|
153
|
+
)
|
125
154
|
elif metric_name == "power_draw":
|
126
|
-
return
|
155
|
+
return pynvml.nvmlDeviceGetPowerUsage(handle) // 1000.0
|
127
156
|
elif metric_name == "power_limit":
|
128
|
-
return (
|
157
|
+
return (
|
158
|
+
pynvml.nvmlDeviceGetEnforcedPowerLimit(handle) // 1000.0
|
159
|
+
)
|
129
160
|
except Exception as e:
|
130
161
|
# pylint: disable=cell-var-from-loop
|
131
|
-
logger.error(
|
132
|
-
|
162
|
+
logger.error(
|
163
|
+
"Error collecting metric %s for GPU %d: %s",
|
164
|
+
metric_name,
|
165
|
+
gpu_index,
|
166
|
+
e,
|
167
|
+
)
|
133
168
|
return 0
|
134
169
|
|
135
170
|
def safe_decode(byte_string):
|
136
171
|
if isinstance(byte_string, bytes):
|
137
|
-
return byte_string.decode(
|
172
|
+
return byte_string.decode("utf-8")
|
138
173
|
return byte_string
|
139
174
|
|
140
175
|
attributes = {
|
@@ -142,19 +177,24 @@ class GPUInstrumentor(BaseInstrumentor):
|
|
142
177
|
SERVICE_NAME: application_name,
|
143
178
|
DEPLOYMENT_ENVIRONMENT: environment,
|
144
179
|
SemanticConvention.GPU_INDEX: str(gpu_index),
|
145
|
-
SemanticConvention.GPU_UUID: safe_decode(
|
146
|
-
|
180
|
+
SemanticConvention.GPU_UUID: safe_decode(
|
181
|
+
pynvml.nvmlDeviceGetUUID(handle)
|
182
|
+
),
|
183
|
+
SemanticConvention.GPU_NAME: safe_decode(
|
184
|
+
pynvml.nvmlDeviceGetName(handle)
|
185
|
+
),
|
147
186
|
}
|
148
187
|
yield Observation(get_metric_value(handle, metric_name), attributes)
|
149
188
|
|
150
189
|
except Exception as e:
|
151
190
|
logger.error("Error in GPU metrics collection: %s", e)
|
152
191
|
|
153
|
-
def _collect_amd_metrics(
|
154
|
-
|
155
|
-
|
192
|
+
def _collect_amd_metrics(
|
193
|
+
self, environment, application_name, metric_name, options: CallbackOptions
|
194
|
+
) -> Iterable[Observation]:
|
156
195
|
try:
|
157
196
|
import amdsmi
|
197
|
+
|
158
198
|
# Get the number of AMD GPUs
|
159
199
|
devices = amdsmi.amdsmi_get_processor_handles()
|
160
200
|
mega_bytes = 1024 * 1024
|
@@ -165,36 +205,69 @@ class GPUInstrumentor(BaseInstrumentor):
|
|
165
205
|
# pylint: disable=no-else-return
|
166
206
|
if metric_name == "temperature":
|
167
207
|
# pylint: disable=line-too-long
|
168
|
-
return amdsmi.amdsmi_get_temp_metric(
|
169
|
-
|
170
|
-
|
208
|
+
return amdsmi.amdsmi_get_temp_metric(
|
209
|
+
device_handle,
|
210
|
+
amdsmi.AmdSmiTemperatureType.EDGE,
|
211
|
+
amdsmi.AmdSmiTemperatureMetric.CURRENT,
|
212
|
+
)
|
171
213
|
elif metric_name == "utilization":
|
172
214
|
# pylint: disable=line-too-long
|
173
|
-
return amdsmi.amdsmi_get_utilization_count(
|
174
|
-
|
215
|
+
return amdsmi.amdsmi_get_utilization_count(
|
216
|
+
device_handle,
|
217
|
+
amdsmi.AmdSmiUtilizationCounterType.COARSE_GRAIN_GFX_ACTIVITY,
|
218
|
+
)
|
175
219
|
elif metric_name in ["utilization_enc", "utilization_dec"]:
|
176
220
|
return 0 # Placeholder if unsupported
|
177
221
|
elif metric_name == "fan_speed":
|
178
222
|
return amdsmi.amdsmi_get_gpu_fan_speed(device_handle, 0)
|
179
223
|
elif metric_name == "memory_available":
|
180
|
-
return (
|
224
|
+
return (
|
225
|
+
amdsmi.amdsmi_get_gpu_memory_total(device_handle)
|
226
|
+
// mega_bytes
|
227
|
+
)
|
181
228
|
elif metric_name == "memory_total":
|
182
|
-
return (
|
229
|
+
return (
|
230
|
+
amdsmi.amdsmi_get_gpu_memory_total(device_handle)
|
231
|
+
// mega_bytes
|
232
|
+
)
|
183
233
|
elif metric_name == "memory_used":
|
184
|
-
return (
|
234
|
+
return (
|
235
|
+
amdsmi.amdsmi_get_gpu_memory_usage(device_handle)
|
236
|
+
// mega_bytes
|
237
|
+
)
|
185
238
|
elif metric_name == "memory_free":
|
186
|
-
total_mem = (
|
187
|
-
|
188
|
-
|
239
|
+
total_mem = (
|
240
|
+
amdsmi.amdsmi_get_gpu_memory_total(device_handle)
|
241
|
+
// mega_bytes
|
242
|
+
)
|
243
|
+
used_mem = (
|
244
|
+
amdsmi.amdsmi_get_gpu_memory_usage(device_handle)
|
245
|
+
// mega_bytes
|
246
|
+
)
|
247
|
+
return total_mem - used_mem
|
189
248
|
elif metric_name == "power_draw":
|
190
249
|
# pylint: disable=line-too-long
|
191
|
-
return (
|
250
|
+
return (
|
251
|
+
amdsmi.amdsmi_get_power_info(device_handle)[
|
252
|
+
"average_socket_power"
|
253
|
+
]
|
254
|
+
// 1000.0
|
255
|
+
)
|
192
256
|
elif metric_name == "power_limit":
|
193
257
|
# pylint: disable=line-too-long
|
194
|
-
return (
|
258
|
+
return (
|
259
|
+
amdsmi.amdsmi_get_power_info(device_handle)[
|
260
|
+
"power_limit"
|
261
|
+
]
|
262
|
+
// 1000.0
|
263
|
+
)
|
195
264
|
except Exception as e:
|
196
|
-
logger.error(
|
197
|
-
|
265
|
+
logger.error(
|
266
|
+
"Error collecting metric %s for AMD GPU %d: %s",
|
267
|
+
metric_name,
|
268
|
+
amdsmi.amdsmi_get_xgmi_info(device_handle)["index"],
|
269
|
+
e,
|
270
|
+
)
|
198
271
|
return 0
|
199
272
|
|
200
273
|
attributes = {
|
@@ -202,12 +275,20 @@ class GPUInstrumentor(BaseInstrumentor):
|
|
202
275
|
SERVICE_NAME: application_name,
|
203
276
|
DEPLOYMENT_ENVIRONMENT: environment,
|
204
277
|
# pylint: disable=line-too-long
|
205
|
-
SemanticConvention.GPU_INDEX: amdsmi.amdsmi_get_xgmi_info(
|
278
|
+
SemanticConvention.GPU_INDEX: amdsmi.amdsmi_get_xgmi_info(
|
279
|
+
device_handle
|
280
|
+
)["index"],
|
206
281
|
# pylint: disable=line-too-long
|
207
|
-
SemanticConvention.GPU_UUID: amdsmi.amdsmi_get_gpu_asic_info(
|
208
|
-
|
282
|
+
SemanticConvention.GPU_UUID: amdsmi.amdsmi_get_gpu_asic_info(
|
283
|
+
device_handle
|
284
|
+
)["market_name"],
|
285
|
+
SemanticConvention.GPU_NAME: amdsmi.amdsmi_get_device_name(
|
286
|
+
device_handle
|
287
|
+
),
|
209
288
|
}
|
210
|
-
yield Observation(
|
289
|
+
yield Observation(
|
290
|
+
get_metric_value(device_handle, metric_name), attributes
|
291
|
+
)
|
211
292
|
|
212
293
|
except Exception as e:
|
213
294
|
logger.error("Error in AMD GPU metrics collection: %s", e)
|
@@ -10,6 +10,7 @@ from openlit.instrumentation.groq.async_groq import async_chat
|
|
10
10
|
|
11
11
|
_instruments = ("groq >= 0.5.0",)
|
12
12
|
|
13
|
+
|
13
14
|
class GroqInstrumentor(BaseInstrumentor):
|
14
15
|
"""
|
15
16
|
An instrumentor for Groq client library.
|
@@ -32,16 +33,32 @@ class GroqInstrumentor(BaseInstrumentor):
|
|
32
33
|
wrap_function_wrapper(
|
33
34
|
"groq.resources.chat.completions",
|
34
35
|
"Completions.create",
|
35
|
-
chat(
|
36
|
-
|
36
|
+
chat(
|
37
|
+
version,
|
38
|
+
environment,
|
39
|
+
application_name,
|
40
|
+
tracer,
|
41
|
+
pricing_info,
|
42
|
+
capture_message_content,
|
43
|
+
metrics,
|
44
|
+
disable_metrics,
|
45
|
+
),
|
37
46
|
)
|
38
47
|
|
39
48
|
# Chat completions
|
40
49
|
wrap_function_wrapper(
|
41
50
|
"groq.resources.chat.completions",
|
42
51
|
"AsyncCompletions.create",
|
43
|
-
async_chat(
|
44
|
-
|
52
|
+
async_chat(
|
53
|
+
version,
|
54
|
+
environment,
|
55
|
+
application_name,
|
56
|
+
tracer,
|
57
|
+
pricing_info,
|
58
|
+
capture_message_content,
|
59
|
+
metrics,
|
60
|
+
disable_metrics,
|
61
|
+
),
|
45
62
|
)
|
46
63
|
|
47
64
|
def _uninstrument(self, **kwargs):
|
@@ -4,19 +4,25 @@ Module for monitoring Groq API calls (async version).
|
|
4
4
|
|
5
5
|
import time
|
6
6
|
from opentelemetry.trace import SpanKind
|
7
|
-
from openlit.__helpers import
|
8
|
-
handle_exception,
|
9
|
-
set_server_address_and_port
|
10
|
-
)
|
7
|
+
from openlit.__helpers import handle_exception, set_server_address_and_port
|
11
8
|
from openlit.instrumentation.groq.utils import (
|
12
9
|
process_chunk,
|
13
10
|
process_streaming_chat_response,
|
14
|
-
process_chat_response
|
11
|
+
process_chat_response,
|
15
12
|
)
|
16
13
|
from openlit.semcov import SemanticConvention
|
17
14
|
|
18
|
-
|
19
|
-
|
15
|
+
|
16
|
+
def async_chat(
|
17
|
+
version,
|
18
|
+
environment,
|
19
|
+
application_name,
|
20
|
+
tracer,
|
21
|
+
pricing_info,
|
22
|
+
capture_message_content,
|
23
|
+
metrics,
|
24
|
+
disable_metrics,
|
25
|
+
):
|
20
26
|
"""
|
21
27
|
Generates a telemetry wrapper for GenAI function call
|
22
28
|
"""
|
@@ -27,15 +33,15 @@ def async_chat(version, environment, application_name, tracer, pricing_info,
|
|
27
33
|
"""
|
28
34
|
|
29
35
|
def __init__(
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
self,
|
37
|
+
wrapped,
|
38
|
+
span,
|
39
|
+
span_name,
|
40
|
+
kwargs,
|
41
|
+
server_address,
|
42
|
+
server_port,
|
43
|
+
**args,
|
44
|
+
):
|
39
45
|
self.__wrapped__ = wrapped
|
40
46
|
self._span = span
|
41
47
|
self._span_name = span_name
|
@@ -78,7 +84,9 @@ def async_chat(version, environment, application_name, tracer, pricing_info,
|
|
78
84
|
return chunk
|
79
85
|
except StopAsyncIteration:
|
80
86
|
try:
|
81
|
-
with tracer.start_as_current_span(
|
87
|
+
with tracer.start_as_current_span(
|
88
|
+
self._span_name, kind=SpanKind.CLIENT
|
89
|
+
) as self._span:
|
82
90
|
process_streaming_chat_response(
|
83
91
|
self,
|
84
92
|
pricing_info=pricing_info,
|
@@ -87,7 +95,7 @@ def async_chat(version, environment, application_name, tracer, pricing_info,
|
|
87
95
|
metrics=metrics,
|
88
96
|
capture_message_content=capture_message_content,
|
89
97
|
disable_metrics=disable_metrics,
|
90
|
-
version=version
|
98
|
+
version=version,
|
91
99
|
)
|
92
100
|
|
93
101
|
except Exception as e:
|
@@ -101,7 +109,9 @@ def async_chat(version, environment, application_name, tracer, pricing_info,
|
|
101
109
|
"""
|
102
110
|
# Check if streaming is enabled for the API call
|
103
111
|
streaming = kwargs.get("stream", False)
|
104
|
-
server_address, server_port = set_server_address_and_port(
|
112
|
+
server_address, server_port = set_server_address_and_port(
|
113
|
+
instance, "api.groq.com", 443
|
114
|
+
)
|
105
115
|
request_model = kwargs.get("model", "mixtral-8x7b-32768")
|
106
116
|
|
107
117
|
span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}"
|
@@ -110,7 +120,9 @@ def async_chat(version, environment, application_name, tracer, pricing_info,
|
|
110
120
|
# Special handling for streaming response
|
111
121
|
awaited_wrapped = await wrapped(*args, **kwargs)
|
112
122
|
span = tracer.start_span(span_name, kind=SpanKind.CLIENT)
|
113
|
-
return TracedAsyncStream(
|
123
|
+
return TracedAsyncStream(
|
124
|
+
awaited_wrapped, span, span_name, kwargs, server_address, server_port
|
125
|
+
)
|
114
126
|
else:
|
115
127
|
# Handling for non-streaming responses
|
116
128
|
with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
|
@@ -132,7 +144,7 @@ def async_chat(version, environment, application_name, tracer, pricing_info,
|
|
132
144
|
capture_message_content=capture_message_content,
|
133
145
|
disable_metrics=disable_metrics,
|
134
146
|
version=version,
|
135
|
-
**kwargs
|
147
|
+
**kwargs,
|
136
148
|
)
|
137
149
|
|
138
150
|
except Exception as e:
|
@@ -4,19 +4,25 @@ Module for monitoring Groq API calls.
|
|
4
4
|
|
5
5
|
import time
|
6
6
|
from opentelemetry.trace import SpanKind
|
7
|
-
from openlit.__helpers import
|
8
|
-
handle_exception,
|
9
|
-
set_server_address_and_port
|
10
|
-
)
|
7
|
+
from openlit.__helpers import handle_exception, set_server_address_and_port
|
11
8
|
from openlit.instrumentation.groq.utils import (
|
12
9
|
process_chunk,
|
13
10
|
process_streaming_chat_response,
|
14
|
-
process_chat_response
|
11
|
+
process_chat_response,
|
15
12
|
)
|
16
13
|
from openlit.semcov import SemanticConvention
|
17
14
|
|
18
|
-
|
19
|
-
|
15
|
+
|
16
|
+
def chat(
|
17
|
+
version,
|
18
|
+
environment,
|
19
|
+
application_name,
|
20
|
+
tracer,
|
21
|
+
pricing_info,
|
22
|
+
capture_message_content,
|
23
|
+
metrics,
|
24
|
+
disable_metrics,
|
25
|
+
):
|
20
26
|
"""
|
21
27
|
Generates a telemetry wrapper for GenAI function call
|
22
28
|
"""
|
@@ -27,15 +33,15 @@ def chat(version, environment, application_name, tracer, pricing_info,
|
|
27
33
|
"""
|
28
34
|
|
29
35
|
def __init__(
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
self,
|
37
|
+
wrapped,
|
38
|
+
span,
|
39
|
+
span_name,
|
40
|
+
kwargs,
|
41
|
+
server_address,
|
42
|
+
server_port,
|
43
|
+
**args,
|
44
|
+
):
|
39
45
|
self.__wrapped__ = wrapped
|
40
46
|
self._span = span
|
41
47
|
self._span_name = span_name
|
@@ -78,7 +84,9 @@ def chat(version, environment, application_name, tracer, pricing_info,
|
|
78
84
|
return chunk
|
79
85
|
except StopIteration:
|
80
86
|
try:
|
81
|
-
with tracer.start_as_current_span(
|
87
|
+
with tracer.start_as_current_span(
|
88
|
+
self._span_name, kind=SpanKind.CLIENT
|
89
|
+
) as self._span:
|
82
90
|
process_streaming_chat_response(
|
83
91
|
self,
|
84
92
|
pricing_info=pricing_info,
|
@@ -87,7 +95,7 @@ def chat(version, environment, application_name, tracer, pricing_info,
|
|
87
95
|
metrics=metrics,
|
88
96
|
capture_message_content=capture_message_content,
|
89
97
|
disable_metrics=disable_metrics,
|
90
|
-
version=version
|
98
|
+
version=version,
|
91
99
|
)
|
92
100
|
|
93
101
|
except Exception as e:
|
@@ -101,7 +109,9 @@ def chat(version, environment, application_name, tracer, pricing_info,
|
|
101
109
|
"""
|
102
110
|
# Check if streaming is enabled for the API call
|
103
111
|
streaming = kwargs.get("stream", False)
|
104
|
-
server_address, server_port = set_server_address_and_port(
|
112
|
+
server_address, server_port = set_server_address_and_port(
|
113
|
+
instance, "api.groq.com", 443
|
114
|
+
)
|
105
115
|
request_model = kwargs.get("model", "mixtral-8x7b-32768")
|
106
116
|
|
107
117
|
span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}"
|
@@ -110,7 +120,9 @@ def chat(version, environment, application_name, tracer, pricing_info,
|
|
110
120
|
# Special handling for streaming response
|
111
121
|
awaited_wrapped = wrapped(*args, **kwargs)
|
112
122
|
span = tracer.start_span(span_name, kind=SpanKind.CLIENT)
|
113
|
-
return TracedSyncStream(
|
123
|
+
return TracedSyncStream(
|
124
|
+
awaited_wrapped, span, span_name, kwargs, server_address, server_port
|
125
|
+
)
|
114
126
|
else:
|
115
127
|
# Handling for non-streaming responses
|
116
128
|
with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
|
@@ -132,7 +144,7 @@ def chat(version, environment, application_name, tracer, pricing_info,
|
|
132
144
|
capture_message_content=capture_message_content,
|
133
145
|
disable_metrics=disable_metrics,
|
134
146
|
version=version,
|
135
|
-
**kwargs
|
147
|
+
**kwargs,
|
136
148
|
)
|
137
149
|
|
138
150
|
except Exception as e:
|