[BUG] OTel: api_request event missing for most requests whose response contains text (only assistant_response is logged); side queries log neither
What's wrong
The monitoring docs say the claude_code.api_request event "is logged for each API request to Claude", and that claude_code.assistant_response is logged after each API request that returns text content. In practice, when a response contains text, Claude Code usually logs only assistant_response and no api_request for that request. Side queries such as auto_mode and agent_classifier log neither event.
assistant_response carries no cost_usd and no token counts, so any consumer that reads per-request cost from api_request misses these requests. In our data that is about a third of all LLM requests.
What should happen
One api_request event, with cost_usd and token counts, for every API request, including requests whose response contains text and side queries. If some requests are excluded on purpose, the docs should say which.
Steps to reproduce
Telemetry on (CLAUDE_CODE_ENABLE_TELEMETRY=1, OTLP logs, traces and metrics, CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1), Claude Code 2.1.284:
claude -p "Reply with the single word: done"- Exported: one
claude_code.llm_requestspan (stop_reason=end_turn,success=true, tokens present) and oneassistant_responselog event with the samerequest_id. - Not exported: any
api_requestlog event for thatrequest_id. - The
claude_code.cost.usagemetric for the session is non-zero, and theclaude_code.token.usagetotals equal the span's tokens.
Variant: ask it to run one Bash command and then reply. The tool-call request gets api_request. The final text reply gets assistant_response only.
Impact
Across about 29k llm_request spans over 7 days, from several developers on versions 2.1.251 through 2.1.284, joined to log events by request_id:
| Log events for the request | Share of requests |
|---|---|
| api_request only (tool-use response, no text) | 64% |
| api_request + assistant_response (the documented behavior) | 3% |
| assistant_response only | 27% |
| neither (side queries: auto_mode, agent_classifier, agent_summary, …) | 6% |
- Only about 11% of text-bearing responses get an
api_request. Per version it ranges from 6% to 17%, so it isn't a recent regression. - Every
end_turnresponse contains text, so 84–91% ofend_turnrequests have noapi_request. - It isn't exporter loss. For each affected request, the
assistant_responseevent with the samerequest_idarrives through the same exporter. - The
claude_code.cost.usagemetric does count these requests. Over the same week its total was 1.64× the sum ofcost_usdonapi_requestevents. Cost is tracked internally but not emitted per request.
Also observed (possibly related)
- #64436 and #89406 describe OTel logs lost on shutdown or stopping mid-session. This looks different: the sibling
assistant_responseevent for the same request is exported, and the gap reproduces on a single short-pcall.
Environment
- Claude Code 2.1.284 (probe); 2.1.251–2.1.284 (aggregate data)
- macOS (Darwin 25.6.0)
- OTLP
http/protobufexporter for logs, traces and metrics