diff --git a/src/strands/telemetry/tracer.py b/src/strands/telemetry/tracer.py index 7cd2d0e7b..860a48ea7 100644 --- a/src/strands/telemetry/tracer.py +++ b/src/strands/telemetry/tracer.py @@ -289,13 +289,13 @@ def end_model_invoke_span( error: Optional exception if the model call failed. """ attributes: Dict[str, AttributeValue] = { - "gen_ai.usage.prompt_tokens": usage["inputTokens"], - "gen_ai.usage.input_tokens": usage["inputTokens"], - "gen_ai.usage.completion_tokens": usage["outputTokens"], - "gen_ai.usage.output_tokens": usage["outputTokens"], - "gen_ai.usage.total_tokens": usage["totalTokens"], - "gen_ai.usage.cache_read_input_tokens": usage.get("cacheReadInputTokens", 0), - "gen_ai.usage.cache_write_input_tokens": usage.get("cacheWriteInputTokens", 0), + "gen_ai.usage.prompt_tokens": str(usage["inputTokens"]), + "gen_ai.usage.input_tokens": str(usage["inputTokens"]), + "gen_ai.usage.completion_tokens": str(usage["outputTokens"]), + "gen_ai.usage.output_tokens": str(usage["outputTokens"]), + "gen_ai.usage.total_tokens": str(usage["totalTokens"]), + "gen_ai.usage.cache_read_input_tokens": str(usage.get("cacheReadInputTokens", 0)), + "gen_ai.usage.cache_write_input_tokens": str(usage.get("cacheWriteInputTokens", 0)), } if self.use_latest_genai_conventions: @@ -607,13 +607,13 @@ def end_agent_span( accumulated_usage = response.metrics.accumulated_usage attributes.update( { - "gen_ai.usage.prompt_tokens": accumulated_usage["inputTokens"], - "gen_ai.usage.completion_tokens": accumulated_usage["outputTokens"], - "gen_ai.usage.input_tokens": accumulated_usage["inputTokens"], - "gen_ai.usage.output_tokens": accumulated_usage["outputTokens"], - "gen_ai.usage.total_tokens": accumulated_usage["totalTokens"], - "gen_ai.usage.cache_read_input_tokens": accumulated_usage.get("cacheReadInputTokens", 0), - "gen_ai.usage.cache_write_input_tokens": accumulated_usage.get("cacheWriteInputTokens", 0), + "gen_ai.usage.prompt_tokens": str(accumulated_usage["inputTokens"]), + "gen_ai.usage.completion_tokens": str(accumulated_usage["outputTokens"]), + "gen_ai.usage.input_tokens": str(accumulated_usage["inputTokens"]), + "gen_ai.usage.output_tokens": str(accumulated_usage["outputTokens"]), + "gen_ai.usage.total_tokens": str(accumulated_usage["totalTokens"]), + "gen_ai.usage.cache_read_input_tokens": str(accumulated_usage.get("cacheReadInputTokens", 0)), + "gen_ai.usage.cache_write_input_tokens": str(accumulated_usage.get("cacheWriteInputTokens", 0)), } ) diff --git a/tests/strands/telemetry/test_tracer.py b/tests/strands/telemetry/test_tracer.py index 4e9872100..f1651b943 100644 --- a/tests/strands/telemetry/test_tracer.py +++ b/tests/strands/telemetry/test_tracer.py @@ -209,13 +209,13 @@ def test_end_model_invoke_span(mock_span): tracer.end_model_invoke_span(mock_span, message, usage, stop_reason) - mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", 10) - mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", 10) - mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", 20) - mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", 20) - mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", 30) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", 0) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", 0) + mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", "10") + mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", "10") + mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", "20") + mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", "20") + mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", "30") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", "0") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", "0") mock_span.add_event.assert_called_with( "gen_ai.choice", attributes={"message": json.dumps(message["content"]), "finish_reason": "end_turn"}, @@ -235,13 +235,13 @@ def test_end_model_invoke_span_latest_conventions(mock_span): tracer.end_model_invoke_span(mock_span, message, usage, stop_reason) - mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", 10) - mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", 10) - mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", 20) - mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", 20) - mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", 30) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", 0) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", 0) + mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", "10") + mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", "10") + mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", "20") + mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", "20") + mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", "30") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", "0") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", "0") mock_span.add_event.assert_called_with( "gen_ai.client.inference.operation.details", attributes={ @@ -698,13 +698,13 @@ def test_end_agent_span(mock_span): tracer.end_agent_span(mock_span, mock_response) - mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", 50) - mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", 50) - mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", 100) - mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", 100) - mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", 150) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", 0) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", 0) + mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", "50") + mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", "50") + mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", "100") + mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", "100") + mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", "150") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", "0") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", "0") mock_span.add_event.assert_any_call( "gen_ai.choice", attributes={"message": "Agent response", "finish_reason": "end_turn"}, @@ -729,13 +729,13 @@ def test_end_agent_span_latest_conventions(mock_span): tracer.end_agent_span(mock_span, mock_response) - mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", 50) - mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", 50) - mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", 100) - mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", 100) - mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", 150) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", 0) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", 0) + mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", "50") + mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", "50") + mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", "100") + mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", "100") + mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", "150") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", "0") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", "0") mock_span.add_event.assert_called_with( "gen_ai.client.inference.operation.details", attributes={ @@ -769,13 +769,13 @@ def test_end_model_invoke_span_with_cache_metrics(mock_span): tracer.end_model_invoke_span(mock_span, message, usage, stop_reason) - mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", 10) - mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", 10) - mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", 20) - mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", 20) - mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", 30) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", 5) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", 3) + mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", "10") + mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", "10") + mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", "20") + mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", "20") + mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", "30") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", "5") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", "3") mock_span.set_status.assert_called_once_with(StatusCode.OK) mock_span.end.assert_called_once() @@ -801,13 +801,13 @@ def test_end_agent_span_with_cache_metrics(mock_span): tracer.end_agent_span(mock_span, mock_response) - mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", 50) - mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", 50) - mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", 100) - mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", 100) - mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", 150) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", 25) - mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", 10) + mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", "50") + mock_span.set_attribute.assert_any_call("gen_ai.usage.input_tokens", "50") + mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", "100") + mock_span.set_attribute.assert_any_call("gen_ai.usage.output_tokens", "100") + mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", "150") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_read_input_tokens", "25") + mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", "10") mock_span.set_status.assert_called_once_with(StatusCode.OK) mock_span.end.assert_called_once()