Observability stack for collecting and visualizing Claude Code telemetry.
- Docker and Docker Compose
-
Copy and configure environment variables:
cp .env.example .env
Set
GRAFANA_ADMIN_PASSWORDin.envto a strong password before starting. -
Start the stack:
docker compose up -d
-
Configure Claude Code to send telemetry:
export CLAUDE_CODE_ENABLE_TELEMETRY=1 export OTEL_METRICS_EXPORTER=otlp export OTEL_LOGS_EXPORTER=otlp export OTEL_EXPORTER_OTLP_PROTOCOL=grpc export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
-
Access Grafana at http://localhost:3500 (credentials from .env)
The dashboards assume the standard Claude Code metric set and labels. See docs/metrics.md for the mapping between Claude Code metric names and the Prometheus names used in Grafana.
If you want the Project filter to work, define a project resource attribute for each environment:
export OTEL_RESOURCE_ATTRIBUTES="project=my-project"Session-level dashboards require OTEL_METRICS_INCLUDE_SESSION_ID=true (default is true).
Model filtering only applies to cost and token panels; session-level metrics are not model-scoped.
This repo uses promtail to scrape transcript logs; OTEL log events from the spec are not ingested into Loki by default.
The "Most Used Commands" panel extracts program names from Bash tool events and is always available. The "Most Used Skills" panel requires an additional environment variable to capture skill names:
export OTEL_LOG_TOOL_DETAILS=1| Service | Port | Description |
|---|---|---|
| Grafana | 3500 | Dashboards |
| Prometheus | 9090 | Metrics storage |
| OTEL Collector | 4317 | OTLP gRPC endpoint |
| OTEL Collector | 4318 | OTLP HTTP endpoint |
The stack can export telemetry to Grafana Cloud in addition to the local stack. By default the local-only configs are used — the cloud exporters are only loaded when you switch to the cloud config files via env vars.
- In Grafana Cloud Portal, open your stack.
- Go to Security → Access Policies and create a new access policy with these scopes:
metrics:write— push OTEL metricslogs:write— push OTEL logs and Loki transcript logstraces:write— (optional, for future trace support)
- Generate a token for the policy — this is your
GRAFANA_CLOUD_API_TOKEN. - Find your instance ID and OTLP endpoint under Connections → OpenTelemetry.
- Find your Loki push URL under Connections → Data sources → Loki (the "URL" field).
Copy .env.example to .env and uncomment the cloud section:
# Switch to cloud-enabled collector configs
OTEL_COLLECTOR_CONFIG=otel-collector-config-cloud.yaml
PROMTAIL_CONFIG=promtail-config-cloud.yaml
# OTEL metrics + logs (via OTEL Collector)
GRAFANA_CLOUD_OTLP_ENDPOINT=https://otlp-gateway-<region>.grafana.net/otlp
GRAFANA_CLOUD_INSTANCE_ID=<numeric-instance-id>
GRAFANA_CLOUD_API_TOKEN=<your-api-token>
# Loki transcript logs (via Promtail) — instance ID and token are reused
GRAFANA_CLOUD_LOKI_ENDPOINT=https://logs-prod-<region>.grafana.net/loki/api/v1/pushRestart the stack after adding credentials:
docker compose up -d --force-recreate otel-collector promtailImport the dashboard JSON from grafana/dashboards/claude-code.json into your Grafana Cloud instance via Dashboards → Import. Datasources are resolved automatically via template variables — no manual remapping needed.
Note: Recording rules defined in
recording-rules.ymlmust be recreated manually in Grafana Cloud under Alerting → Alert rules (Mimir recording rules). Panels that rely on recording rules will show no data until they are created.
docker compose down