Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

claude-otel

Monitor every Claude Code session with OpenTelemetry and Grafana Cloud — see exactly what each session costs, how many tokens it burns, and where your money goes.

Claude Code Sessions Dashboard

The problem

Claude Code is fantastic, but it's a black box when it comes to cost. You finish a session and wonder: How much did that just cost me? Was it the cache reads that added up, or the output tokens? How does today compare to yesterday?

The built-in /cost command gives you a snapshot of the current session, but there's no way to see historical data, compare sessions, or track spending trends over time.

The solution

Claude Code has built-in OpenTelemetry (OTEL) support. It can export metrics and events to any OTEL-compatible backend. This repo shows you how to wire it up to Grafana Cloud's free tier — which gives you a proper dashboard with cost breakdowns, token usage, and session tracking, at zero cost.

The setup takes about 5 minutes. No Docker, no collectors, no infrastructure. Just a config change and a free Grafana Cloud account.

What you get

The dashboard gives you:

Panel What it shows
Total Cost Aggregate USD spend across all sessions
Total Tokens Combined token count (input + output + cache)
Sessions Number of distinct sessions tracked
Total Active Time How long you've been actively using Claude Code
Sessions Table Per-session breakdown: cost, active time, input/output tokens, cache read/write
Cost Over Time Stacked bar chart of spend by model (Opus, Sonnet, Haiku)
Tokens Over Time Stacked bar chart of token usage by type
Cost by Model Pie chart showing which models eat your budget
Cost by Session (Top 10) Horizontal bar chart of your most expensive sessions

Quick start

1. Create a free Grafana Cloud account

Go to grafana.com and sign up. The free tier includes:

  • 50 GB of traces/logs per month
  • 10,000 metrics series
  • 14-day retention
  • 3 users
  • No credit card required

This is more than enough for personal Claude Code monitoring.

2. Get your OTLP credentials

In Grafana Cloud:

  1. Go to your stack's Connections > Add new connection
  2. Search for OpenTelemetry (OTLP)
  3. Click Configure
  4. Note your OTLP endpoint (e.g., https://otlp-gateway-prod-us-east-0.grafana.net/otlp)
  5. Generate an API token — make sure it has metrics:write and logs:write scopes
  6. Note the Instance ID and API key
  7. Create your Base64 credentials: echo -n "INSTANCE_ID:API_KEY" | base64

3. Configure Claude Code

Add the following to your ~/.claude/settings.json (merge into the existing "env" block if you have one):

{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_METRICS_EXPORTER": "otlp",
    "OTEL_LOGS_EXPORTER": "otlp",
    "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "https://otlp-gateway-prod-<REGION>.grafana.net/otlp",
    "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Basic <BASE64_CREDENTIALS>",
    "OTEL_LOG_USER_PROMPTS": "1",
    "OTEL_LOG_TOOL_DETAILS": "1",
    "OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": "cumulative"
  }
}

Replace <REGION> with your Grafana Cloud region (e.g., us-east-0, eu-west-0, au-southeast-1) and <BASE64_CREDENTIALS> with the Base64 string from step 2.

Important: The cumulative temporality setting is critical. Without it, Grafana Cloud silently rejects Claude Code's metrics (they default to delta temporality, which Grafana's Mimir backend doesn't accept for counters). This is the most common reason metrics don't show up.

4. Import the dashboard

Option A: Via the Grafana UI

  1. In Grafana Cloud, go to Dashboards > New > Import
  2. Upload the grafana-dashboard.json file from this repo
  3. Select your Prometheus datasource
  4. Click Import

Option B: Via the API

# Create a service account with Admin role in Grafana Cloud
# Administration > Service Accounts > Add > Role: Admin > Generate token

curl -X POST "https://YOUR_STACK.grafana.net/api/dashboards/db" \
  -H "Authorization: Bearer YOUR_SERVICE_ACCOUNT_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"dashboard\": $(cat grafana-dashboard.json), \"overwrite\": true, \"folderUid\": \"\"}"

5. Start a Claude Code session

Every new Claude Code session will now export telemetry to Grafana Cloud. Metrics flush every 60 seconds and log events every 5 seconds.

echo "hello" | claude --print   # Quick test

Wait about 60 seconds, then check your dashboard.

Understanding the data

You don't need to be a Grafana expert to use this dashboard. Here's a quick primer on what's happening under the hood.

