Note: this is a follow-up to my post on monitoring GitHub Copilot Chat with the Aspire Dashboard. Same idea, different agent.
Some developers on the team have switched (part-time) from Copilot Chat to Claude Code for their agentic work. Same question came up again: how much are we actually using it, what does it cost, and where does the time go in a session? Claude Code has its own OTel support, separate from Copilot's, so it needs its own setup — but it plugs into the exact same Aspire Dashboard we already had running.
What Claude Code exports
Claude Code emits three kinds of OTel signals:
- Metrics — session counts, token usage, cost, lines of code changed, active time
- Events — one event per prompt, per API call, per tool result, per permission decision
- Traces (beta) — a
claude_code.interactionspan per prompt, withclaude_code.llm_requestandclaude_code.toolspans nested underneath
Remark: traces are still beta. Metrics and events are the stable path and honestly cover most of what you want for a usage dashboard — cost, tokens, sessions, tool acceptance rate. Only reach for traces if you specifically want to see the timeline of one interaction, tool call by tool call.
Reusing the Aspire Dashboard
If you've still got the Aspire Dashboard container running from the Copilot setup, you don't need a second one. Claude Code and Copilot Chat can both point at the same OTLP endpoint — the dashboard separates them by service.name automatically.
If you don't have it running, use the Aspire CLI:
aspire dashboard run
Or use the available Docker image:
docker run --rm -d -p 18888:18888 -p 4318:18890 --name aspire-dashboard \
mcr.microsoft.com/dotnet/aspire-dashboard:latest
Open http://localhost:18888 like before.
Enabling telemetry in Claude Code
Claude Code is configured through environment variables, not VS Code settings, since it also runs standalone in a terminal. Minimal setup for metrics and events over OTLP/HTTP, pointed at the same Aspire container:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
claude
Run a session, ask it to do something, exit. Give it a few seconds (export intervals default to 60s for metrics and 5s for logs), so don't panic if the dashboard is empty immediately.
Tip: to verify without waiting on a real backend, swap OTEL_METRICS_EXPORTER=console first and watch the numbers print straight to your terminal. Once you see them, switch back to otlp.
Turning on traces too
Metrics and events don't need anything beyond what's above. If you also want the span tree — one claude_code.interaction per prompt, with the LLM calls and tool executions nested underneath — add the beta flag and a traces exporter:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
claude
Back in the dashboard's Traces view, filter by service and you'll see claude_code.interaction as the root span, with claude_code.llm_request and claude_code.tool as children. The same shape as the Copilot invoke_agent tree from last time, just under Anthropic's own naming.
Remark: by default, prompt text, tool arguments and tool output are all redacted in both events and traces. If you want the full content, set OTEL_LOG_USER_PROMPTS=1, OTEL_LOG_TOOL_DETAILS=1 and OTEL_LOG_TOOL_CONTENT=1.
What you get for free
Once the data is flowing, a few things are immediately useful without building any dashboard:
claude_code.cost.usageandclaude_code.token.usage:actual spend and token counts per session, broken down by modelclaude_code.code_edit_tool.decision:how often edits get accepted vs rejected, which is a decent proxy for "is this actually useful to people"claude_code.active_time.total:real active time, not wall-clock time, so it isn't inflated by someone leaving a session open in a background tab
Rolling it out to a team
Everything above is developer-set environment variables, which is fine for trying it out. For a team rollout, the same keys go into Claude Code's managed settings file instead, so telemetry flows to an approved collector without every developer configuring it themselves.
That's it. Same dashboard, second agent, no new tooling.