Python: Improved telemetry setup (#421)

* test with stack and simplified names

* quick demo of agent decorator

* moved builder to protocol to enhance functionality

* undid chatclientAgent -> agent rename

* one more

* reverted AIAgent rename

* final reverts

* fixed foundry import

* revert changes

* streamlined otel and fcc decorators

* cleanup of telemetry

* further refinement

* lots of updates

* fixed typing

* fix for mypy

* added input and output atttributes

* fix import

* initial work on baking in otel

* major update to telemetry

* final fixes after rename

* fix

* fix test

* updated tests

* fix for tests

* fixes for tests

* updated based on comments

* removed agent decorator

* fix for Python: ServiceResponseException when using multiple tools
Fixes #649

* addressed comments

* fix tests

* fix tests

* fix tools tests

* fix for conversation_id in assistants client

* fix responses test

* fix tests and mypy

* updated test

* foundry fix

---------

Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
This commit is contained in:
Eduard van Valkenburg
2025-09-10 16:52:42 +02:00
committed by GitHub
Unverified
parent 6aa746d891
commit 82ca4065cb
45 changed files with 3246 additions and 2984 deletions
@@ -35,11 +35,11 @@ class WorkflowDiagnosticSettings(AFBaseSettings):
"""Settings for workflow tracing diagnostics."""
env_prefix: ClassVar[str] = "AGENT_FRAMEWORK_WORKFLOW_"
enable_otel_diagnostics: bool = False
enable_otel: bool = False
@property
def ENABLED(self) -> bool:
return self.enable_otel_diagnostics
return self.enable_otel
class WorkflowTracer:
+8 -11
View File
@@ -22,8 +22,8 @@ from agent_framework_workflow._workflow_context import WorkflowContext
@pytest.fixture
def tracing_enabled() -> Generator[None, None, None]:
"""Enable tracing for tests."""
original_value = os.environ.get("AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL_DIAGNOSTICS")
os.environ["AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL_DIAGNOSTICS"] = "true"
original_value = os.environ.get("AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL")
os.environ["AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL"] = "true"
# Force reload the settings to pick up the environment variable
from agent_framework_workflow._telemetry import WorkflowDiagnosticSettings
@@ -34,9 +34,9 @@ def tracing_enabled() -> Generator[None, None, None]:
# Restore original value
if original_value is None:
os.environ.pop("AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL_DIAGNOSTICS", None)
os.environ.pop("AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL", None)
else:
os.environ["AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL_DIAGNOSTICS"] = original_value
os.environ["AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL"] = original_value
# Reload settings again
workflow_tracer.settings = WorkflowDiagnosticSettings()
@@ -142,7 +142,6 @@ class FanInAggregator(Executor):
return self._processed_messages
@pytest.mark.asyncio
async def test_workflow_tracer_configuration() -> None:
"""Test that workflow tracer can be enabled and disabled."""
# Test disabled by default
@@ -150,8 +149,8 @@ async def test_workflow_tracer_configuration() -> None:
assert not tracer.enabled
# Test enabled with environment variable
original_value = os.environ.get("AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL_DIAGNOSTICS")
os.environ["AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL_DIAGNOSTICS"] = "true"
original_value = os.environ.get("AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL")
os.environ["AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL"] = "true"
# Force reload the settings to pick up the environment variable
from agent_framework_workflow._telemetry import WorkflowDiagnosticSettings
@@ -162,15 +161,14 @@ async def test_workflow_tracer_configuration() -> None:
# Restore original value
if original_value is None:
os.environ.pop("AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL_DIAGNOSTICS", None)
os.environ.pop("AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL", None)
else:
os.environ["AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL_DIAGNOSTICS"] = original_value
os.environ["AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL"] = original_value
# Reload settings again
tracer.settings = WorkflowDiagnosticSettings()
@pytest.mark.asyncio
async def test_span_creation_and_attributes(tracing_enabled: Any, span_exporter: InMemorySpanExporter) -> None:
"""Test creation and attributes of all span types (workflow, processing, sending)."""
# Create a mock workflow object
@@ -228,7 +226,6 @@ async def test_span_creation_and_attributes(tracing_enabled: Any, span_exporter:
assert sending_span.attributes.get("message.destination_executor_id") == "target-789"
@pytest.mark.asyncio
async def test_trace_context_handling(tracing_enabled: Any, span_exporter: InMemorySpanExporter) -> None:
"""Test trace context propagation and handling in messages and executors."""
shared_state = SharedState()