openlit 1.34.27__py3-none-any.whl → 1.34.29__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 (33) hide show
  1. openlit/__helpers.py +38 -0
  2. openlit/__init__.py +22 -155
  3. openlit/_instrumentors.py +144 -0
  4. openlit/guard/all.py +3 -3
  5. openlit/instrumentation/chroma/utils.py +2 -2
  6. openlit/instrumentation/controlflow/controlflow.py +2 -2
  7. openlit/instrumentation/embedchain/embedchain.py +4 -4
  8. openlit/instrumentation/groq/__init__.py +4 -4
  9. openlit/instrumentation/haystack/__init__.py +57 -28
  10. openlit/instrumentation/haystack/async_haystack.py +54 -0
  11. openlit/instrumentation/haystack/haystack.py +35 -65
  12. openlit/instrumentation/haystack/utils.py +377 -0
  13. openlit/instrumentation/julep/async_julep.py +2 -2
  14. openlit/instrumentation/julep/julep.py +2 -2
  15. openlit/instrumentation/langchain_community/utils.py +2 -2
  16. openlit/instrumentation/llamaindex/__init__.py +165 -37
  17. openlit/instrumentation/llamaindex/async_llamaindex.py +53 -0
  18. openlit/instrumentation/llamaindex/llamaindex.py +32 -64
  19. openlit/instrumentation/llamaindex/utils.py +412 -0
  20. openlit/instrumentation/mem0/mem0.py +2 -2
  21. openlit/instrumentation/openai/__init__.py +24 -24
  22. openlit/instrumentation/openai/utils.py +66 -27
  23. openlit/instrumentation/openai_agents/__init__.py +46 -26
  24. openlit/instrumentation/openai_agents/processor.py +600 -0
  25. openlit/instrumentation/pinecone/utils.py +2 -2
  26. openlit/instrumentation/qdrant/utils.py +2 -2
  27. openlit/instrumentation/together/__init__.py +8 -8
  28. openlit/semcov/__init__.py +80 -0
  29. {openlit-1.34.27.dist-info → openlit-1.34.29.dist-info}/METADATA +2 -1
  30. {openlit-1.34.27.dist-info → openlit-1.34.29.dist-info}/RECORD +32 -27
  31. openlit/instrumentation/openai_agents/openai_agents.py +0 -65
  32. {openlit-1.34.27.dist-info → openlit-1.34.29.dist-info}/LICENSE +0 -0
  33. {openlit-1.34.27.dist-info → openlit-1.34.29.dist-info}/WHEEL +0 -0
@@ -22,6 +22,14 @@ from openlit.__helpers import (
22
22
  )
23
23
  from openlit.semcov import SemanticConvention
24
24
 
25
+ def handle_not_given(value, default=None):
26
+ """
27
+ Handle OpenAI's NotGiven values by converting them to appropriate defaults.
28
+ """
29
+ if hasattr(value, '__class__') and value.__class__.__name__ == 'NotGiven':
30
+ return default
31
+ return value
32
+
25
33
  def format_content(messages):
