Skip to main content

What the telemetry can (and cannot) tell you

Costpilot builds on the OpenTelemetry export of the coding tools. A few findings from analysing that data shape what the dashboard shows. The full analysis is in the telemetry data model.

The atomic unit is one model API call​

Each claude_code.api_request log event is one real request (message.id) with input, output, cache-read and cache-creation tokens. One user prompt usually triggers several calls (the agentic tool loop), so cost is rolled up from calls, not prompts.

The tool's own cost wins​

Claude Code reports each call's cost (cost_usd) and splits cache writes by lifetime (5 minutes at 1.25x input, 1 hour at 2x); the main thread caches for 1 hour, subagents for 5 minutes. Costpilot stores the reported cost and calculates its own from tokens and the price table next to it: as the cross-check (a difference above 1% is logged) and as the fallback for versions that report neither. Without the split, the main thread is priced at 1 hour and subagents and named pipeline agents at 5 minutes. Each record says which it is (cost_source). Gemini CLI and Codex CLI costs are always calculated.

No cost below the API call​

Neither OTel nor the local transcripts split tokens by thinking, text or tool use; the API only reports usage per response. Costpilot therefore never claims "tokens spent on tool X". Tool and MCP cards show calls, errors and durations instead.

Logs are event-driven, metrics are periodic​

Productivity counters (active time, commits, PRs, lines of code) are exported at most every 60 seconds, as deltas by default; cumulative payloads are diffed on ingestion. Active time and lines of code are stored but deliberately not shown as KPIs: lines of code reward the wrong thing, and active time is a tool-side measure that includes waits on the human. The turn is the unit the dashboard uses instead.

session_id is the join key​

Resource attributes are frozen at process start and Claude Code offers no way to inject a custom attribute such as an issue id into an event. That is why the agent hook reports the issue separately and the API joins by session id. See Attribution.

claude_code.* is proprietary, not the OTel GenAI convention​

The logs and metrics Costpilot consumes use Claude Code's own attribute names; the standardized gen_ai.* names only appear on trace spans, which the API accepts and discards. Every emitter (Claude Code, Gemini CLI, Codex CLI) therefore gets its own normalizer instead of one shared mapping.

Consequences for the dashboard​

  • USD is the comparable figure; tokens are a volume indicator.
  • Issues with zero recorded tokens never appear.
  • Tool usage is shown as counts and durations, never as cost.