@@ -59,26 +59,58 @@ def internal_method(self):
5959import logging
6060
6161from collections .abc import Callable
62- from typing import Any , TypeAlias
62+ from typing import TYPE_CHECKING , Any
6363
64- from opentelemetry import trace
65- from opentelemetry .trace import SpanKind as _SpanKind
66- from opentelemetry .trace import StatusCode
6764
65+ if TYPE_CHECKING :
66+ from opentelemetry .trace import SpanKind as SpanKindType
67+ else :
68+ SpanKindType = object
6869
69- SpanKind : TypeAlias = _SpanKind
70+ logger = logging .getLogger (__name__ )
71+
72+ try :
73+ from opentelemetry import trace
74+ from opentelemetry .trace import SpanKind as _SpanKind
75+ from opentelemetry .trace import StatusCode
76+
77+ except ImportError :
78+ logger .debug (
79+ 'OpenTelemetry not found. Tracing will be disabled. '
80+ 'Install with: \' pip install "a2a-sdk[telemetry]"\' '
81+ )
82+
83+ class _NoOp :
84+ """A no-op object that absorbs all tracing calls when OpenTelemetry is not installed."""
85+
86+ def __call__ (self , * args : Any , ** kwargs : Any ) -> '_NoOp' :
87+ return self
88+
89+ def __enter__ (self ) -> '_NoOp' :
90+ return self
91+
92+ def __exit__ (self , * args : object , ** kwargs : Any ) -> None :
93+ pass
94+
95+ def __getattr__ (self , name : str ) -> '_NoOp' :
96+ return self
97+
98+ trace = _NoOp ()
99+ _SpanKind = _NoOp ()
100+ StatusCode = _NoOp ()
101+
102+ SpanKind = _SpanKind
70103__all__ = ['SpanKind' ]
104+
71105INSTRUMENTING_MODULE_NAME = 'a2a-python-sdk'
72106INSTRUMENTING_MODULE_VERSION = '1.0.0'
73107
74- logger = logging .getLogger (__name__ )
75-
76108
77109def trace_function ( # noqa: PLR0915
78110 func : Callable | None = None ,
79111 * ,
80112 span_name : str | None = None ,
81- kind : SpanKind = SpanKind .INTERNAL ,
113+ kind : SpanKindType = SpanKind .INTERNAL ,
82114 attributes : dict [str , Any ] | None = None ,
83115 attribute_extractor : Callable | None = None ,
84116) -> Callable :
@@ -225,7 +257,7 @@ def sync_wrapper(*args, **kwargs) -> Any:
225257def trace_class (
226258 include_list : list [str ] | None = None ,
227259 exclude_list : list [str ] | None = None ,
228- kind : SpanKind = SpanKind .INTERNAL ,
260+ kind : SpanKindType = SpanKind .INTERNAL ,
229261) -> Callable :
230262 """A class decorator to automatically trace specified methods of a class.
231263
@@ -280,22 +312,15 @@ def not_traced_method(self):
280312 exclude_list = exclude_list or []
281313
282314 def decorator (cls : Any ) -> Any :
283- all_methods = {}
284315 for name , method in inspect .getmembers (cls , inspect .isfunction ):
285- # Skip Dunders
286316 if name .startswith ('__' ) and name .endswith ('__' ):
287317 continue
288-
289- # Skip if include list is defined but the method not included.
290318 if include_list and name not in include_list :
291319 continue
292- # Skip if include list is not defined but the method is in excludes.
293320 if not include_list and name in exclude_list :
294321 continue
295322
296- all_methods [name ] = method
297323 span_name = f'{ cls .__module__ } .{ cls .__name__ } .{ name } '
298- # Set the decorator on the method.
299324 setattr (
300325 cls ,
301326 name ,
0 commit comments