fix(ingest): count TypeScript ADK's call_llm as the model call - #1170
Conversation
#1143 excluded every google_adk call_llm span before the inference-op check. Python ADK's call_llm is a wrapper with no operation over its generate_content child, but TypeScript ADK has no generate_content span: the Maple span processor stamps op chat on call_llm, so those sessions lost every LLM call and their tokens. Without the arm, the op decides: Python's opless wrapper still falls through to false, TypeScript's chat span is the call.
Maple review🟢 Confidence 4/5 · likely safe to merge Drops the
What was checked
|
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (1)
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review. 📝 WalkthroughWalkthroughGoogle ADK ChangesGoogle ADK usage classification
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to The change enables inference-tagged Google ADK Architecture SummaryArchitecture risk: 🔵 Low · up to The change affects 1 system. Changed systems: Architecture concerns Review detailsSystems and components
Before / after behavior
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings
🧪 Generate unit tests (beta)
🛠️ Fix failing CI checks 💡
Warning Some tools did not complete. Review the errors below. 🔧 Clippy (1.98.1)Clippy execution failed Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Regression from #1143 in
apps/ingest/src/ai_session/usage.rs(is_model_call)."google_adk" if span_name == "call_llm" => falseran before the inference-op check, so no ADKcall_llmspan was ever marked as the model call.call_llmis a wrapper with nogen_ai.operation.name, and itsgenerate_contentchild carries the same figures. Everycall_llmin the trace-capture ADK recordings (docs_google-adk_a/b, google_adk_agents, google_adk_agents_probe, google_adk_hitl_probe, google_adk_user, smoke-adk) has no operation and noopeninference.span.kind.generate_contentspan. TheAdkSpanProcessorfrom the google-adk setup guide stampsgen_ai.operation.name=chatoncall_llm, which makes that span the model call. With the arm in place, TS ADK sessions got no LLM calls and no tokens. EU prod shows this on the synthetic span fromverify2-adk-ts-synthetic(maple_ai.llm_call=0).call_llmhas no operation, so it missesINFERENCE_OPSand falls through tofalselike before, becausegoogle_adkis not anunknown:vendor. A TScall_llmhas opchatand counts as the call. This is the same as the suggestedop.is_empty()guard, one line shorter.facts.rshas nocall_llmor span-name rule of this kind.Tests:
google_adk_generate_content_owns_usagetest covers Python:call_llm+generate_contentgives one call, and the wrapper getsllm_call=0and no buckets.google_adk_ts_call_llm_owns_usagetest covers TS:call_llmwith opchatand usage gives one call, with buckets[600, 400, 0, 100, 0].cargo test --lib ai_session: 79 passed.Out of scope, noted here: for Gemini,
output_tokensexcludes thinking.Usage::readclamps reasoning to the completion count, so a Gemini call that thinks more than it writes (the synthetic span had output 100 and reasoning 300) is bucketed as output 0 and reasoning 100. The new test leaves reasoning out so it does not lock that behaviour in.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by CodeRabbit
call_llmas the model call when nogenerate_contentcall is present, and separates cached from uncached prompt usage.