fix: Fix incorrect token count mapping in telemetry

Merge https://github.com/google/adk-python/pull/2109

Fixes #2105

## Problem
  When integrating Google ADK with Langfuse using the @observe
  decorator, the usage details displayed in Langfuse web UI were
  incorrect.

  The root cause was in the telemetry implementation where
  total_token_count was being mapped to gen_ai.usage.output_tokens
  instead of candidates_token_count.

  - Expected mapping:
    - candidates_token_count → completion_tokens (output tokens)
    - prompt_token_count → prompt_tokens (input tokens)

  - Previous incorrect mapping:
    - total_token_count → completion_tokens (wrong!)
    - prompt_token_count → prompt_tokens (correct)

  ## Solution
  Updated trace_call_llm function in telemetry.py to use
  candidates_token_count for output token tracking instead of
  total_token_count, ensuring proper token count reporting to
  observability tools like Langfuse.

  ## Testing plan
  - Updated test expectations in test_telemetry.py
  - Verified telemetry tests pass
  - Manual verification with Langfuse integration

  ## Screenshots
  **Before**

<img width="1187" height="329" alt="Screenshot from 2025-07-22 20-20-33" src="https://github.com/user-attachments/assets/ad5fc957-64a2-4524-bd31-0cebb15a5270" />

  **After**

<img width="1187" height="329" alt="Screenshot from 2025-07-22 20-21-40" src="https://github.com/user-attachments/assets/3920df2a-be75-47e0-9bd0-f961bb72c838" />

 _Notes_: From the screenshot, there's another problem: thoughts_token_count field is not mapped, but this should be another issue imo

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2109 from tl-nguyen:fix-telemetry-token-count-mapping 3d043f558b5f8bcb2c6e0370e2cc4c0ff25d1f4a
PiperOrigin-RevId: 786827802
This commit is contained in:
Lam Nguyen
2025-07-24 14:01:03 -07:00
committed by Copybara-Service
parent 11037fc133
commit c8f8b4a20a
2 changed files with 5 additions and 3 deletions
+4 -2
View File
@@ -155,7 +155,9 @@ async def test_trace_call_llm_usage_metadata(monkeypatch, mock_span_fixture):
llm_response = LlmResponse(
turn_complete=True,
usage_metadata=types.GenerateContentResponseUsageMetadata(
total_token_count=100, prompt_token_count=50
total_token_count=100,
prompt_token_count=50,
candidates_token_count=50,
),
)
trace_call_llm(invocation_context, 'test_event_id', llm_request, llm_response)
@@ -163,7 +165,7 @@ async def test_trace_call_llm_usage_metadata(monkeypatch, mock_span_fixture):
expected_calls = [
mock.call('gen_ai.system', 'gcp.vertex.agent'),
mock.call('gen_ai.usage.input_tokens', 50),
mock.call('gen_ai.usage.output_tokens', 100),
mock.call('gen_ai.usage.output_tokens', 50),
]
assert mock_span_fixture.set_attribute.call_count == 9
mock_span_fixture.set_attribute.assert_has_calls(