Claude Code can export OpenTelemetry (OTel) data to track usage, costs, and tool activity. This is opt-in and requires explicit configuration.

Quick Start

1. Enable Telemetry

export CLAUDE_CODE_ENABLE_TELEMETRY=1

Or in .claude/settings.json:

{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1"
  }
}

2. Choose Exporters

# Export metrics
export OTEL_METRICS_EXPORTER=otlp

# Export events/logs
export OTEL_LOGS_EXPORTER=otlp

# Or console for debugging
export OTEL_METRICS_EXPORTER=console

3. Configure Endpoint

export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

4. Optional: Authentication

export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer your-token"

5. Start Claude Code

claude

Metrics and events will now be exported to your collector.

Exporter Options

OTLP (OpenTelemetry Protocol)

Standard protocol — works with most backends.

export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

Backends:

  • OpenTelemetry Collector
  • Datadog
  • New Relic
  • Honeycomb
  • Jaeger

Prometheus

For metrics directly into Prometheus:

export OTEL_METRICS_EXPORTER=prometheus

Starts a Prometheus endpoint on port 8888.

Console

For debugging — metrics are printed to console:

export OTEL_METRICS_EXPORTER=console
export OTEL_METRIC_EXPORT_INTERVAL=10000  # Every 10 seconds

Configuration

Environment Variables

Variable Description Example
CLAUDE_CODE_ENABLE_TELEMETRY Enable telemetry (MUST be set) 1
OTEL_METRICS_EXPORTER Metrics exporter otlp, prometheus, console
OTEL_LOGS_EXPORTER Logs/events exporter otlp, console
OTEL_EXPORTER_OTLP_ENDPOINT OTLP collector endpoint http://localhost:4317
OTEL_EXPORTER_OTLP_PROTOCOL OTLP protocol grpc, http/json, http/protobuf
OTEL_EXPORTER_OTLP_HEADERS Auth headers Authorization=Bearer token
OTEL_METRIC_EXPORT_INTERVAL Export interval in ms 60000 (default)
OTEL_LOGS_EXPORT_INTERVAL Logs export interval 5000 (default)

Cardinality Control

Reduce metrics cardinality (less storage):

export OTEL_METRICS_INCLUDE_SESSION_ID=false
export OTEL_METRICS_INCLUDE_ACCOUNT_UUID=false
export OTEL_METRICS_INCLUDE_VERSION=false

Available Metrics

Sessions

claude_code.session.count

Counter: New sessions started.

Attributes:

  • session.id
  • user.email
  • organization.id

Code Changes

claude_code.lines_of_code.count

Counter: Lines added/removed.

Attributes:

  • type: "added" or "removed"

Commits

claude_code.commit.count

Counter: Git commits created.

Pull Requests

claude_code.pull_request.count

Counter: PRs created.

Token Usage

claude_code.token.usage

Counter: Tokens used.

Attributes:

  • type: "input", "output", "cacheRead", "cacheCreation"
  • model: Model used

Cost

claude_code.cost.usage

Counter: Estimated costs in USD.

Attributes:

  • model: Model name

Tool Decisions

claude_code.code_edit_tool.decision

Counter: Code-edit approvals (accept/reject).

Attributes:

  • tool_name: "Edit", "Write", "NotebookEdit"
  • decision: "accept" or "reject"
  • language: Programming language

Active Time

claude_code.active_time.total

Counter: Active time in seconds (without idle).

Attributes:

  • type: "user" (keyboard) or "cli" (tool execution)

Available Events

User Prompt Event

When user enters a prompt.

Field: claude_code.user_prompt

Data:

  • prompt_length
  • prompt (optional, enable with OTEL_LOG_USER_PROMPTS=1)

Tool Result Event

When a tool execution completes.

Field: claude_code.tool_result

Data:

  • tool_name
  • success: true/false
  • duration_ms
  • error (if failed)

API Request Event

For each Claude API request.

Field: claude_code.api_request

Data:

  • model
  • cost_usd
  • duration_ms
  • input_tokens
  • output_tokens
  • cache_read_tokens
  • cache_creation_tokens

API Error Event

When API request fails.

Field: claude_code.api_error

Data:

  • model
  • error
  • status_code
  • attempt (retry number)

Dynamic Headers (Enterprise)

For organizations with dynamic authentication (token refresh):

{
  "otelHeadersHelper": "/bin/generate_headers.sh"
}

Script must return JSON headers:

#!/bin/bash
echo "{\"Authorization\": \"Bearer $(get-token.sh)\"}"

Refreshed every 29 minutes. Interval configurable:

export CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS=900000

Dashboards & Analysis

With Prometheus/Grafana

  1. Export metrics to Prometheus
  2. Create Grafana dashboard
  3. Query metrics:
rate(claude_code_token_usage_total{type="input"}[5m])

With Datadog

Connect Datadog OTel receiver:

export OTEL_EXPORTER_OTLP_ENDPOINT=http://datadog-agent:4317
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer $DD_API_KEY"

Metrics appear automatically in Datadog.

With Honeycomb

Use Honeycomb as OTel receiver:

export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io
export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=$HC_API_KEY"

Team Multi-Tenancy

For organizations with multiple teams:

export OTEL_RESOURCE_ATTRIBUTES="department=engineering,team.id=platform,cost_center=eng-123"

All metrics are tagged with these attributes.

Formatting rules:

  • Comma-separated key=value pairs
  • No spaces in values
  • Percent-encode special characters
# WRONG
export OTEL_RESOURCE_ATTRIBUTES="team=My Team"

# CORRECT
export OTEL_RESOURCE_ATTRIBUTES="team=my_team"

ROI Measurement

Base Metrics

Metric Description Formula
LOC/Session Code per session total_lines_added / session_count
Cost/LOC Cost per line total_cost / total_lines_added
Time Saved Estimated time commits_count * avg_commit_time
Commits/Day Velocity commits_count / days

Calculate ROI

ROI % = ((Time_Saved * Hourly_Rate) - Total_Cost) / Total_Cost * 100

Example:

  • Time saved: 40 hours (400 commits × 6 min each)
  • Hourly rate: $100
  • Total cost: $500 (tokens)
ROI = ((40 × 100) - 500) / 500 × 100 = 7,900%

Cost Optimization

# Reduce export interval if unnecessary overhead
export OTEL_METRIC_EXPORT_INTERVAL=120000  # 2 minutes instead of 60s

# Disable session ID if cardinality is a problem
export OTEL_METRICS_INCLUDE_SESSION_ID=false

# Reduce event logging
export OTEL_LOG_USER_PROMPTS=0
export OTEL_LOG_TOOL_DETAILS=0

Security & Privacy

What Gets Collected

ALWAYS:

  • Session ID
  • User email (if OAuth)
  • Organization ID
  • Token counts
  • Cost
  • Tool names

ONLY if enabled:

  • User prompt content (OTEL_LOG_USER_PROMPTS=1)
  • MCP/skill names (OTEL_LOG_TOOL_DETAILS=1)

What Does NOT Get Collected

  • File contents
  • Raw code
  • Secrets/API keys
  • Passwords

Redaction & Filtering

Your backend can filter telemetry:

# Only public metrics
rate(claude_code_cost_usage_total[5m])

# Exclude sensitive orgs
rate(claude_code_token_usage_total{organization_id!="private"}[5m])

Troubleshooting

Metrics Not Arriving

  1. Check if enabled:

    echo $CLAUDE_CODE_ENABLE_TELEMETRY
    
  2. Check if endpoint reachable:

    curl http://localhost:4317/healthz
    
  3. Check if exporter configured:

    echo $OTEL_METRICS_EXPORTER
    

Too Many Metrics (Cardinality Issue)

Problem: claude_code.session.count with every session ID creates 10000+ time series.

Solutions:

# Disable session ID
export OTEL_METRICS_INCLUDE_SESSION_ID=false

# Or use organization ID aggregation
export OTEL_RESOURCE_ATTRIBUTES="organization.id=org-1"

Authentication Failed

# Check if token valid
echo $OTEL_EXPORTER_OTLP_HEADERS

# Test with curl
curl -H "$OTEL_EXPORTER_OTLP_HEADERS" \
  http://your-collector:4317/metrics

Further Resources


Last updated: 2026-03-21 | Claude Code Monitoring & Telemetry Reference