26
34
  """
27
35
  Format the messages into a string for span events.
@@ -37,9 +45,15 @@ def format_content(messages):
37
45
 
38
46
  # Handle list of messages
39
47
  formatted_messages = []
48
+
40
49
  for message in messages:
41
- role = message.get("role", "user")
42
- content = message.get("content", "")
50
+ try:
51
+ role = message.get("role", "user") or message.role
52
+ content = message.get("content", "") or message.content
53
+
54
+ except:
55
+ role = "user"
56
+ content = str(messages)
43
57
 
44
58
  if isinstance(content, list):
45
59
  content_str_list = []
@@ -242,9 +256,15 @@ def common_response_logic(scope, pricing_info, environment, application_name, me
242
256
  environment, application_name, is_stream, scope._tbt, scope._ttft, version)
243
257
 
244
258
  # Span Attributes for Request parameters specific to responses API
245
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, scope._kwargs.get("temperature", 1.0))
246
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_P, scope._kwargs.get("top_p", 1.0))
247
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS, scope._kwargs.get("max_output_tokens", -1))
259
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, handle_not_given(scope._kwargs.get("temperature"), 1.0))
260
+ scope._span.set_attribute(
261
+ SemanticConvention.GEN_AI_REQUEST_TOP_P,
262
+ handle_not_given(scope._kwargs.get("top_p"), 1.0)
263
+ )
264
+ scope._span.set_attribute(
265
+ SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS,
266
+ handle_not_given(scope._kwargs.get("max_output_tokens"), -1)
267
+ )
248
268
 
249
269
  # Reasoning parameters
250
270
  reasoning = scope._kwargs.get("reasoning", {})
@@ -421,20 +441,30 @@ def common_chat_logic(scope, pricing_info, environment, application_name, metric
421
441
  cost = get_chat_model_cost(request_model, pricing_info, input_tokens, output_tokens)
422
442
 
423
443
  # Common Span Attributes
424
- common_span_attributes(scope,
425
- SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_OPENAI,
426
- scope._server_address, scope._server_port, request_model, scope._response_model,
427
- environment, application_name, is_stream, scope._tbt, scope._ttft, version)
444
+ common_span_attributes(
445
+ scope,
446
+ SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
447
+ SemanticConvention.GEN_AI_SYSTEM_OPENAI,
448
+ scope._server_address, scope._server_port, request_model,
449
+ scope._response_model, environment, application_name,
450
+ is_stream, scope._tbt, scope._ttft, version
451
+ )
428
452
 
429
453
  # Span Attributes for Request parameters
430
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SEED, str(scope._kwargs.get("seed", "")))
431
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_FREQUENCY_PENALTY, scope._kwargs.get("frequency_penalty", 0.0))
432
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS, scope._kwargs.get("max_tokens", -1))
433
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_PRESENCE_PENALTY, scope._kwargs.get("presence_penalty", 0.0))
434
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_STOP_SEQUENCES, scope._kwargs.get("stop", []))
435
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, scope._kwargs.get("temperature", 1.0))
436
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_P, scope._kwargs.get("top_p", 1.0))
437
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_USER, scope._kwargs.get("user", ""))
454
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SEED, str(handle_not_given(scope._kwargs.get("seed"), "")))
455
+ scope._span.set_attribute(
456
+ SemanticConvention.GEN_AI_REQUEST_FREQUENCY_PENALTY,
457
+ handle_not_given(scope._kwargs.get("frequency_penalty"), 0.0)
458
+ )
459
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS, handle_not_given(scope._kwargs.get("max_tokens"), -1))
460
+ scope._span.set_attribute(
461
+ SemanticConvention.GEN_AI_REQUEST_PRESENCE_PENALTY,
462
+ handle_not_given(scope._kwargs.get("presence_penalty"), 0.0)
463
+ )
464
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_STOP_SEQUENCES, handle_not_given(scope._kwargs.get("stop"), []))
465
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, handle_not_given(scope._kwargs.get("temperature"), 1.0))
466
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_P, handle_not_given(scope._kwargs.get("top_p"), 1.0))
467
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_USER, handle_not_given(scope._kwargs.get("user"), ""))
438
468
 
439
469
  # Span Attributes for Response parameters
440
470
  scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_ID, scope._response_id)
@@ -442,9 +472,9 @@ def common_chat_logic(scope, pricing_info, environment, application_name, metric
442
472
  scope._span.set_attribute(SemanticConvention.GEN_AI_OUTPUT_TYPE, "text" if isinstance(scope._llmresponse, str) else "json")
443
473
 
444
474
  # OpenAI-specific attributes
445
- if hasattr(scope, "_system_fingerprint"):
475
+ if hasattr(scope, "_system_fingerprint") and scope._system_fingerprint:
446
476
  scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_SYSTEM_FINGERPRINT, scope._system_fingerprint)
447
- if hasattr(scope, "_service_tier"):
477
+ if hasattr(scope, "_service_tier") and scope._service_tier:
448
478
  scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SERVICE_TIER, scope._service_tier)
449
479
 
450
480
  # Span Attributes for Tools - optimized
@@ -565,8 +595,11 @@ def common_embedding_logic(scope, request_model, pricing_info, environment, appl
565
595
  environment, application_name, False, scope._tbt, scope._ttft, version)
566
596
 
567
597
  # Span Attributes for Request parameters
568
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_ENCODING_FORMATS, [scope._kwargs.get("encoding_format", "float")])
569
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_USER, scope._kwargs.get("user", ""))
598
+ scope._span.set_attribute(
599
+ SemanticConvention.GEN_AI_REQUEST_ENCODING_FORMATS,
600
+ [handle_not_given(scope._kwargs.get("encoding_format"), "float")]
601
+ )
602
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_USER, handle_not_given(scope._kwargs.get("user"), ""))
570
603
 
571
604
  # Span Attributes for Cost and Tokens
572
605
  scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens)
@@ -605,9 +638,12 @@ def common_image_logic(scope, request_model, pricing_info, environment, applicat
605
638
  environment, application_name, False, scope._tbt, scope._ttft, version)
606
639
 
607
640
  # Span Attributes for Request parameters
608
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_IMAGE_SIZE, scope._kwargs.get("size", "1024x1024"))
609
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_IMAGE_QUALITY, scope._kwargs.get("quality", "standard"))
610
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_USER, scope._kwargs.get("user", ""))
641
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_IMAGE_SIZE, handle_not_given(scope._kwargs.get("size"), "1024x1024"))
642
+ scope._span.set_attribute(
643
+ SemanticConvention.GEN_AI_REQUEST_IMAGE_QUALITY,
644
+ handle_not_given(scope._kwargs.get("quality"), "standard")
645
+ )
646
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_USER, handle_not_given(scope._kwargs.get("user"), ""))
611
647
 
612
648
  # Extract response data
613
649
  response_dict = scope._response_dict
@@ -703,9 +739,12 @@ def common_audio_logic(scope, request_model, pricing_info, environment, applicat
703
739
  environment, application_name, False, scope._tbt, scope._ttft, version)
704
740
 
705
741
  # Span Attributes for Request parameters
706
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_AUDIO_VOICE, scope._kwargs.get("voice", "alloy"))
707
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_AUDIO_RESPONSE_FORMAT, scope._kwargs.get("response_format", "mp3"))
708
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_AUDIO_SPEED, scope._kwargs.get("speed", 1.0))
742
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_AUDIO_VOICE, handle_not_given(scope._kwargs.get("voice"), "alloy"))
743
+ scope._span.set_attribute(
744
+ SemanticConvention.GEN_AI_REQUEST_AUDIO_RESPONSE_FORMAT,
745
+ handle_not_given(scope._kwargs.get("response_format"), "mp3")
746
+ )
747
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_AUDIO_SPEED, handle_not_given(scope._kwargs.get("speed"), 1.0))
709
748
 
710
749
  # Span Attributes for Cost
711
750
  scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
@@ -1,42 +1,62 @@
1
- """Initializer of Auto Instrumentation of OpenAI Agents Functions"""
1
+ """
2
+ OpenLIT OpenAI Agents Instrumentation - Native Tracing Integration
3
+ """
2
4
 
3
5
  from typing import Collection
4
6
  import importlib.metadata
5
7
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
6
- from wrapt import wrap_function_wrapper
7
8
 
8
- from openlit.instrumentation.openai_agents.openai_agents import (
9
- create_agent
10
- )
9
+ from openlit.instrumentation.openai_agents.processor import OpenLITTracingProcessor
11
10
 
12
- _instruments = ('openai-agents >= 0.0.3',)
11
+ _instruments = ("openai-agents >= 0.0.3",)
13
12
 
14
13
  class OpenAIAgentsInstrumentor(BaseInstrumentor):
15
- """
16
- An instrumentor for openai-agents's client library.
17
- """
14
+ """OpenLIT instrumentor for OpenAI Agents using native tracing system"""
18
15
 
19
16
  def instrumentation_dependencies(self) -> Collection[str]:
20
17
  return _instruments
21
18
 
22
19
  def _instrument(self, **kwargs):
23
- application_name = kwargs.get('application_name', 'default')
24
- environment = kwargs.get('environment', 'default')
25
- tracer = kwargs.get('tracer')
26
- event_provider = kwargs.get('event_provider')
27
- metrics = kwargs.get('metrics_dict')
28
- pricing_info = kwargs.get('pricing_info', {})
29
- capture_message_content = kwargs.get('capture_message_content', False)
30
- disable_metrics = kwargs.get('disable_metrics')
31
- version = importlib.metadata.version('openai-agents')
32
-
33
- wrap_function_wrapper(
34
- 'agents.agent',
35
- 'Agent.__init__',
36
- create_agent(version, environment, application_name,
37
- tracer, event_provider, pricing_info, capture_message_content, metrics, disable_metrics),
20
+ version = importlib.metadata.version("openai-agents")
21
+ environment = kwargs.get("environment", "default")
22
+ application_name = kwargs.get("application_name", "default")
23
+ tracer = kwargs.get("tracer")
24
+ pricing_info = kwargs.get("pricing_info", {})
25
+ capture_message_content = kwargs.get("capture_message_content", False)
26
+ metrics = kwargs.get("metrics_dict")
27
+ disable_metrics = kwargs.get("disable_metrics")
28
+ detailed_tracing = kwargs.get("detailed_tracing", False)
29
+
30
+ # Create our processor with OpenLIT enhancements
31
+ processor = OpenLITTracingProcessor(
32
+ tracer=tracer,
33
+ version=version,
34
+ environment=environment,
35
+ application_name=application_name,
36
+ pricing_info=pricing_info,
37
+ capture_message_content=capture_message_content,
38
+ metrics=metrics,
39
+ disable_metrics=disable_metrics,
40
+ detailed_tracing=detailed_tracing
38
41
  )
39
42
 
43
+ # Integrate with OpenAI Agents' native tracing system
44
+ try:
45
+ from agents import set_trace_processors
46
+ # Replace existing processors with our enhanced processor
47
+ set_trace_processors([processor])
48
+ except ImportError:
49
+ # Fallback: Add our processor to existing ones
50
+ try:
51
+ from agents import add_trace_processor
52
+ add_trace_processor(processor)
53
+ except ImportError:
54
+ pass # Agents package may not have tracing
55
+
40
56
  def _uninstrument(self, **kwargs):
41
- # Proper uninstrumentation logic to revert patched methods
42
- pass
57
+ # Clear our processors
58
+ try:
59
+ from agents import set_trace_processors
60
+ set_trace_processors([])
61
+ except ImportError:
62
+ pass