How I Built Real-Time Dashboards for Claude Code Metrics with OTEL, Prometheus, and Grafana
Source: Dev.to
Overview
I wanted concrete numbers from Claude Code—tokens, cost, lines of code, productivity ratios, ROI. This guide shows how to collect telemetry with OTEL, store it in Prometheus, and visualize it in Grafana.
Prerequisites
- Claude Code with native OTEL telemetry enabled
- Prometheus (v2.45+ recommended)
- Grafana (v10+ recommended)
jqfor JSON parsing (optional, for verification)
1. Enable Telemetry in Claude Code
Add the following environment variables to your shell profile (~/.zshrc, ~/.bashrc, etc.):
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:9090/api/v1/otlp
After editing, reload the profile:
source ~/.zshrc # or source ~/.bashrc
2. Configure Prometheus to Receive OTLP Metrics
Prometheus must be started with the OTLP receiver enabled and the delta‑to‑cumulative conversion flag:
prometheus \
--config.file=prometheus.yml \
--web.enable-otlp-receiver \
--enable-feature=otlp-deltatocumulative
Note: On macOS with Homebrew, you may need to edit the service plist or wrap the command in a script to include these flags.
Why otlp-deltatocumulative?
Some Claude Code metrics (e.g., lines of code) are delta metrics. The flag automatically converts them to cumulative counters, which Prometheus expects.
3. Verify Data Ingestion
Run the following command to list metric names that Prometheus has received:
curl 'http://localhost:9090/api/v1/label/__name__/values' | jq '.data[]' | grep claude
You should see metrics such as:
claude_code_token_usage_tokens_totalclaude_code_cost_usage_USD_totalclaude_code_active_time_seconds_totalclaude_code_lines_of_code_count_totalclaude_code_session_count_total
4. Metric Reference
| Metric | Labels | Description |
|---|---|---|
claude_code_token_usage_tokens_total | type (input/output/cacheRead/cacheCreation), model | Token consumption |
claude_code_cost_usage_USD_total | model | Estimated API cost (USD) |
claude_code_active_time_seconds_total | type (cli/user) | Time tracking (CLI vs. user) |
claude_code_lines_of_code_count_total | type (added/removed) | Code output (delta metric) |
claude_code_session_count_total | — | Number of Claude sessions |
Interpreting active_time
type="cli"– how long Claude was processing.type="user"– how long you were interacting.
The productivity multiplier is cli time / user time.
5. Grafana Dashboards
I created three dashboards:
- Claude Code Metrics – token stats, cost breakdown, productivity ratio.
- Daily/Weekly Summary – aggregated stats with time‑range awareness.
- Engineering Economics – ROI calculations, team equivalence, business metrics.
Importing
Export the JSON files to a GitHub gist (link pending) and import via Dashboards → Import in Grafana.
6. Grafana Variables & Useful Queries
Define variables for:
- Hourly rate – used in ROI calculations.
- Average developer lines/hour – for team equivalence.
- Productivity Ratio –
CLI time / User time.
Example Queries
Productivity Ratio
sum(claude_code_active_time_seconds_total{type="cli"})
/
sum(claude_code_active_time_seconds_total{type="user"})
Lines per Dollar
sum(sum_over_time(claude_code_lines_of_code_count_total[$__range]))
/
sum(increase(claude_code_cost_usage_USD_total[$__range]))
Equivalent Developer Hours (assuming 75 lines/hour)
sum(sum_over_time(claude_code_lines_of_code_count_total[$__range])) / 75
Max Plan ROI (for $200/month subscribers)
sum(increase(claude_code_cost_usage_USD_total[$__range]))
/ (6.67 * ($__range_s / 86400))
Handling Delta Metrics
claude_code_lines_of_code_count_total is a delta metric, so use sum_over_time() instead of increase():
# Incorrect – yields extrapolated values
sum(increase(claude_code_lines_of_code_count_total[$__range]))
# Correct
sum(sum_over_time(claude_code_lines_of_code_count_total[$__range]))
7. Sample Output (One Hour)
- 27,000 lines of code
- 11 minutes of user time
- 362× velocity multiplier
- $47 K equivalent output value
The productivity ratio peaked above 10,000× when running multiple parallel agents.
8. Exporting to Other OTLP Backends
The OTEL exporter works with any OTLP‑compatible endpoint. Simply change the endpoint variable:
export OTEL_EXPORTER_OTLP_ENDPOINT=https://your-backend-endpoint
For Datadog, point to their OTLP intake URL; the metric names remain the same.
9. Future Enhancements
- Alerts when the productivity ratio drops (e.g., you’re stuck).
- Cost projections based on current burn rate.
- Comparison panels for different projects or teams.
If you extend this setup, feel free to share your results!