# Send Claude Code Telemetry to Bindplane

[Claude Code](https://code.claude.com/docs/en/monitoring-usage) exports OpenTelemetry metrics and events to any OTLP endpoint — covering per-session API cost, token counts, and tool-use activity. Routing that data through Bindplane lets you forward it to any backend you already use (Datadog, Splunk, a SIEM, or anything else) and monitor usage across your entire team from one place, without each developer configuring their own export target.

## Prerequisites

Network access from the host running Claude Code to the collector's OTLP ports:

* `4317` for gRPC
* `4318` for HTTP

{% hint style="info" %}
If the collector runs in Kubernetes, use the in-cluster service DNS names instead of a hostname. See the Kubernetes section below.
{% endhint %}

## Step 1: Configure the Bindplane Configuration

1. Open an existing Bindplane configuration or create a new one.
2. Add the **OpenTelemetry (OTLP)** source. It listens on port 4317 (gRPC) and 4318 (HTTP) on all interfaces by default. Enable TLS if your environment requires it — see the [OTLP source documentation](https://app.gitbook.com/s/gmiOMzBfoNFwmKJFHMcJ/integrations/sources/opentelemetry-otlp) for options.

<figure><img src="https://4134819172-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FA6BP9V0wfJj4LZdQH6OJ%2Fuploads%2Fgit-blob-a0b9e4b5d7879acd26d977b2514fd30c002f9faf%2Fhow-to-guides-send-claude-code-telemetry-to-bindplane-image-1.png?alt=media" alt="Bindplane docs - Send Claude Code telemetry to Bindplane - image 1"><figcaption></figcaption></figure>

3. Add a destination. Any logging or metrics backend works. If you just want to confirm data is flowing, the **Dev Null** destination writes telemetry to `/dev/null` and is the simplest option for initial testing.

<figure><img src="https://4134819172-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FA6BP9V0wfJj4LZdQH6OJ%2Fuploads%2Fgit-blob-70cc4122297d7750dd624f2dacb7ee43725b88f5%2Fhow-to-guides-send-claude-code-telemetry-to-bindplane-image-2.png?alt=media" alt="Bindplane docs - Send Claude Code telemetry to Bindplane - image 2"><figcaption></figcaption></figure>

4. Roll out the configuration to the collector(s) that will receive Claude Code telemetry.

<figure><img src="https://4134819172-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FA6BP9V0wfJj4LZdQH6OJ%2Fuploads%2Fgit-blob-2ecb5fb937e40cdf9762da8b53e26a1a38d1ba39%2Fhow-to-guides-send-claude-code-telemetry-to-bindplane-image-3.png?alt=media" alt="Bindplane docs - Send Claude Code telemetry to Bindplane - image 3"><figcaption></figcaption></figure>

5. Note the collector's hostname or IP — you'll need it in the next step (for example, `collector.example.com` or `localhost` if you're running the collector locally).

## Step 2: Enable telemetry in Claude Code

Set these environment variables before running `claude`. Replace `<collector-host>` with your collector's hostname or IP.

#### OTLP GRPC

```bash
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://<collector-host>:4317
```

#### OTLP HTTP

```bash
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=http://<collector-host>:4318
```

#### Run Claude

Then run `claude` in the same shell session.

```
claude
```

### Make it permanent

Exporting variables each session gets old fast. Add them to your shell profile so they apply automatically:

```bash
# Add to ~/.zshrc or ~/.bashrc
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://<collector-host>:4317
```

Alternatively, create a `.env` file in your project directory and load it with `source .env` or a tool like [`direnv`](https://direnv.net/).

### Authentication

If your OTLP endpoint requires a header (for example, an API key), set `OTEL_EXPORTER_OTLP_HEADERS`:

```bash
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer your-token"
```

For mutual TLS, the Claude Code monitoring docs cover the client cert and key variables.

### Organization-wide rollout

Administrators can configure these variables in the [managed settings file](https://code.claude.com/docs/en/monitoring-usage#administrator-configuration) so that all users automatically send telemetry to Bindplane without any per-developer setup.

## Step 3: Verify data is flowing

The first metric export happens after `OTEL_METRIC_EXPORT_INTERVAL` milliseconds (default: 60,000 ms — one minute). Start a Claude Code session, run a prompt or two, then wait for the interval to pass before checking.

To verify in Bindplane, open the configuration and click a **Processor Node** in the Configuration.

<figure><img src="https://4134819172-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FA6BP9V0wfJj4LZdQH6OJ%2Fuploads%2Fgit-blob-64e8513720b988cf31ba4573d4a02b21289107f0%2Fhow-to-guides-send-claude-code-telemetry-to-bindplane-image-4.png?alt=media" alt="Bindplane docs - Send Claude Code telemetry to Bindplane - image 4"><figcaption></figcaption></figure>

Look for telemetry with the attribute `service.name=claude-code`. That attribute is present on every record Claude Code exports, so it's the fastest way to confirm the right data is coming in.

### Key metrics and events

| Signal      | Name                              | What it represents                                              |
| ----------- | --------------------------------- | --------------------------------------------------------------- |
| Metric      | `claude_code.cost.usage`          | Per-session API cost                                            |
| Metric      | `claude_code.token.usage`         | Input, output, and cache token counts (labeled by `token.type`) |
| Metric      | `claude_code.session.count`       | Number of sessions started                                      |
| Metric      | `claude_code.lines_of_code.count` | Lines of code added or removed                                  |
| Event (log) | `claude_code.api_request`         | Each request sent to the Claude API                             |
| Event (log) | `claude_code.user_prompt`         | Each prompt submitted by the user                               |
| Event (log) | `claude_code.tool_result`         | Result returned from a tool call                                |

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

## Troubleshooting

**No data after waiting 60+ seconds**

Check that `CLAUDE_CODE_ENABLE_TELEMETRY=1` is set in the same shell where you run `claude` — a variable exported in a different terminal won't carry over. Confirm the endpoint value matches the collector's address, and verify the collector is reachable:

```bash
curl http://<collector-host>:4318/
```

A connection error here means the collector is not reachable, not that telemetry is missing.

**Connection refused**

The collector process may not be running, or a firewall is blocking the port. Confirm the collector is up and that inbound traffic on 4317 or 4318 is allowed from the host running Claude Code.

**Wrong protocol error**

gRPC (port 4317) and HTTP/protobuf (port 4318) are not interchangeable. If you're using port 4318, you must also set `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf`. Leaving the protocol as `grpc` while pointing at 4318 (or vice versa) will produce connection or serialization errors.

## Kubernetes

If the Bindplane collector runs inside the cluster, use the in-cluster service DNS name as the endpoint. Claude Code (or the workload running it) must be able to reach the service — either from within the same cluster or via appropriate network policy.

**Gateway collector:**

| Protocol | Service type       | Endpoint                                                                  |
| -------- | ------------------ | ------------------------------------------------------------------------- |
| gRPC     | clusterIP          | `bindplane-gateway-agent.bindplane-agent.svc.cluster.local:4317`          |
| gRPC     | headless clusterIP | `bindplane-gateway-agent-headless.bindplane-agent.svc.cluster.local:4317` |
| HTTP     | clusterIP          | `http://bindplane-gateway-agent.bindplane-agent.svc.cluster.local:4318`   |

**Node (DaemonSet) collector:**

| Protocol | Service type       | Endpoint                                                               |
| -------- | ------------------ | ---------------------------------------------------------------------- |
| gRPC     | clusterIP          | `bindplane-node-agent.bindplane-agent.svc.cluster.local:4317`          |
| gRPC     | headless clusterIP | `bindplane-node-agent-headless.bindplane-agent.svc.cluster.local:4317` |
| HTTP     | clusterIP          | `http://bindplane-node-agent.bindplane-agent.svc.cluster.local:4318`   |

If DaemonSet resource consumption is a concern, prefer the Gateway collector — it scales independently of cluster size.

## Security and privacy

Tool events can include bash commands and file paths in `tool_parameters`. If your commands or paths may contain secrets, configure your telemetry backend or a Bindplane processor to filter or redact `tool_parameters` before the data reaches its destination.

By default, user prompt content and MCP/skill names are not included in telemetry — only prompt length is recorded. To include full prompt content or detailed tool parameters, set `OTEL_LOG_USER_PROMPTS=1` and/or `OTEL_LOG_TOOL_DETAILS=1`. Only enable these when you have a specific need and understand the data that will be exported.

See the [Security and privacy](https://code.claude.com/docs/en/monitoring-usage#security-and-privacy) section in Claude's monitoring docs for the full details.
