For the complete documentation index, see llms.txt. This page is also available as Markdown.

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 ↗. Then create this configuration:

# 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:

SWARMIA_OTEL_AUTHORIZATION_TOKEN is the value after Authorization= in the direct Claude Code configuration. 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.

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.

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 ↗.

  • 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.

As an optional convenience, a Claude Code SessionStart hook ↗ 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.

Point Claude Code to the collector

Use the Claude Code OpenTelemetry configuration 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:

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. 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.

Last updated

Was this helpful?