> For the complete documentation index, see [llms.txt](https://help.swarmia.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.swarmia.com/settings/integrations/ai-coding-tool-integrations/claude-code-integration/claude-code-otel-collector.md).

# Send Claude Code OpenTelemetry metrics to multiple destinations

Send Claude Code OpenTelemetry metrics to Swarmia and another destination

Claude Code can send metrics to only one OpenTelemetry endpoint. If you already send Claude Code metrics to another destination, use an OpenTelemetry Collector to receive them once and forward them to both destinations.

```
Claude Code → OpenTelemetry Collector → Swarmia
                                      → Your metrics backend
```

A collector is the appropriate choice for this setup. `OTEL_METRICS_EXPORTER=console,otlp` selects multiple exporter *types*, not two OTLP endpoints.

## Use a local collector

Run one collector on each engineer's machine whenever possible. This is the safest setup because each collector receives metrics from only one person. It also keeps the receiver on `localhost` rather than exposing it on your network.

Install an [OpenTelemetry Collector distribution that includes the `otlp` receiver and `otlphttp` exporter ↗](https://opentelemetry.io/docs/collector/). Then create this configuration:

```yaml
# config.yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 127.0.0.1:4317
      http:
        endpoint: 127.0.0.1:4318

exporters:
  otlphttp/swarmia:
    metrics_endpoint: https://hook.swarmia.com/otel/v1/metrics
    encoding: json
    headers:
      Authorization: ${env:SWARMIA_OTEL_AUTHORIZATION_TOKEN}

  otlphttp/customer:
    metrics_endpoint: ${env:CUSTOMER_OTEL_METRICS_ENDPOINT}
    encoding: proto
    headers:
      Authorization: ${env:CUSTOMER_OTEL_AUTHORIZATION_HEADER}

service:
  pipelines:
    metrics:
      receivers: [otlp]
      exporters: [otlphttp/swarmia, otlphttp/customer]
```

Set the environment variables for the process that runs the collector:

```bash
export SWARMIA_OTEL_AUTHORIZATION_TOKEN='<AUTHORIZATION_TOKEN>'
export CUSTOMER_OTEL_METRICS_ENDPOINT='https://metrics.example.com/v1/metrics'
export CUSTOMER_OTEL_AUTHORIZATION_HEADER='Bearer <CUSTOMER_TOKEN>'
```

`SWARMIA_OTEL_AUTHORIZATION_TOKEN` is the value after `Authorization=` in the [direct Claude Code configuration](/settings/integrations/ai-coding-tool-integrations/claude-code-integration.md#opentelemetry-monitoring). `CUSTOMER_OTEL_METRICS_ENDPOINT` must be your backend's full metrics ingest URL. Change the customer exporter's encoding and headers to match your backend. For a gRPC-only backend, use the Collector's OTLP gRPC exporter for the customer destination instead.

These examples use `otlphttp`, which works with older Collector releases and remains a deprecated alias in releases from January 2026 onward. If your Collector uses the newer component name, replace `otlphttp` with `otlp_http` everywhere in the configuration.

{% hint style="warning" %}
Pass the Swarmia pipeline through unchanged. Don't add a `batch` processor or another processor that combines or reconstructs metric payloads. Also don't use processors that modify resource attributes, metric names, or datapoint attributes, including `resource`, `transform`, `attributes`, or `resourcedetection` with its default `override: true` setting. Rewriting `service.name` can cause Swarmia to drop data, and removing or hashing `user.email` prevents attribution.
{% endhint %}

{% hint style="info" %}
Claude Code must use `delta` temporality for Swarmia. This can change what your existing backend receives. If it requires cumulative metrics, use a `deltatocumulative` processor in its own customer-only pipeline. Never add it to the Swarmia pipeline.
{% endhint %}

Start the collector with its `config.yaml` file. The command depends on the distribution you install, but is commonly `otelcol --config config.yaml`.

## Keep a local collector running

Claude Code configures the metrics endpoint, but it doesn't start or manage a Collector. Run the Collector as a background service so it is available whenever someone starts Claude Code.

Choose the deployment option that fits your environment:

* **Per-user operating system service:** Use a `launchd` agent on macOS, a `systemd --user` service on Linux, or a Windows service or scheduled task. This is the best option for managed fleets because the operating system starts and restarts the Collector for each engineer.
* **Docker Compose:** If Docker is already standard in your environment, run the Collector with `docker compose up -d` and a `restart: unless-stopped` policy. Map only `127.0.0.1:4318` on the host, and map `127.0.0.1:4317` too if you use gRPC. In the container's Collector configuration, use `0.0.0.0` for each exposed receiver endpoint so Docker can expose the port. See the [OpenTelemetry Collector Docker guide ↗](https://opentelemetry.io/docs/collector/install/docker/).
* **IT-managed installation:** Use your device management tool to install the Collector configuration, set its environment variables, and register one of the background services above. Keep authorization tokens in the service or secret configuration, not in the Claude Code settings file.

{% hint style="info" %}
As an optional convenience, a [Claude Code `SessionStart` hook ↗](https://code.claude.com/docs/en/hooks) can run a fast, idempotent script that checks whether the background service is running. Don't use it as the primary way to run the Collector: it doesn't supervise the process, and it can run whenever Claude Code starts or resumes a session. The script should start no foreground process and write nothing to standard output.
{% endhint %}

## Point Claude Code to the collector

Use the [Claude Code OpenTelemetry configuration](/settings/integrations/ai-coding-tool-integrations/claude-code-integration.md#opentelemetry-monitoring) as the basis for your settings. Make these changes:

* Set `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` to `http://127.0.0.1:4318/v1/metrics`.
* Remove `OTEL_EXPORTER_OTLP_HEADERS`. The Swarmia authorization token now belongs in the collector environment instead.
* Keep `OTEL_EXPORTER_OTLP_PROTOCOL` as `http/json` and `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` as `delta`.

The configuration above also enables gRPC on port `4317`. If Claude Code already sends to your Collector with gRPC, keep `OTEL_EXPORTER_OTLP_PROTOCOL` as `grpc` and set `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` to `http://127.0.0.1:4317`. Only the Collector-to-Swarmia connection must use HTTP with JSON encoding.

For example:

```json
{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_METRICS_EXPORTER": "otlp",
    "OTEL_EXPORTER_OTLP_PROTOCOL": "http/json",
    "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "http://127.0.0.1:4318/v1/metrics",
    "OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": "delta",
    "OTEL_METRIC_EXPORT_INTERVAL": "600000"
  }
}
```

If you use a third-party platform such as Amazon Bedrock, Google Vertex AI, Microsoft Foundry, or LiteLLM, also keep the required `OTEL_RESOURCE_ATTRIBUTES` setting from the Claude Code configuration.

## Use a centralized collector

A centralized collector can work, but treat it as an advanced deployment. It must forward each user's metric payload to Swarmia separately. Identifying users with a `user.email` attribute isn't enough if the collector combines their data in one outbound payload.

In addition to the requirements for a local collector:

* Route only Claude Code metrics to the Swarmia exporter. Don't add the Swarmia exporter to a common pipeline that receives all your organization's telemetry. Use a filter processor that drops metrics unless `resource.attributes["service.name"]` is `claude-code` or `claude-code-desktop`, or use equivalent routing to a dedicated Swarmia pipeline.
* Don't use a `batch` processor or any other processing that combines payloads before the Swarmia exporter.
* Secure the network-facing receiver with TLS, authentication, and appropriate network access controls.
* Keep `delta` temporality in Claude Code.

Keep the Swarmia pipeline separate from your other metrics pipeline. This lets you filter Claude Code metrics for Swarmia and, when needed, convert delta metrics to cumulative only for your other backend.

## Verify the setup

Make some Claude Code activity, then check the latest event timestamp in [Settings → AI tools → Claude Code](https://app.swarmia.com/settings/ai-assistants). It updates in real time when Swarmia accepts the data, so it helps identify a misconfigured filtering or forwarding pipeline. The usage metrics themselves can take up to 24 hours to appear.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://help.swarmia.com/settings/integrations/ai-coding-tool-integrations/claude-code-integration/claude-code-otel-collector.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
