# Observe Claude Code with OpenTelemetry

Claude Code exports its own usage data over OpenTelemetry: metrics for sessions, tokens, and cost, structured events for prompts, tool calls, and API errors, and optional traces for individual interactions. Point that export at [Better Stack](https://betterstack.com/) to see how your team uses Claude Code, what it costs, and where it fails, with no extra instrumentation.


## Prerequisites

You need Claude Code installed and authenticated, and a Better Stack **Telemetry source** to receive the data.

Create one in **Telemetry → Sources → [Connect source](https://telemetry.betterstack.com/team/0/sources/new ";_blank")**, or read more in the [Quick start guide](https://betterstack.com/docs/logs/logging-start/#starting-with-centralized-logging). Select the **OpenTelemetry** platform, then copy the **source token** and **ingesting host** shown for the source.

[info]
#### Use the ingesting host from your source
Copy the ingesting host exactly as shown for your source. It already points to your team's data region, so your metrics and logs land in the right place.
[/info]

## Connect Claude Code to Better Stack

There are two ways to send the data. Use the settings file to keep telemetry on across sessions, or shell variables to turn it on for a single terminal session. Either way, replace `$INGESTING_HOST` and `$SOURCE_TOKEN` with the values from your source.

### Keep telemetry on across sessions

Add the variables to your Claude Code settings file. `~/.claude/settings.json` applies to every project, while a project's `.claude/settings.json` applies to that project and can be committed to source control.

```json
[label ~/.claude/settings.json]
{
  "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://$INGESTING_HOST",
    "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer $SOURCE_TOKEN"
  }
}
```

### Turn telemetry on for one session

Export the variables in your shell before starting Claude Code. They apply only to that terminal session.

```bash
[label Enable telemetry for one session]
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=https://$INGESTING_HOST
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer $SOURCE_TOKEN"
```

Better Stack ingests OpenTelemetry over HTTP, so with the `http/protobuf` protocol Claude Code appends the per-signal paths `/v1/metrics` and `/v1/logs` to the endpoint for you.

Claude Code reads telemetry configuration only at startup, so restart it after any change.

## Verify the data is arriving

Start Claude Code:

```bash
[label Start Claude Code]
claude
```

At the prompt, give it a small task so it exercises the model and a tool. For example:

```text
[label Example prompt]
Create a file called hello.py that prints "Hello from Better Stack", then run it.
```

Approve the action when Claude Code asks. This one task produces a `claude_code.user_prompt`, one or more `claude_code.api_request` events, a `claude_code.tool_decision` and `claude_code.tool_result` for the file it writes and runs, and a `claude_code.assistant_response`.

Open [Live tail](https://telemetry.betterstack.com/team/0/tail ";_blank") in Better Stack. Within a minute you should see those `claude_code.*` events.

![Live tail showing Claude Code events arriving in Better Stack](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/e9fbf2b2-369b-4b8b-df15-6a7cd557ac00/lg2x =3012x1500)

[info]
#### Can't see any data?
Run `claude --debug` and look for OpenTelemetry export errors. Check that the ingesting host and source token match your source, and remember that Claude Code reads telemetry configuration only at startup.
[/info]

## What Claude Code exports

Claude Code emits these metrics, each attributable by user, team, and model:

- `claude_code.session.count`: sessions started
- `claude_code.cost.usage`: estimated spend in USD
- `claude_code.token.usage`: tokens used, with a `type` label of `input`, `output`, `cacheCreation`, or `cacheRead`
- `claude_code.lines_of_code.count`: lines added or removed
- `claude_code.commit.count`: git commits created
- `claude_code.pull_request.count`: pull requests opened
- `claude_code.code_edit_tool.decision`: edit permission decisions, with a `decision` label of `accept` or `reject`
- `claude_code.active_time.total`: active time in seconds

For the full list of metrics, events, and attributes, see the [Claude Code monitoring documentation](https://code.claude.com/docs/en/monitoring-usage#available-metrics-and-events).

## Capture prompts, tool calls, and traces

Claude Code redacts prompt text and tool details by default. To include them, add these variables to the `env` block:

```json
[label Capture prompt and tool content]
{
  "env": {
    "OTEL_LOG_USER_PROMPTS": "1",
    "OTEL_LOG_TOOL_DETAILS": "1"
  }
}
```

[info]
#### Review the privacy impact first
These variables send prompt text, commands, file paths, and other potentially sensitive content to your source. Enable them only where that is acceptable.
[/info]

Claude Code can also export distributed traces that link each prompt to the API requests and tool executions it triggers. This capability is currently in beta. To turn it on, add `"CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1"` and `"OTEL_TRACES_EXPORTER": "otlp"` to the same `env` block. Traces reach Better Stack at the same endpoint. See [Tracing](https://betterstack.com/docs/logs/tracing/) for how to explore them.

## What to do next

- [Query your telemetry](https://betterstack.com/docs/logs/using-logtail/live-tail-query-language/) with the live tail query language.
- [Extract metrics from logs](https://betterstack.com/docs/logs/dashboards/logs-to-metrics/) to chart usage and cost over time.
- [Set up alerts](https://betterstack.com/docs/logs/dashboards/alerts/) for cost spikes or a rising API error rate.
- [Query your data through the MCP server](https://betterstack.com/docs/getting-started/integrations/mcp/) straight from Claude Code.

## Need help?

Please let us know at hello@betterstack.com.  
We're happy to help! 🙏