4
4
import logging
5
5
from pathlib import Path
6
6
import time
7
- from typing import Any , Dict , Optional , Union , List
7
+ from datetime import datetime
8
+ from typing import Any , Dict , Optional , Union , List , TYPE_CHECKING
8
9
9
10
from ..tracing import tracer , steps , enums
10
11
12
+ if TYPE_CHECKING :
13
+ try :
14
+ from agents import tracing # type: ignore[import]
15
+ except ImportError :
16
+ # When agents isn't available, we'll use string literals for type annotations
17
+ pass
18
+
11
19
try :
12
20
from agents import tracing # type: ignore[import]
13
-
14
21
HAVE_AGENTS = True
15
22
except ImportError :
16
23
HAVE_AGENTS = False
24
+ tracing = None # type: ignore[assignment]
17
25
18
26
logger = logging .getLogger (__name__ )
19
27
@@ -582,7 +590,14 @@ def _configure_chat_completion_step(
582
590
step .model_parameters = model_parameters or {}
583
591
584
592
585
- class OpenlayerTracerProcessor (tracing .TracingProcessor ): # type: ignore[no-redef]
593
+ # Dynamic base class to handle inheritance when agents is available
594
+ if HAVE_AGENTS :
595
+ _BaseProcessor = tracing .TracingProcessor # type: ignore[misc]
596
+ else :
597
+ _BaseProcessor = object # type: ignore[assignment,misc]
598
+
599
+
600
+ class OpenlayerTracerProcessor (_BaseProcessor ): # type: ignore[misc]
586
601
"""Tracing processor for the `OpenAI Agents SDK
587
602
<https://openai.github.io/openai-agents-python/>`_.
588
603
@@ -649,6 +664,12 @@ def __init__(self, **kwargs: Any) -> None:
649
664
Args:
650
665
**kwargs: Additional metadata to associate with all traces.
651
666
"""
667
+ if not HAVE_AGENTS :
668
+ raise ImportError (
669
+ "The 'agents' library is required to use OpenlayerTracerProcessor. "
670
+ "Please install it with: pip install openai-agents"
671
+ )
672
+
652
673
self .metadata : Dict [str , Any ] = kwargs or {}
653
674
self ._active_traces : Dict [str , Dict [str , Any ]] = {}
654
675
self ._active_steps : Dict [str , steps .Step ] = {}
@@ -676,7 +697,7 @@ def __init__(self, **kwargs: Any) -> None:
676
697
global _active_openlayer_processor
677
698
_active_openlayer_processor = self
678
699
679
- def on_trace_start (self , trace : tracing .Trace ) -> None :
700
+ def on_trace_start (self , trace : " tracing.Trace" ) -> None :
680
701
"""Handle the start of a trace (root agent workflow)."""
681
702
try :
682
703
# Get trace information
@@ -693,7 +714,7 @@ def on_trace_start(self, trace: tracing.Trace) -> None:
693
714
except Exception as e :
694
715
logger .error (f"Failed to handle trace start: { e } " )
695
716
696
- def on_trace_end (self , trace : tracing .Trace ) -> None :
717
+ def on_trace_end (self , trace : " tracing.Trace" ) -> None :
697
718
"""Handle the end of a trace (root agent workflow)."""
698
719
try :
699
720
trace_data = self ._active_traces .pop (trace .trace_id , None )
@@ -786,7 +807,7 @@ def on_trace_end(self, trace: tracing.Trace) -> None:
786
807
except Exception as e :
787
808
logger .error (f"Failed to handle trace end: { e } " )
788
809
789
- def on_span_start (self , span : tracing .Span ) -> None :
810
+ def on_span_start (self , span : " tracing.Span" ) -> None :
790
811
"""Handle the start of a span (individual agent step)."""
791
812
try :
792
813
# Extract span attributes using helper function
@@ -840,7 +861,7 @@ def on_span_start(self, span: tracing.Span) -> None:
840
861
except Exception as e :
841
862
logger .error (f"Failed to handle span start: { e } " )
842
863
843
- def on_span_end (self , span : tracing .Span ) -> None :
864
+ def on_span_end (self , span : " tracing.Span" ) -> None :
844
865
"""Handle the end of a span (individual agent step)."""
845
866
try :
846
867
# Extract span attributes using helper function
@@ -912,7 +933,7 @@ def on_span_end(self, span: tracing.Span) -> None:
912
933
logger .error (f"Failed to handle span end: { e } " )
913
934
914
935
def _create_step_for_span (
915
- self , span : tracing .Span , span_data : Any
936
+ self , span : " tracing.Span" , span_data : Any
916
937
) -> Optional [steps .Step ]:
917
938
"""Create the appropriate Openlayer step for a span."""
918
939
try :
@@ -1315,7 +1336,7 @@ def _create_generic_step(
1315
1336
step .start_time = start_time
1316
1337
return step
1317
1338
1318
- def _extract_usage_from_response (self , response : Any , field : str = None ) -> int :
1339
+ def _extract_usage_from_response (self , response : Any , field : Optional [ str ] = None ) -> Union [ int , Dict [ str , int ]] :
1319
1340
"""Extract usage information from response object."""
1320
1341
if not response :
1321
1342
return 0
@@ -1339,7 +1360,7 @@ def _extract_usage_from_response(self, response: Any, field: str = None) -> int:
1339
1360
}
1340
1361
1341
1362
def _update_step_with_span_data (
1342
- self , step : steps .Step , span : tracing .Span , span_data : Any
1363
+ self , step : steps .Step , span : " tracing.Span" , span_data : Any
1343
1364
) -> None :
1344
1365
"""Update step with final span data."""
1345
1366
try :
@@ -1650,7 +1671,7 @@ def _extract_actual_llm_output(self, span_data: Any) -> Optional[str]:
1650
1671
except Exception :
1651
1672
return None
1652
1673
1653
- def _cleanup_dict_with_warning (self , dict_obj : Dict , name : str ) -> None :
1674
+ def _cleanup_dict_with_warning (self , dict_obj : Dict [ str , Any ] , name : str ) -> None :
1654
1675
"""Helper to clean up dictionaries with warning logging."""
1655
1676
if dict_obj :
1656
1677
dict_obj .clear ()
0 commit comments