@@ -177,6 +177,8 @@ def test_end_model_invoke_span(mock_span):
177177 mock_span .set_attribute .assert_any_call ("gen_ai.usage.completion_tokens" , 20 )
178178 mock_span .set_attribute .assert_any_call ("gen_ai.usage.output_tokens" , 20 )
179179 mock_span .set_attribute .assert_any_call ("gen_ai.usage.total_tokens" , 30 )
180+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.cache_read_input_tokens" , 0 )
181+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.cache_write_input_tokens" , 0 )
180182 mock_span .add_event .assert_called_with (
181183 "gen_ai.choice" ,
182184 attributes = {"message" : json .dumps (message ["content" ]), "finish_reason" : "end_turn" },
@@ -404,6 +406,8 @@ def test_end_agent_span(mock_span):
404406 mock_span .set_attribute .assert_any_call ("gen_ai.usage.completion_tokens" , 100 )
405407 mock_span .set_attribute .assert_any_call ("gen_ai.usage.output_tokens" , 100 )
406408 mock_span .set_attribute .assert_any_call ("gen_ai.usage.total_tokens" , 150 )
409+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.cache_read_input_tokens" , 0 )
410+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.cache_write_input_tokens" , 0 )
407411 mock_span .add_event .assert_any_call (
408412 "gen_ai.choice" ,
409413 attributes = {"message" : "Agent response" , "finish_reason" : "end_turn" },
@@ -412,6 +416,64 @@ def test_end_agent_span(mock_span):
412416 mock_span .end .assert_called_once ()
413417
414418
419+ def test_end_model_invoke_span_with_cache_metrics (mock_span ):
420+ """Test ending a model invoke span with cache metrics."""
421+ tracer = Tracer ()
422+ message = {"role" : "assistant" , "content" : [{"text" : "Response" }]}
423+ usage = Usage (
424+ inputTokens = 10 ,
425+ outputTokens = 20 ,
426+ totalTokens = 30 ,
427+ cacheReadInputTokens = 5 ,
428+ cacheWriteInputTokens = 3 ,
429+ )
430+ stop_reason : StopReason = "end_turn"
431+
432+ tracer .end_model_invoke_span (mock_span , message , usage , stop_reason )
433+
434+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.prompt_tokens" , 10 )
435+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.input_tokens" , 10 )
436+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.completion_tokens" , 20 )
437+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.output_tokens" , 20 )
438+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.total_tokens" , 30 )
439+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.cache_read_input_tokens" , 5 )
440+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.cache_write_input_tokens" , 3 )
441+ mock_span .set_status .assert_called_once_with (StatusCode .OK )
442+ mock_span .end .assert_called_once ()
443+
444+
445+ def test_end_agent_span_with_cache_metrics (mock_span ):
446+ """Test ending an agent span with cache metrics."""
447+ tracer = Tracer ()
448+
449+ # Mock AgentResult with metrics including cache tokens
450+ mock_metrics = mock .MagicMock ()
451+ mock_metrics .accumulated_usage = {
452+ "inputTokens" : 50 ,
453+ "outputTokens" : 100 ,
454+ "totalTokens" : 150 ,
455+ "cacheReadInputTokens" : 25 ,
456+ "cacheWriteInputTokens" : 10 ,
457+ }
458+
459+ mock_response = mock .MagicMock ()
460+ mock_response .metrics = mock_metrics
461+ mock_response .stop_reason = "end_turn"
462+ mock_response .__str__ = mock .MagicMock (return_value = "Agent response" )
463+
464+ tracer .end_agent_span (mock_span , mock_response )
465+
466+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.prompt_tokens" , 50 )
467+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.input_tokens" , 50 )
468+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.completion_tokens" , 100 )
469+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.output_tokens" , 100 )
470+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.total_tokens" , 150 )
471+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.cache_read_input_tokens" , 25 )
472+ mock_span .set_attribute .assert_any_call ("gen_ai.usage.cache_write_input_tokens" , 10 )
473+ mock_span .set_status .assert_called_once_with (StatusCode .OK )
474+ mock_span .end .assert_called_once ()
475+
476+
415477def test_get_tracer_singleton ():
416478 """Test that get_tracer returns a singleton instance."""
417479 # Reset the singleton first
0 commit comments