How Claude Code sends data

When you enable telemetry, Claude Code uses the OpenTelemetry standard to export two types of data:

  • Metrics — Numerical counters that get aggregated over time. These power the stat panels and time series charts. Metrics are stored in Prometheus (Grafana calls their hosted version "Mimir").
  • Log events — Individual records for each API call, tool use, and user prompt. These are stored in Loki (Grafana's log storage).

What metrics are tracked

Claude Code exports these metrics automatically:

Metric Labels Description
claude_code_cost_usage_USD_total model, session_id Cost in USD
claude_code_token_usage_tokens_total type, model, session_id Token count by type (input, output, cacheRead, cacheCreation)
claude_code_session_count_total session_id Session counter
claude_code_active_time_seconds_total type, session_id Active time (cli vs user)
claude_code_lines_of_code_count_total type, session_id Lines added/removed
claude_code_commit_count_total session_id Git commits created
claude_code_pull_request_count_total session_id PRs created

What log events are tracked

Event Key fields Description
claude_code.api_request model, cost_usd, duration_ms, tokens Every API call to Claude
claude_code.user_prompt prompt_length, prompt (if enabled) Every user message
claude_code.tool_result tool_name, success, duration_ms Every tool execution
claude_code.api_error error, status_code, attempt API failures and retries
claude_code.tool_decision tool_name Tool permission decisions

Exploring beyond the dashboard

In Grafana Cloud's Explore view, you can run custom queries:

Prometheus (metrics):

# Cost per session
sum by (session_id) (claude_code_cost_usage_USD_total)

# Token breakdown by model
sum by (model, type) (claude_code_token_usage_tokens_total)

# Most expensive sessions
topk(5, sum by (session_id) (claude_code_cost_usage_USD_total))

Loki (log events):

# All API requests
{service_name="claude-code"} | json | event_name="claude_code.api_request"

# Failed API calls
{service_name="claude-code"} | json | event_name="claude_code.api_error"

# Tool usage
{service_name="claude-code"} | json | event_name="claude_code.tool_result"

Configuration reference

The full claude-settings-snippet.json in this repo contains all the settings. Here's what each one does:

Setting Value Purpose
CLAUDE_CODE_ENABLE_TELEMETRY 1 Master switch — required
OTEL_METRICS_EXPORTER otlp Send metrics via OTLP
OTEL_LOGS_EXPORTER otlp Send log events via OTLP
OTEL_EXPORTER_OTLP_PROTOCOL http/protobuf Use HTTP with protobuf encoding
OTEL_EXPORTER_OTLP_ENDPOINT https://...grafana.net/otlp Your Grafana Cloud OTLP gateway
OTEL_EXPORTER_OTLP_HEADERS Authorization=Basic ... Base64-encoded instanceId:apiKey
OTEL_LOG_USER_PROMPTS 1 Include prompt text in events
OTEL_LOG_TOOL_DETAILS 1 Include tool names in events
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE cumulative Critical — Grafana Cloud rejects delta counters

Gotchas

  1. Metrics don't show up? Almost certainly a temporality issue. Make sure OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE is set to cumulative. Without this, Grafana Cloud silently drops all counter metrics.

  2. Logs show up but metrics don't? Same issue — logs use a different protocol path than metrics, so logs can work while metrics are rejected.

  3. Short sessions may not export metrics. The metrics flush interval is 60 seconds. If a session completes in under 60 seconds, the OTEL SDK may not flush in time. Longer sessions will always export properly.

  4. Settings only apply to new sessions. After changing ~/.claude/settings.json, you must start a new Claude Code session. Existing sessions won't pick up the changes.

  5. The dashboard datasource must match. If your Grafana Prometheus datasource isn't named grafanacloud-prom, you'll need to edit the dashboard JSON or select the correct datasource after import.

Cost of monitoring

Zero. Grafana Cloud's free tier is generous:

  • A typical Claude Code session generates a few hundred metrics data points and a few dozen log events
  • At normal usage (10-20 sessions/day), you'd use less than 1% of the free tier's 10,000 metrics series
  • Log events are similarly tiny compared to the 50 GB/month allowance
  • The 14-day retention is plenty for tracking recent usage patterns

License

MIT

About

Monitor Claude Code sessions with OpenTelemetry and Grafana Cloud — cost, tokens, and usage metrics per session

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors