[DOCS] Clarify that OTEL telemetry exports events via logs protocol, not metrics
Description
The monitoring documentation mentions configuring both OTEL_METRICS_EXPORTER and OTEL_LOGS_EXPORTER, which implies Claude Code exports both traditional OTel metrics and logs. However, the actual telemetry data (token usage, tool calls, API requests, etc.) is exported exclusively via the logs/events protocol, not as OTel metrics.
This caused confusion when setting up an OTel collector + ClickHouse pipeline - we spent time looking for data in otel_metrics_* tables when it was actually in otel_logs.
Expected Behavior (from docs)
-
OTEL_METRICS_EXPORTER=otlpwould export time-series metrics -
OTEL_LOGS_EXPORTER=otlpwould export log events
Actual Behavior
- All Claude Code telemetry (token counts, tool usage, API requests, costs) is exported as events via the logs protocol
- Setting
OTEL_METRICS_EXPORTERdoesn't appear to export any traditional OTel metrics -
OTEL_RESOURCE_ATTRIBUTESworks correctly for logs/events ✅
Additional Context
What works well:
-
OTEL_RESOURCE_ATTRIBUTES="team=my-team"correctly applies to all log events - Events like
claude_code.api_request,claude_code.tool_result,claude_code.user_promptcontain rich data inLogAttributes
Suggested doc improvements:
- Clarify that Claude Code exports events via OTel logs, not traditional metrics
- Explain that "metrics" like token usage are attributes on events, not separate metric signals
- Add example queries for backends like ClickHouse showing how to query
otel_logstables - Clarify what
OTEL_METRICS_EXPORTERactually does (if anything)
Environment
- Claude Code version: 2.0.76
- OS: macOS (Darwin 24.6.0)
cc: @avishkarsonni (Avishkar Sonni) - co-investigated this issue
Update: Claude Code Does Export Native OTEL Metrics
After extensive testing, I can confirm that Claude Code does export both native OTEL metrics AND log events. The confusion stems from several gotchas that make the metrics hard to discover.
Native Metrics Exported
Claude Code exports these metrics via the com.anthropic.claude_code instrumentation scope:
| Metric | Description |
|---|---|
claude_code.cost.usage |
Cumulative cost in USD (labels: model, session_id, user_email, org_id) |
claude_code.token.usage |
Token counts (labels: type=input/output/cache_read/cache_creation, model) |
claude_code.active_time.total |
Active session time in seconds |
claude_code.session.count |
Sessions started |
Why They're Hard to Find
-
Delta Temporality: The metrics use delta temporality, which Prometheus doesn't natively support. You need a
deltatocumulativeprocessor in your OTEL Collector pipeline. -
Dot-notation Names: In Prometheus,
claude_code.cost.usagebecomesclaude_code_cost_usage_USD_total(dots to underscores, unit suffix added). -
Export Interval: Default export interval may be slow. Setting
OTEL_METRIC_EXPORT_INTERVAL=5000(5 seconds) helps.
Working Configuration
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
"OTEL_METRIC_EXPORT_INTERVAL": "5000"
}
}
Log Events Still Valuable
The log events (api_request, tool_result, etc.) contain richer per-request details that the native metrics don't provide:
-
cost_usd,duration_msper request -
cache_read_tokens,cache_creation_tokens -
tool_namefor each tool invocation
These can be converted to metrics using OTEL Collector's signaltometrics connector if needed.
Gotcha: Attribute Values Are Strings
When converting log attributes to metrics, note that numeric values are exported as strings:
cost_usd: Str(0.051199) // Not Double\!
Use Double(attributes["cost_usd"]) in OTTL expressions.
TL;DR: The documentation is technically correct - Claude Code exports both metrics and logs. But the metrics are easy to miss due to delta temporality and naming conventions. The docs could be improved by documenting the specific metric names and the deltatocumulative requirement for Prometheus users.