From 7eeab90326a90e9c4c7c4985a3d9a908b9b4a219 Mon Sep 17 00:00:00 2001 From: giulio-leone Date: Fri, 13 Mar 2026 00:11:40 +0100 Subject: [PATCH] fix(telemetry): add common gen_ai attributes to event loop cycle spans start_event_loop_cycle_span() was missing the _get_common_attributes() call that all other span start methods (start_model_invoke_span, start_tool_call_span, start_agent_span, start_multiagent_span) include. This caused event_loop_cycle spans to carry gen_ai.input.messages (via _add_event_messages) but lack gen_ai.system/gen_ai.provider.name and gen_ai.operation.name, which downstream OTEL tooling (collectors, exporters, redaction processors) may rely on for filtering/policy. Closes #1876 --- src/strands/telemetry/tracer.py | 7 ++++--- tests/strands/telemetry/test_tracer.py | 10 +++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/strands/telemetry/tracer.py b/src/strands/telemetry/tracer.py index 0471a7fcc..4fc614561 100644 --- a/src/strands/telemetry/tracer.py +++ b/src/strands/telemetry/tracer.py @@ -521,9 +521,10 @@ def start_event_loop_cycle_span( event_loop_cycle_id = str(invocation_state.get("event_loop_cycle_id")) parent_span = parent_span if parent_span else invocation_state.get("event_loop_parent_span") - attributes: dict[str, AttributeValue] = { - "event_loop.cycle_id": event_loop_cycle_id, - } + attributes: dict[str, AttributeValue] = self._get_common_attributes( + operation_name="execute_event_loop_cycle" + ) + attributes["event_loop.cycle_id"] = event_loop_cycle_id if custom_trace_attributes: attributes.update(custom_trace_attributes) diff --git a/tests/strands/telemetry/test_tracer.py b/tests/strands/telemetry/test_tracer.py index 410db0c0c..d54235854 100644 --- a/tests/strands/telemetry/test_tracer.py +++ b/tests/strands/telemetry/test_tracer.py @@ -631,6 +631,8 @@ def test_start_event_loop_cycle_span(mock_tracer): mock_span.set_attributes.assert_called_once_with( { + "gen_ai.operation.name": "execute_event_loop_cycle", + "gen_ai.system": "strands-agents", "event_loop.cycle_id": "cycle-123", "request_id": "req-456", "trace_level": "debug", @@ -660,7 +662,13 @@ def test_start_event_loop_cycle_span_latest_conventions(mock_tracer, monkeypatch mock_tracer.start_span.assert_called_once() assert mock_tracer.start_span.call_args[1]["name"] == "execute_event_loop_cycle" - mock_span.set_attributes.assert_called_once_with({"event_loop.cycle_id": "cycle-123"}) + mock_span.set_attributes.assert_called_once_with( + { + "gen_ai.operation.name": "execute_event_loop_cycle", + "gen_ai.provider.name": "strands-agents", + "event_loop.cycle_id": "cycle-123", + } + ) mock_span.add_event.assert_any_call( "gen_ai.client.inference.operation.details", attributes={