Allow for tracing via context provider (#5889)

These changes allow for 2 important use-cases:
1. Add a span for tool calls which will enable tracing of all tool calls
in agent_chat
2. Allow runtimes to pick up global `tracer_providers` if they are
available. This is very helpful because it allows for nested teams/agent
to all use the same tracer.
---------

Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
This commit is contained in:
Eitan Yarmush 2025-03-11 19:33:39 -04:00 committed by GitHub
parent 817f728d04
commit 8fb9ca3a3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 16 additions and 6 deletions

View File

@ -1,7 +1,7 @@
import contextlib
from typing import Dict, Generic, Iterator, Optional
from opentelemetry.trace import NoOpTracerProvider, Span, SpanKind, TracerProvider
from opentelemetry.trace import NoOpTracerProvider, Span, SpanKind, TracerProvider, get_tracer_provider
from opentelemetry.util import types
from ._propagation import TelemetryMetadataContainer, get_telemetry_links
@ -22,9 +22,10 @@ class TraceHelper(Generic[Operation, Destination, ExtraAttributes]):
tracer_provider: TracerProvider | None,
instrumentation_builder_config: TracingConfig[Operation, Destination, ExtraAttributes],
) -> None:
self.tracer = (tracer_provider if tracer_provider else NoOpTracerProvider()).get_tracer(
f"autogen {instrumentation_builder_config.name}"
)
# Evaluate in order: first try tracer_provider param, then get_tracer_provider(), finally fallback to NoOp
# This allows for nested tracing with a default tracer provided by the user
self.tracer_provider = tracer_provider or get_tracer_provider() or NoOpTracerProvider()
self.tracer = self.tracer_provider.get_tracer(f"autogen {instrumentation_builder_config.name}")
self.instrumentation_builder_config = instrumentation_builder_config
@contextlib.contextmanager

View File

@ -5,6 +5,7 @@ from collections.abc import Sequence
from typing import Any, Dict, Generic, Mapping, Protocol, Type, TypedDict, TypeVar, cast, runtime_checkable
import jsonref
from opentelemetry.trace import get_tracer
from pydantic import BaseModel
from typing_extensions import NotRequired
@ -147,8 +148,16 @@ class BaseTool(ABC, Tool, Generic[ArgsT, ReturnT], ComponentBase[BaseModel]):
async def run(self, args: ArgsT, cancellation_token: CancellationToken) -> ReturnT: ...
async def run_json(self, args: Mapping[str, Any], cancellation_token: CancellationToken) -> Any:
# Execute the tool's run method
return_value = await self.run(self._args_type.model_validate(args), cancellation_token)
with get_tracer("base_tool").start_as_current_span(
self._name,
attributes={
"tool_name": self._name,
"tool_description": self._description,
"tool_args": json.dumps(args),
},
):
# Execute the tool's run method
return_value = await self.run(self._args_type.model_validate(args), cancellation_token)
# Log the tool call event
event = ToolCallEvent(