openlit 1.11.0__py3-none-any.whl → 1.14.0__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/__init__.py CHANGED
@@ -1,17 +1,26 @@
1
+ # pylint: disable=broad-exception-caught
1
2
  """
2
3
  The __init__.py module for the openLIT package.
3
4
  This module sets up the openLIT configuration and instrumentation for various
4
5
  large language models (LLMs).
5
6
  """
7
+
6
8
  from typing import Dict
7
9
  import logging
8
10
  from importlib.util import find_spec
11
+ from functools import wraps
12
+ from contextlib import contextmanager
13
+
9
14
 
10
15
  # Import internal modules for setting up tracing and fetching pricing info.
16
+ from opentelemetry import trace as t
17
+ from opentelemetry.trace import SpanKind, Status, StatusCode, Span
18
+ from openlit.semcov import SemanticConvetion
11
19
  from openlit.otel.tracing import setup_tracing
12
20
  from openlit.otel.metrics import setup_meter
13
21
  from openlit.__helpers import fetch_pricing_info
14
22
 
23
+
15
24
  # Instrumentors for various large language models.
16
25
  from openlit.instrumentation.openai import OpenAIInstrumentor
17
26
  from openlit.instrumentation.anthropic import AnthropicInstrumentor
@@ -31,17 +40,19 @@ from openlit.instrumentation.pinecone import PineconeInstrumentor
31
40
  from openlit.instrumentation.qdrant import QdrantInstrumentor
32
41
  from openlit.instrumentation.milvus import MilvusInstrumentor
33
42
  from openlit.instrumentation.transformers import TransformersInstrumentor
43
+ from openlit.instrumentation.gpu import NvidiaGPUInstrumentor
34
44
 
35
45
  # Set up logging for error and information messages.
36
46
  logger = logging.getLogger(__name__)
37
47
 
48
+
38
49
  class OpenlitConfig:
39
50
  """
40
51
  A Singleton Configuration class for openLIT.
41
-
52
+
42
53
  This class maintains a single instance of configuration settings including
43
54
  environment details, application name, and tracing information throughout the openLIT package.
44
-
55
+
45
56
  Attributes:
46
57
  environment (str): Deployment environment of the application.
47
58
  application_name (str): Name of the application using openLIT.
@@ -52,6 +63,7 @@ class OpenlitConfig:
52
63
  disable_batch (bool): Flag to disable batch span processing in tracing.
53
64
  trace_content (bool): Flag to enable or disable tracing of content.
54
65
  """
66
+
55
67
  _instance = None
56
68
 
57
69
  def __new__(cls):
@@ -76,9 +88,19 @@ class OpenlitConfig:
76
88
  cls.disable_metrics = False
77
89
 
78
90
  @classmethod
79
- def update_config(cls, environment, application_name, tracer, otlp_endpoint,
80
- otlp_headers, disable_batch, trace_content, metrics_dict,
81
- disable_metrics, pricing_json):
91
+ def update_config(
92
+ cls,
93
+ environment,
94
+ application_name,
95
+ tracer,
96
+ otlp_endpoint,
97
+ otlp_headers,
98
+ disable_batch,
99
+ trace_content,
100
+ metrics_dict,
101
+ disable_metrics,
102
+ pricing_json,
103
+ ):
82
104
  """
83
105
  Updates the configuration based on provided parameters.
84
106
 
@@ -104,8 +126,14 @@ class OpenlitConfig:
104
126
  cls.trace_content = trace_content
105
127
  cls.disable_metrics = disable_metrics
106
128
 
107
- def instrument_if_available(instrumentor_name, instrumentor_instance, config,
108
- disabled_instrumentors, module_name_map):
129
+
130
+ def instrument_if_available(
131
+ instrumentor_name,
132
+ instrumentor_instance,
133
+ config,
134
+ disabled_instrumentors,
135
+ module_name_map,
136
+ ):
109
137
  """Instruments the specified instrumentor if its library is available."""
110
138
  if instrumentor_name in disabled_instrumentors:
111
139
  return
@@ -121,7 +149,7 @@ def instrument_if_available(instrumentor_name, instrumentor_instance, config,
121
149
  pricing_info=config.pricing_info,
122
150
  trace_content=config.trace_content,
123
151
  metrics_dict=config.metrics_dict,
124
- disable_metrics=config.disable_metrics
152
+ disable_metrics=config.disable_metrics,
125
153
  )
126
154
 
127
155
  # pylint: disable=broad-exception-caught
@@ -130,13 +158,13 @@ def instrument_if_available(instrumentor_name, instrumentor_instance, config,
130
158
 
131
159
  def init(environment="default", application_name="default", tracer=None, otlp_endpoint=None,
132
160
  otlp_headers=None, disable_batch=False, trace_content=True, disabled_instrumentors=None,
133
- meter=None, disable_metrics=False, pricing_json=None):
161
+ meter=None, disable_metrics=False, pricing_json=None, collect_gpu_stats=False):
134
162
  """
135
163
  Initializes the openLIT configuration and setups tracing.
136
-
137
- This function sets up the openLIT environment with provided configurations
164
+
165
+ This function sets up the openLIT environment with provided configurations
138
166
  and initializes instrumentors for tracing.
139
-
167
+
140
168
  Args:
141
169
  environment (str): Deployment environment.
142
170
  application_name (str): Application name.
@@ -147,16 +175,17 @@ def init(environment="default", application_name="default", tracer=None, otlp_en
147
175
  disable_batch (bool): Flag to disable batch span processing (Optional).
148
176
  trace_content (bool): Flag to trace content (Optional).
149
177
  disabled_instrumentors (List[str]): Optional. List of instrumentor names to disable.
150
- disable_metrics (bool): Flag to disable metrics (Optional)
151
- pricing_json(str): File path or url to the pricing json (Optional)
178
+ disable_metrics (bool): Flag to disable metrics (Optional).
179
+ pricing_json(str): File path or url to the pricing json (Optional).
180
+ collect_gpu_stats (bool): Flag to enable or disable GPU metrics collection.
152
181
  """
153
182
  disabled_instrumentors = disabled_instrumentors if disabled_instrumentors else []
154
183
  # Check for invalid instrumentor names
155
184
 
156
185
  module_name_map = {
157
186
  "openai": "openai",
158
- "anthropic": "anthropic",
159
- "cohere": "cohere",
187
+ "anthropic": "anthropic",
188
+ "cohere": "cohere",
160
189
  "mistral": "mistralai",
161
190
  "bedrock": "boto3",
162
191
  "vertexai": "vertexai",
@@ -171,12 +200,16 @@ def init(environment="default", application_name="default", tracer=None, otlp_en
171
200
  "pinecone": "pinecone",
172
201
  "qdrant": "qdrant_client",
173
202
  "milvus": "pymilvus",
174
- "transformers": "transformers"
203
+ "transformers": "transformers",
175
204
  }
176
205
 
177
- invalid_instrumentors = [name for name in disabled_instrumentors if name not in module_name_map]
206
+ invalid_instrumentors = [
207
+ name for name in disabled_instrumentors if name not in module_name_map
208
+ ]
178
209
  for invalid_name in invalid_instrumentors:
179
- logger.warning("Invalid instrumentor name detected and ignored: '%s'", invalid_name)
210
+ logger.warning(
211
+ "Invalid instrumentor name detected and ignored: '%s'", invalid_name
212
+ )
180
213
 
181
214
  try:
182
215
  # Retrieve or create the single configuration instance.
@@ -185,9 +218,11 @@ def init(environment="default", application_name="default", tracer=None, otlp_en
185
218
  # Setup tracing based on the provided or default configuration.
186
219
  tracer = setup_tracing(
187
220
  application_name=application_name,
188
- environment=environment, tracer=tracer,
189
- otlp_endpoint=otlp_endpoint, otlp_headers=otlp_headers,
190
- disable_batch=disable_batch
221
+ environment=environment,
222
+ tracer=tracer,
223
+ otlp_endpoint=otlp_endpoint,
224
+ otlp_headers=otlp_headers,
225
+ disable_batch=disable_batch,
191
226
  )
192
227
 
193
228
  if not tracer:
@@ -195,18 +230,31 @@ def init(environment="default", application_name="default", tracer=None, otlp_en
195
230
  return
196
231
 
197
232
  # Setup meter and receive metrics_dict instead of meter
198
- metrics_dict = setup_meter(application_name=application_name,
199
- environment=environment, meter=meter,
200
- otlp_endpoint=otlp_endpoint, otlp_headers=otlp_headers)
233
+ metrics_dict = setup_meter(
234
+ application_name=application_name,
235
+ environment=environment,
236
+ meter=meter,
237
+ otlp_endpoint=otlp_endpoint,
238
+ otlp_headers=otlp_headers,
239
+ )
201
240
 
202
241
  if not metrics_dict:
203
242
  logger.error("openLIT metrics setup failed. Metrics will not be available.")
204
243
  return
205
244
 
206
245
  # Update global configuration with the provided settings.
207
- config.update_config(environment, application_name, tracer, otlp_endpoint,
208
- otlp_headers, disable_batch, trace_content,
209
- metrics_dict, disable_metrics, pricing_json)
246
+ config.update_config(
247
+ environment,
248
+ application_name,
249
+ tracer,
250
+ otlp_endpoint,
251
+ otlp_headers,
252
+ disable_batch,
253
+ trace_content,
254
+ metrics_dict,
255
+ disable_metrics,
256
+ pricing_json,
257
+ )
210
258
 
211
259
  # Map instrumentor names to their instances
212
260
  instrumentor_instances = {
@@ -227,7 +275,7 @@ def init(environment="default", application_name="default", tracer=None, otlp_en
227
275
  "pinecone": PineconeInstrumentor(),
228
276
  "qdrant": QdrantInstrumentor(),
229
277
  "milvus": MilvusInstrumentor(),
230
- "transformers": TransformersInstrumentor()
278
+ "transformers": TransformersInstrumentor(),
231
279
  }
232
280
 
233
281
  # Initialize and instrument only the enabled instrumentors
@@ -235,6 +283,139 @@ def init(environment="default", application_name="default", tracer=None, otlp_en
235
283
  instrument_if_available(name, instrumentor, config,
236
284
  disabled_instrumentors, module_name_map)
237
285
 
238
- # pylint: disable=broad-exception-caught
286
+ if (disable_metrics is False) and (collect_gpu_stats is True):
287
+ NvidiaGPUInstrumentor().instrument(
288
+ environment=config.environment,
289
+ application_name=config.application_name,
290
+ )
291
+
239
292
  except Exception as e:
240
293
  logger.error("Error during openLIT initialization: %s", e)
294
+
295
+
296
+ def trace(wrapped):
297
+ """
298
+ Generates a telemetry wrapper for messages to collect metrics.
299
+ """
300
+
301
+ @wraps(wrapped)
302
+ def wrapper(*args, **kwargs):
303
+ __trace = t.get_tracer_provider()
304
+ with __trace.get_tracer(__name__).start_as_current_span(
305
+ name=wrapped.__name__,
306
+ kind=SpanKind.CLIENT,
307
+ ) as span:
308
+ try:
309
+ response = wrapped(*args, **kwargs)
310
+ span.set_attribute(
311
+ SemanticConvetion.GEN_AI_CONTENT_COMPLETION, response
312
+ )
313
+ span.set_status(Status(StatusCode.OK))
314
+
315
+ except Exception as e:
316
+ response = None
317
+ span.record_exception(e)
318
+ span.set_status(status=Status(StatusCode.ERROR), description=e)
319
+ logging.error("Error in %s: %s", wrapped.__name__, e, exc_info=True)
320
+
321
+ # Adding function arguments as metadata
322
+ try:
323
+ span.set_attribute("function.args", str(args))
324
+ span.set_attribute("function.kwargs", str(kwargs))
325
+ span.set_attribute(
326
+ SemanticConvetion.GEN_AI_APPLICATION_NAME,
327
+ OpenlitConfig.application_name,
328
+ )
329
+ span.set_attribute(
330
+ SemanticConvetion.GEN_AI_ENVIRONMENT, OpenlitConfig.environment
331
+ )
332
+
333
+ except Exception as meta_exception:
334
+ logging.error(
335
+ "Failed to set metadata for %s: %s",
336
+ wrapped.__name__,
337
+ meta_exception,
338
+ exc_info=True,
339
+ )
340
+
341
+ return response
342
+
343
+ return wrapper
344
+
345
+
346
+ class TracedSpan:
347
+ """
348
+ A wrapper class for an OpenTelemetry span that provides helper methods
349
+ for setting result and metadata attributes on the span.
350
+
351
+ Attributes:
352
+ _span (Span): The underlying OpenTelemetry span.
353
+ """
354
+
355
+ def __init__(self, span):
356
+ """
357
+ Initializes the TracedSpan with the given span.
358
+
359
+ Params:
360
+ span (Span): The OpenTelemetry span to be wrapped.
361
+ """
362
+
363
+ self._span: Span = span
364
+
365
+ def set_result(self, result):
366
+ """
367
+ Sets the result attribute on the underlying span.
368
+
369
+ Params:
370
+ result: The result to be set as an attribute on the span.
371
+ """
372
+
373
+ self._span.set_attribute(SemanticConvetion.GEN_AI_CONTENT_COMPLETION, result)
374
+
375
+ def set_metadata(self, metadata: Dict):
376
+ """
377
+ Sets multiple attributes on the underlying span.
378
+
379
+ Params:
380
+ metadata (Dict): A dictionary of attributes to be set on the span.
381
+ """
382
+
383
+ self._span.set_attributes(attributes=metadata)
384
+
385
+ def __enter__(self):
386
+ """
387
+ Enters the context of the TracedSpan, returning itself.
388
+
389
+ Returns:
390
+ TracedSpan: The instance of TracedSpan.
391
+ """
392
+
393
+ return self
394
+
395
+ def __exit__(self, _exc_type, _exc_val, _exc_tb):
396
+ """
397
+ Exits the context of the TracedSpan by ending the underlying span.
398
+ """
399
+
400
+ self._span.end()
401
+
402
+
403
+ @contextmanager
404
+ def start_trace(name: str):
405
+ """
406
+ A context manager that starts a new trace and provides a TracedSpan
407
+ for usage within the context.
408
+
409
+ Params:
410
+ name (str): The name of the span.
411
+
412
+ Yields:
413
+ TracedSpan: The wrapped span for trace operations.
414
+ """
415
+
416
+ __trace = t.get_tracer_provider()
417
+ with __trace.get_tracer(__name__).start_as_current_span(
418
+ name,
419
+ kind=SpanKind.CLIENT,
420
+ ) as span:
421
+ yield TracedSpan(span)
@@ -0,0 +1,132 @@
1
+ # pylint: disable=useless-return, bad-staticmethod-argument, duplicate-code, import-outside-toplevel, broad-exception-caught, unused-argument
2
+ """Initializer of Auto Instrumentation of GPU Metrics"""
3
+
4
+ from typing import Collection, Iterable
5
+ import logging
6
+ from functools import partial
7
+
8
+ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
9
+ from opentelemetry.sdk.resources import TELEMETRY_SDK_NAME
10
+ from opentelemetry.metrics import get_meter, CallbackOptions, Observation
11
+
12
+ from openlit.semcov import SemanticConvetion
13
+
14
+ # Initialize logger for logging potential issues and operations
15
+ logger = logging.getLogger(__name__)
16
+
17
+ class NvidiaGPUInstrumentor(BaseInstrumentor):
18
+ """
19
+ An instrumentor for collecting NVIDIA GPU metrics.
20
+ """
21
+
22
+ def instrumentation_dependencies(self) -> Collection[str]:
23
+ return []
24
+
25
+ def _instrument(self, **kwargs):
26
+
27
+ application_name = kwargs.get("application_name", "default")
28
+ environment = kwargs.get("environment", "default")
29
+
30
+ meter = get_meter(
31
+ __name__,
32
+ "0.1.0",
33
+ schema_url="https://opentelemetry.io/schemas/1.11.0",
34
+ )
35
+
36
+ def check_and_record(value):
37
+ return value if value is not None else 0
38
+
39
+ meter.create_observable_gauge(
40
+ name=SemanticConvetion.GPU_UTILIZATION,
41
+ callbacks=[partial(self._collect_metric, environment,
42
+ application_name, check_and_record, "utilization")],
43
+ description="GPU Utilization",
44
+ )
45
+ meter.create_observable_gauge(
46
+ name=SemanticConvetion.GPU_UTILIZATION_ENC,
47
+ callbacks=[partial(self._collect_metric, environment,
48
+ application_name, check_and_record, "utilization_enc")],
49
+ description="GPU Encoder Utilization",
50
+ )
51
+ meter.create_observable_gauge(
52
+ name=SemanticConvetion.GPU_UTILIZATION_DEC,
53
+ callbacks=[partial(self._collect_metric, environment,
54
+ application_name, check_and_record, "utilization_dec")],
55
+ description="GPU Decoder Utilization",
56
+ )
57
+ meter.create_observable_gauge(
58
+ name=SemanticConvetion.GPU_TEMPERATURE,
59
+ callbacks=[partial(self._collect_metric, environment,
60
+ application_name, check_and_record, "temperature")],
61
+ description="GPU Temperature",
62
+ )
63
+ meter.create_observable_gauge(
64
+ name=SemanticConvetion.GPU_FAN_SPEED,
65
+ callbacks=[partial(self._collect_metric, environment,
66
+ application_name, check_and_record, "fan_speed")],
67
+ description="GPU Fan Speed",
68
+ )
69
+ meter.create_observable_gauge(
70
+ name=SemanticConvetion.GPU_MEMORY_AVAILABLE,
71
+ callbacks=[partial(self._collect_metric, environment,
72
+ application_name, check_and_record, "memory_available")],
73
+ description="GPU Memory Available",
74
+ )
75
+ meter.create_observable_gauge(
76
+ name=SemanticConvetion.GPU_MEMORY_TOTAL,
77
+ callbacks=[partial(self._collect_metric, environment,
78
+ application_name, check_and_record, "memory_total")],
79
+ description="GPU Memory Total",
80
+ )
81
+ meter.create_observable_gauge(
82
+ name=SemanticConvetion.GPU_MEMORY_USED,
83
+ callbacks=[partial(self._collect_metric, environment,
84
+ application_name, check_and_record, "memory_used")],
85
+ description="GPU Memory Used",
86
+ )
87
+ meter.create_observable_gauge(
88
+ name=SemanticConvetion.GPU_MEMORY_FREE,
89
+ callbacks=[partial(self._collect_metric, environment,
90
+ application_name, check_and_record, "memory_free")],
91
+ description="GPU Memory Free",
92
+ )
93
+ meter.create_observable_gauge(
94
+ name=SemanticConvetion.GPU_POWER_DRAW,
95
+ callbacks=[partial(self._collect_metric, environment,
96
+ application_name, check_and_record, "power_draw")],
97
+ description="GPU Power Draw",
98
+ )
99
+ meter.create_observable_gauge(
100
+ name=SemanticConvetion.GPU_POWER_LIMIT,
101
+ callbacks=[partial(self._collect_metric, environment,
102
+ application_name, check_and_record, "power_limit")],
103
+ description="GPU Power Limit",
104
+ )
105
+
106
+ def _uninstrument(self, **kwargs):
107
+ # Proper uninstrumentation logic to revert patched methods
108
+ pass
109
+
110
+ def _collect_metric(self, environment, application_name,
111
+ check_and_record, metric_name,
112
+ options: CallbackOptions) -> Iterable[Observation]:
113
+
114
+ import gpustat
115
+
116
+ try:
117
+ gpu_stats = gpustat.GPUStatCollection.new_query()
118
+
119
+ for gpu in gpu_stats.gpus:
120
+ attributes = {
121
+ TELEMETRY_SDK_NAME: "openlit",
122
+ SemanticConvetion.GEN_AI_APPLICATION_NAME: application_name,
123
+ SemanticConvetion.GEN_AI_ENVIRONMENT: environment,
124
+ SemanticConvetion.GPU_INDEX: gpu.index,
125
+ SemanticConvetion.GPU_UUID: gpu.uuid,
126
+ SemanticConvetion.GPU_NAME: gpu.name,
127
+ }
128
+
129
+ yield Observation(check_and_record(getattr(gpu, metric_name, 0)), attributes)
130
+
131
+ except Exception as e:
132
+ logger.error("Error in GPU metrics collection: %s", e)
@@ -268,7 +268,7 @@ def async_chat(gen_ai_endpoint, version, environment, application_name,
268
268
  else:
269
269
  i = 0
270
270
  while i < kwargs["n"] and trace_content is True:
271
- attribute_name = f"gen_ai.content.completion.{i}"
271
+ attribute_name = f"gen_ai.completion.{i}"
272
272
  span.set_attribute(attribute_name,
273
273
  response.choices[i].message.content)
274
274
  i += 1
@@ -268,7 +268,7 @@ def chat(gen_ai_endpoint, version, environment, application_name,
268
268
  else:
269
269
  i = 0
270
270
  while i < kwargs["n"] and trace_content is True:
271
- attribute_name = f"gen_ai.content.completion.{i}"
271
+ attribute_name = f"gen_ai.completion.{i}"
272
272
  span.set_attribute(attribute_name,
273
273
  response.choices[i].message.content)
274
274
  i += 1
@@ -269,7 +269,7 @@ def azure_async_chat_completions(gen_ai_endpoint, version, environment, applicat
269
269
  else:
270
270
  i = 0
271
271
  while i < kwargs["n"] and trace_content is True:
272
- attribute_name = f"gen_ai.content.completion.{i}"
272
+ attribute_name = f"gen_ai.completion.{i}"
273
273
  span.set_attribute(attribute_name,
274
274
  response.choices[i].message.content)
275
275
  i += 1
@@ -550,7 +550,7 @@ def azure_async_completions(gen_ai_endpoint, version, environment, application_n
550
550
  else:
551
551
  i = 0
552
552
  while i < kwargs["n"] and trace_content is True:
553
- attribute_name = f"gen_ai.content.completion.{i}"
553
+ attribute_name = f"gen_ai.completion.{i}"
554
554
  span.set_attribute(attribute_name,
555
555
  response.choices[i].text)
556
556
  i += 1
@@ -273,7 +273,7 @@ def async_chat_completions(gen_ai_endpoint, version, environment, application_na
273
273
  else:
274
274
  i = 0
275
275
  while i < kwargs["n"] and trace_content is True:
276
- attribute_name = f"gen_ai.content.completion.{i}"
276
+ attribute_name = f"gen_ai.completion.{i}"
277
277
  span.set_attribute(attribute_name,
278
278
  response.choices[i].message.content)
279
279
  i += 1
@@ -269,7 +269,7 @@ def azure_chat_completions(gen_ai_endpoint, version, environment, application_na
269
269
  else:
270
270
  i = 0
271
271
  while i < kwargs["n"] and trace_content is True:
272
- attribute_name = f"gen_ai.content.completion.{i}"
272
+ attribute_name = f"gen_ai.completion.{i}"
273
273
  span.set_attribute(attribute_name,
274
274
  response.choices[i].message.content)
275
275
  i += 1
@@ -548,7 +548,7 @@ def azure_completions(gen_ai_endpoint, version, environment, application_name,
548
548
  else:
549
549
  i = 0
550
550
  while i < kwargs["n"] and trace_content is True:
551
- attribute_name = f"gen_ai.content.completion.{i}"
551
+ attribute_name = f"gen_ai.completion.{i}"
552
552
  span.set_attribute(attribute_name,
553
553
  response.choices[i].text)
554
554
  i += 1
@@ -272,7 +272,7 @@ def chat_completions(gen_ai_endpoint, version, environment, application_name,
272
272
  else:
273
273
  i = 0
274
274
  while i < kwargs["n"] and trace_content is True:
275
- attribute_name = f"gen_ai.content.completion.{i}"
275
+ attribute_name = f"gen_ai.completion.{i}"
276
276
  span.set_attribute(attribute_name,
277
277
  response.choices[i].message.content)
278
278
  i += 1
@@ -98,7 +98,7 @@ def text_wrap(gen_ai_endpoint, version, environment, application_name,
98
98
  completion_tokens = 0
99
99
  for completion in response:
100
100
  if len(response) > 1:
101
- attribute_name = f"gen_ai.content.completion.{i}"
101
+ attribute_name = f"gen_ai.completion.{i}"
102
102
  else:
103
103
  attribute_name = SemanticConvetion.GEN_AI_CONTENT_COMPLETION
104
104
  if i == 0:
@@ -21,7 +21,7 @@ class SemanticConvetion:
21
21
  GEN_AI_SYSTEM = "gen_ai.system"
22
22
  GEN_AI_ENVIRONMENT = "gen_ai.environment"
23
23
  GEN_AI_APPLICATION_NAME = "gen_ai.application_name"
24
- GEN_AI_TYPE = "gen_ai.type"
24
+ GEN_AI_TYPE = "gen_ai.operation.name"
25
25
  GEN_AI_HUB_OWNER = "gen_ai.hub.owner"
26
26
  GEN_AI_HUB_REPO = "gen_ai.hub.repo"
27
27
  GEN_AI_RETRIEVAL_SOURCE = "gen_ai.retrieval.source"
@@ -68,8 +68,8 @@ class SemanticConvetion:
68
68
  GEN_AI_RESPONSE_IMAGE_STYLE = "gen_ai.request.image_style"
69
69
 
70
70
  # GenAI Content
71
- GEN_AI_CONTENT_PROMPT = "gen_ai.content.prompt"
72
- GEN_AI_CONTENT_COMPLETION = "gen_ai.content.completion"
71
+ GEN_AI_CONTENT_PROMPT = "gen_ai.prompt"
72
+ GEN_AI_CONTENT_COMPLETION = "gen_ai.completion"
73
73
  GEN_AI_CONTENT_REVISED_PROMPT = "gen_ai.content.revised_prompt"
74
74
 
75
75
  # GenAI Evaluation Metrics
@@ -145,3 +145,20 @@ class SemanticConvetion:
145
145
  DB_SYSTEM_PINECONE = "pinecone"
146
146
  DB_SYSTEM_QDRANT = "qdrant"
147
147
  DB_SYSTEM_MILVUS = "milvus"
148
+
149
+ # GPU
150
+ GPU_INDEX = "gpu.index"
151
+ GPU_UUID = "gpu.uuid"
152
+ GPU_NAME = "gpu.name"
153
+
154
+ GPU_UTILIZATION = "gpu.utilization"
155
+ GPU_UTILIZATION_ENC = "gpu.enc.utilization"
156
+ GPU_UTILIZATION_DEC = "gpu.dec.utilization"
157
+ GPU_TEMPERATURE = "gpu.temperature"
158
+ GPU_FAN_SPEED = "gpu.fan_speed"
159
+ GPU_MEMORY_AVAILABLE = "gpu.memory.available"
160
+ GPU_MEMORY_TOTAL = "gpu.memory.total"
161
+ GPU_MEMORY_USED = "gpu.memory.used"
162
+ GPU_MEMORY_FREE = "gpu.memory.free"
163
+ GPU_POWER_DRAW = "gpu.power.draw"
164
+ GPU_POWER_LIMIT = "gpu.power.limit"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openlit
3
- Version: 1.11.0
3
+ Version: 1.14.0
4
4
  Summary: OpenTelemetry-native Auto instrumentation library for monitoring LLM Applications, facilitating the integration of observability into your GenAI-driven projects
5
5
  Home-page: https://github.com/openlit/openlit/tree/main/openlit/python
6
6
  Keywords: OpenTelemetry,otel,otlp,llm,tracing,openai,anthropic,claude,cohere,llm monitoring,observability,monitoring,gpt,Generative AI,chatGPT
@@ -14,11 +14,13 @@ Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Requires-Dist: boto3 (>=1.34.0,<2.0.0)
16
16
  Requires-Dist: botocore (>=1.34.0,<2.0.0)
17
+ Requires-Dist: gpustat (>=1.1.1,<2.0.0)
17
18
  Requires-Dist: opentelemetry-api (>=1.24.0,<2.0.0)
18
19
  Requires-Dist: opentelemetry-exporter-otlp (>=1.24.0,<2.0.0)
19
20
  Requires-Dist: opentelemetry-instrumentation (>=0.45b0,<0.46)
20
21
  Requires-Dist: opentelemetry-sdk (>=1.24.0,<2.0.0)
21
22
  Requires-Dist: requests (>=2.26.0,<3.0.0)
23
+ Requires-Dist: schedule (>=1.2.2,<2.0.0)
22
24
  Requires-Dist: tiktoken (>=0.6.0,<0.7.0)
23
25
  Project-URL: Repository, https://github.com/openlit/openlit/tree/main/openlit/python
24
26
  Description-Content-Type: text/markdown
@@ -36,7 +38,8 @@ OpenTelemetry Auto-Instrumentation for GenAI & LLM Applications</h1>
36
38
  [![GitHub Contributors](https://img.shields.io/github/contributors/openlit/openlit)](https://github.com/openlit/openlit/graphs/contributors)
37
39
 
38
40
  [![Slack](https://img.shields.io/badge/Slack-4A154B?logo=slack&logoColor=white)](https://join.slack.com/t/openlit/shared_invite/zt-2etnfttwg-TjP_7BZXfYg84oAukY8QRQ)
39
- [![X](https://img.shields.io/badge/follow-%40OpenLIT-1DA1F2?logo=x&style=social)](https://twitter.com/openlit_io)
41
+ [![Discord](https://img.shields.io/badge/Discord-7289DA?logo=discord&logoColor=white)](https://discord.gg/rjvTm6zd)
42
+ [![X](https://img.shields.io/badge/follow-%40openlit__io-1DA1F2?logo=x&style=social)](https://twitter.com/openlit_io)
40
43
 
41
44
  ![OpenLIT Connections Banner](https://github.com/openlit/.github/blob/main/profile/assets/github-readme-connections-banner.png?raw=true)
42
45
 
@@ -70,8 +73,9 @@ This project adheres to the [Semantic Conventions](https://github.com/open-telem
70
73
  - [✅ Prometheus + Tempo](https://docs.openlit.io/latest/connections/prometheus-tempo)
71
74
  - [✅ Prometheus + Jaeger](https://docs.openlit.io/latest/connections/prometheus-jaeger)
72
75
  - [✅ Grafana Cloud](https://docs.openlit.io/latest/connections/grafanacloud)
73
- - [✅ DataDog](https://docs.openlit.io/latest/connections/datadog)
74
76
  - [✅ New Relic](https://docs.openlit.io/latest/connections/new-relic)
77
+ - [✅ Elastic](https://docs.openlit.io/latest/connections/elastic)
78
+ - [✅ DataDog](https://docs.openlit.io/latest/connections/datadog)
75
79
  - [✅ SigNoz](https://docs.openlit.io/latest/connections/signoz)
76
80
  - [✅ Dynatrace](https://docs.openlit.io/latest/connections/dynatrace)
77
81
  - [✅ OpenObserve](https://docs.openlit.io/latest/connections/openobserve)
@@ -183,6 +187,7 @@ Below is a detailed overview of the configuration options available, allowing yo
183
187
  | `disabled_instrumentors`| List of instrumentors to disable. | `None` | No |
184
188
  | `disable_metrics` | If set, disables the collection of metrics. | `False` | No |
185
189
  | `pricing_json` | URL or file path of the pricing JSON file. | `https://github.com/openlit/openlit/blob/main/assets/pricing.json` | No |
190
+ | `collect_gpu_stats` | Flag to enable or disable GPU metrics collection. | `False` | No |
186
191
 
187
192
  ## 🌱 Contributing
188
193
 
@@ -190,7 +195,7 @@ Whether it's big or small, we love contributions 💚. Check out our [Contributi
190
195
 
191
196
  Unsure where to start? Here are a few ways to get involved:
192
197
 
193
- - Join our [Slack channel](https://join.slack.com/t/openlit/shared_invite/zt-2etnfttwg-TjP_7BZXfYg84oAukY8QRQ) to discuss ideas, share feedback, and connect with both our team and the wider OpenLIT community.
198
+ - Join our [Slack](https://join.slack.com/t/openlit/shared_invite/zt-2etnfttwg-TjP_7BZXfYg84oAukY8QRQ) or [Discord](https://discord.gg/rjvTm6zd) community to discuss ideas, share feedback, and connect with both our team and the wider OpenLIT community.
194
199
 
195
200
  Your input helps us grow and improve, and we're here to support you every step of the way.
196
201
 
@@ -199,7 +204,7 @@ Your input helps us grow and improve, and we're here to support you every step o
199
204
  Connect with the OpenLIT community and maintainers for support, discussions, and updates:
200
205
 
201
206
  - 🌟 If you like it, Leave a star on our [GitHub](https://github.com/openlit/openlit/)
202
- - 🌍 Join our [Slack](https://join.slack.com/t/openlit/shared_invite/zt-2etnfttwg-TjP_7BZXfYg84oAukY8QRQ) Community for live interactions and questions.
207
+ - 🌍 Join our [Slack](https://join.slack.com/t/openlit/shared_invite/zt-2etnfttwg-TjP_7BZXfYg84oAukY8QRQ) or [Discord](https://discord.gg/rjvTm6zd) community for live interactions and questions.
203
208
  - 🐞 Report bugs on our [GitHub Issues](https://github.com/openlit/openlit/issues) to help us improve OpenLIT.
204
209
  - 𝕏 Follow us on [X](https://x.com/openlit_io) for the latest updates and news.
205
210
 
@@ -1,5 +1,5 @@
1
1
  openlit/__helpers.py,sha256=lrn4PBs9owDudiCY2NBoVbAi7AU_HtUpyOj0oqPBsPY,5545
2
- openlit/__init__.py,sha256=uW32Zg5R6NK3qqy3rfQhUnFi_YfvhnM4TFJSLo6Yr54,10439
2
+ openlit/__init__.py,sha256=1CB3rIWpEzhc330JtZ7HxZ77bZfX4DEUtiubOQivXk0,14841
3
3
  openlit/instrumentation/anthropic/__init__.py,sha256=oaU53BOPyfUKbEzYvLr1DPymDluurSnwo4Hernf2XdU,1955
4
4
  openlit/instrumentation/anthropic/anthropic.py,sha256=CYBui5eEfWdSfFF0xtCQjh1xO-gCVJc_V9Hli0szVZE,16026
5
5
  openlit/instrumentation/anthropic/async_anthropic.py,sha256=NW84kTQ3BkUx1zZuMRps_J7zTYkmq5BxOrqSjqWInBs,16068
@@ -13,9 +13,10 @@ openlit/instrumentation/embedchain/__init__.py,sha256=8TYk1OEbz46yF19dr-gB_x80VZ
13
13
  openlit/instrumentation/embedchain/embedchain.py,sha256=SLlr7qieT3kp4M6OYSRy8FaVCXQ2t3oPyIiE99ioNE4,7892
14
14
  openlit/instrumentation/gpt4all/__init__.py,sha256=-59CP2B3-HGZJ_vC-fI9Dt-0BuQXRhSCWCjnaGeU15Q,1802
15
15
  openlit/instrumentation/gpt4all/gpt4all.py,sha256=iDu8CAat4j5VPAlhIdkGOclZvhFPG-u7zKwadsKeJps,17948
16
+ openlit/instrumentation/gpu/__init__.py,sha256=Dj2MLar0DB20-t6W3pfR-3jfR_mwg4SYwhzIrH_n9sU,5596
16
17
  openlit/instrumentation/groq/__init__.py,sha256=uW_0G6HSanQyK2dIXYhzR604pDiyPQfybzc37DsfSew,1911
17
- openlit/instrumentation/groq/async_groq.py,sha256=WQwHpC-NJoyEf-jAJlxEcdnpd5jmlfAsDtEBRJ47CxA,19084
18
- openlit/instrumentation/groq/groq.py,sha256=4uiEFUjxJ0q-c3GlgPAMc4NijG1YLgQp7o3wcwFrxeg,19048
18
+ openlit/instrumentation/groq/async_groq.py,sha256=aOwgoUrEqIgLSlnAtJnaGIF8T_LUlpTnOzPNBIUwez4,19076
19
+ openlit/instrumentation/groq/groq.py,sha256=iMh4TPwBEJ7Eg6Gi4x6KYpELtQKDXIsgLrh6kQHVkHc,19040
19
20
  openlit/instrumentation/haystack/__init__.py,sha256=QK6XxxZUHX8vMv2Crk7rNBOc64iOOBLhJGL_lPlAZ8s,1758
20
21
  openlit/instrumentation/haystack/haystack.py,sha256=oQIZiDhdp3gnJnhYQ1OouJMc9YT0pQ-_31cmNuopa68,3891
21
22
  openlit/instrumentation/langchain/__init__.py,sha256=TW1ZR7I1i9Oig-wDWp3j1gmtQFO76jNBXQRBGGKzoOo,2531
@@ -31,23 +32,23 @@ openlit/instrumentation/ollama/__init__.py,sha256=cOax8PiypDuo_FC4WvDCYBRo7lH5nV
31
32
  openlit/instrumentation/ollama/async_ollama.py,sha256=ESk1zZTj2hPmkWIH5F2owuoo0apleDSSx5VORlO3e3w,28991
32
33
  openlit/instrumentation/ollama/ollama.py,sha256=PLGF9RB3TRNZ9GSGqeGVvKFBtgUK8Hc8xwvk-3NPeGI,28901
33
34
  openlit/instrumentation/openai/__init__.py,sha256=AZ2cPr3TMKkgGdMl_yXMeSi7bWhtmMqOW1iHdzHHGHA,16265
34
- openlit/instrumentation/openai/async_azure_openai.py,sha256=QE_5KHaCHAndkf7Y2Iq66mZUc0I1qtqIJ6iYPnwiuXA,46297
35
- openlit/instrumentation/openai/async_openai.py,sha256=qfJG_gIkSz3Gjau0zQ_G3tvkqkOd-md5LBK6wIjvH0U,45841
36
- openlit/instrumentation/openai/azure_openai.py,sha256=8nm1hsGdWLhJt97fkV254_biYdGeVJiZP2_Yb3pKSEU,46091
37
- openlit/instrumentation/openai/openai.py,sha256=VVl0fuQfxitH-V4hVeP5VxB31-yWMI74Xz4katlsG78,46522
35
+ openlit/instrumentation/openai/async_azure_openai.py,sha256=Lkclj_EraztqBpuYldDMwhqApa0iUb1s5gcUlgkwMkA,46281
36
+ openlit/instrumentation/openai/async_openai.py,sha256=KtY_nGbUjDXE4jU3udGT51XbV-FVJwPMj8uoHfiAvi8,45833
37
+ openlit/instrumentation/openai/azure_openai.py,sha256=q1o2tnxOY5Abm3YV7cNqkgLJPNzIxlETZ2gET6FRdxI,46075
38
+ openlit/instrumentation/openai/openai.py,sha256=kTGe7BjByIVRSWEALwFc1D3ZYLioTmKlZ4m76luupoQ,46514
38
39
  openlit/instrumentation/pinecone/__init__.py,sha256=Mv9bElqNs07_JQkYyNnO0wOM3hdbprmw7sttdMeKC7g,2526
39
40
  openlit/instrumentation/pinecone/pinecone.py,sha256=0EhLmtOuvwWVvAKh3e56wyd8wzQq1oaLOmF15SVHxVE,8765
40
41
  openlit/instrumentation/qdrant/__init__.py,sha256=OJIg17-IGmBEvBYVKjCHcJ0hFXuEL7XV_jzUTqkolN8,4799
41
42
  openlit/instrumentation/qdrant/qdrant.py,sha256=4uHKYGvWQtRAEVLUWo3o4joJw7hFm2NxVuBu5YKZKiI,14456
42
43
  openlit/instrumentation/transformers/__init__.py,sha256=9-KLjq-aPTh13gTBYsWltV6hokGwt3mP4759SwsaaCk,1478
43
- openlit/instrumentation/transformers/transformers.py,sha256=peT0BGskYt7AZ0b93TZ7qECXfZRgDQMasUeamexYdZI,7592
44
+ openlit/instrumentation/transformers/transformers.py,sha256=Kh7WlEDT4ZNGQTMO8V-eYCc45nj-OPrkXXN-Ss4V5no,7584
44
45
  openlit/instrumentation/vertexai/__init__.py,sha256=N3E9HtzefD-zC0fvmfGYiDmSqssoavp_i59wfuYLyMw,6079
45
46
  openlit/instrumentation/vertexai/async_vertexai.py,sha256=PMHYyLf1J4gZpC_-KZ_ZVx1xIHhZDJSNa7mrjNXZ5M0,52372
46
47
  openlit/instrumentation/vertexai/vertexai.py,sha256=UvpNKBHPoV9idVMfGigZnmWuEQiyqSwZn0zK9-U7Lzw,52125
47
48
  openlit/otel/metrics.py,sha256=O7NoaDz0bY19mqpE4-0PcKwEe-B-iJFRgOCaanAuZAc,4291
48
49
  openlit/otel/tracing.py,sha256=vL1ifMbARPBpqK--yXYsCM6y5dSu5LFIKqkhZXtYmUc,3712
49
- openlit/semcov/__init__.py,sha256=6t5P_0_oS4TtorvKsfLtCQchO0HtIzTenxSye_F4G2Y,6687
50
- openlit-1.11.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
51
- openlit-1.11.0.dist-info/METADATA,sha256=EAwsft48mdWV1fOxy_XghH1H1rnvhdTOpIrvKviIXSE,13055
52
- openlit-1.11.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
53
- openlit-1.11.0.dist-info/RECORD,,
50
+ openlit/semcov/__init__.py,sha256=LgMVOQj_9DA9maxZLlcVM3Vfvt3dBL8yXMA0aWVkh9A,7235
51
+ openlit-1.14.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
52
+ openlit-1.14.0.dist-info/METADATA,sha256=PrevJMeTAaGTYwG2Wiq7pkHsKUQV97aMaDDh-pPN3W4,13563
53
+ openlit-1.14.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
54
+ openlit-1.14.0.dist-info/RECORD,,