OTEL telemetry stopped working after auto-update to v2.1.72 with OTEL_LOG_TOOL_DETAILS: 1 and elastic apm 8.*

Status Closed — not planned
Reported on v2.1.72
Maintainer reply None cached
Activity 12 comments · opened Mar 10, 2026 · closed May 26, 2026

Bug Description

OpenTelemetry (OTEL) telemetry stopped working after auto-updating to v2.1.72 today. Data was confirmed to be flowing correctly on v2.1.71 (and presumably v2.1.70) but no activity is visible after the upgrade.

Environment

  • Claude Code version: 2.1.72 (auto-updated 2026-03-10)
  • Previous working version: 2.1.71
  • OS: Linux (AWS, kernel 6.17.0-1007-aws)
  • OTEL backend: Elastic APM via OTLP HTTP (http/protobuf protocol)

Configuration

The following OTEL environment variables are set in ~/.claude/settings.json (sensitive values redacted):

CLAUDE_CODE_ENABLE_TELEMETRY=1
OTEL_METRICS_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT=https://<apm-server>:<port>
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer <token>
OTEL_SERVICE_NAME=claude-code
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta
OTEL_LOG_TOOL_DETAILS=1
OTEL_METRICS_INCLUDE_VERSION=true
NODE_TLS_REJECT_UNAUTHORIZED=0

What was verified

  • ✅ OTLP endpoint is reachable (HTTP 200)
  • ✅ Bearer token is valid — manual OTLP POST with a real protobuf payload returns 200 with valid ExportLogsServiceResponse
  • ✅ Settings look structurally correct (all required env vars present)
  • ✅ OTLP exporter class names are identical between v2.1.71 and v2.1.72 (OTLPLogExporter, OTLPMetricExporter)
  • ❌ No telemetry data is appearing in the APM backend after upgrade

Suspected cause

The v2.1.72 binary is ~3MB smaller than v2.1.71 (234MB vs 237MB). The changelog mentions "Reduced bundle size by ~510 KB" and "Improved bash command parsing by switching to a native module — faster initialization and no memory leak." It's possible the native module switch changed initialization order, or a dependency change affected OTEL setup.

Reproduction

  1. Have OTEL telemetry working on v2.1.71 with OTEL_METRICS_EXPORTER=otlp and OTEL_LOGS_EXPORTER=otlp
  2. Allow Claude Code to auto-update to v2.1.72
  3. Restart a Claude Code session
  4. No telemetry data appears in the OTLP backend

Workaround

Currently testing whether rolling back to v2.1.71 restores telemetry (the binary is still available at ~/.local/share/claude/versions/2.1.71).

View original on GitHub ↗

12 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/14019
  2. https://github.com/anthropics/claude-code/issues/13803
  3. https://github.com/anthropics/claude-code/issues/1712

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

ffma-glen-sampson · 5 months ago

Root Cause Identified

After extensive debugging, we've identified the root cause of the OTEL telemetry regression.

Summary

Claude Code's bundled OTEL SDK is using @opentelemetry/exporter-logs-otlp-http (which sends application/json) instead of @opentelemetry/exporter-logs-otlp-proto (which sends application/x-protobuf). This happens regardless of the OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf setting. Elastic APM 8.17.4's OTLP endpoint (/v1/logs, /v1/metrics) only accepts protobuf — it returns HTTP 400 for JSON payloads:

failed to unmarshal request body: proto: illegal wireType 6

Evidence

1. The JSON exporter (what Claude Code uses) fails:

$ node -e '... OTLPLogExporter from exporter-logs-otlp-http ...'
Export result: {"code":1,"error":{"code":400,"name":"OTLPExporterError","data":"failed to unmarshal request body: proto: illegal wireType 7"}}

2. The proto exporter (what Claude Code should use) succeeds:

$ node -e '... OTLPLogExporter from exporter-logs-otlp-proto ...'
Export result: {"code":0}
# → Data appears in Elasticsearch ✅

3. Proxy capture confirms the SDK sends JSON despite http/protobuf config:

Content-Type: application/json
Transfer-Encoding: chunked
User-Agent: OTel-OTLP-Exporter-JavaScript/0.200.0
Body (429 bytes): {"resourceLogs":[{"resource":{"attributes":[...

4. APM rejects JSON on OTLP endpoints:

$ curl -X POST https://apm:8200/v1/logs -H "Content-Type: application/json" -d '{"resourceLogs":[...]}'
HTTP 400: failed to unmarshal request body: proto: illegal wireType 6

Environment

  • Claude Code: v2.1.71 (binary MD5: 9c4eedf2411a18eef6a08e94866bdff3 — identical to v2.1.72)
  • Node.js (embedded): v24.3.0
  • Bundled OTEL SDK: @opentelemetry/* v0.208.0 (approximate, from binary strings)
  • Elastic APM Server: 8.17.4
  • OS: Linux 6.17.0-1007-aws (x86_64)

What worked previously

606 events (logs + metrics) were successfully exported between March 7-8, 2026 on the same binary. The proto exporter was correctly selected during those sessions. Something in the exporter selection path changed between sessions — possibly related to initialization timing or env var loading order from settings.json.

Workaround

None currently available via configuration. The OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf setting is ignored by the bundled exporter selection logic.

Possible workarounds:

  • Deploy an OpenTelemetry Collector as a proxy (receives JSON, forwards protobuf)
  • Upgrade Elastic APM to a version supporting JSON OTLP

Suggested Fix

Ensure Claude Code selects @opentelemetry/exporter-logs-otlp-proto (and the equivalent metrics proto exporter) when OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf is configured. The binary already bundles both protobufjs and @bufbuild protobuf libraries.

ffma-glen-sampson · 5 months ago

I take it this is a me problem if no body else is experiencing it? I just don’t get why it was working and then stopped after the updated and yet I can manually get Claude to send test messages with the same credentials

carrysocks · 5 months ago

Same issue here — confirmed on v2.1.74 (macOS arm64).

I was setting up OTel monitoring for my team's Claude Code usage (tracking MCP tool names and skill invocations via OTEL_LOG_TOOL_DETAILS=1).
Everything looked correctly configured, but no data was reaching our ClickHouse backend.

After hours of debugging, I narrowed it down to a version issue. Here's what I found:

### Setup

  • Claude Code v2.1.74 (Homebrew Cask), Amazon Bedrock
  • OTel Collector (contrib image, Helm) → ClickHouse
  • Tested both grpc and http/protobuf protocols

### Results

| Version | Protocol | TCP to collector | Data received |
|---------|----------|-----------------|---------------|
| v2.1.71 | grpc | ESTABLISHED | ✅ 235 events |
| v2.1.74 | grpc | ESTABLISHED | ❌ 0 events (5+ min wait) |
| v2.1.71 | http/protobuf | ESTABLISHED | ✅ (Content-Type: application/x-protobuf) |
| v2.1.74 | http/protobuf | ESTABLISHED | ❌ 0 events |

The interesting part: lsof shows v2.1.74 maintains active TCP connections to the collector, so it's clearly attempting to send — but nothing arrives on the other end. This happens with both grpc and http/protobuf, so the issue seems broader than just the HTTP exporter mentioned in the original report.

### Workaround

Rolled back to v2.1.71 via npm and confirmed all telemetry flows correctly — MCP tool events, Skill events, API requests:

```bash
npm install --prefix ~/.local/share/claude/versions/2.1.71 @anthropic-ai/claude-code@2.1.71

  This is blocking the team from adopting OTel monitoring on the latest version. Any timeline on a fix would be appreciated.
ella-ktech · 5 months ago

Datadog-specific OTLP metrics failures: logs work, metrics silently dropped

My config uses the env vars below including http/protobuf on both logs and metrics. Logs (api_request, user_prompt, etc) arrive in datadog no problem, but no metrics show up, confirmed across multiple sessions including one I left open for 50 minutes.

I believe it may be possible that the metrics exporter isn't initialising at all, rather than initialising but sending the wrong format.

My setup

  • Claude Code: v2.1.74
  • macOS Darwin 25.3.0 arm64
  • OTLP backend: Datadog direct ingest (otlp.datadoghq.com) as per this doc.

Configured env vars

export CLAUDE_CODE_ENABLE_TELEMETRY="1"
export OTEL_METRICS_EXPORTER="otlp"
export OTEL_LOGS_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT="https://otlp.datadoghq.com/v1/metrics"
export OTEL_EXPORTER_OTLP_METRICS_HEADERS="<redacted>" 
export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE="delta"
export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT="https://otlp.datadoghq.com/v1/logs"
export OTEL_EXPORTER_OTLP_LOGS_HEADERS="<redacted>"
export OTEL_LOG_TOOL_DETAILS="1"
export OTEL_METRIC_EXPORT_INTERVAL="10000" # set short for testing 
export OTEL_LOGS_EXPORT_INTERVAL="5000"

Steps to Reproduce

1. Console exporter produces no output

Set OTEL_METRICS_EXPORTER=console with a 1s interval and captured everything to a file:

CLAUDECODE="" OTEL_METRICS_EXPORTER=console OTEL_METRIC_EXPORT_INTERVAL=1000 \
  claude -p "what is 2+2" > /tmp/out.log 2>&1

Output was just 4. No metric JSON at any point during the session.

2. Local capture server receives nothing

Spun up a local HTTP server and pointed the metrics exporter at it:

# /tmp/capture_server.py
import http.server, sys
class H(http.server.BaseHTTPRequestHandler): 
    def do_POST(self):
        length = int(self.headers.get('Content-Length', 0)) 
        body = self.rfile.read(length) if length else b'' 
        print(f"POST {self.path} | Content-Type: {self.headers.get('Content-Type')} | {len(body)} bytes", flush=True)                             
        self.send_response(200); self.end_headers()
    def log_message(self, *a): pass 
http.server.HTTPServer(('127.0.0.1', 14318), H).serve_forever() 

# run 
python3 /tmp/capture_server.py 

# separate terminal run this -> FAILS 
CLAUDECODE="" OTEL_METRICS_EXPORTER=otlp \
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://127.0.0.1:14318/v1/metrics \
OTEL_EXPORTER_OTLP_METRICS_HEADERS="" OTEL_METRIC_EXPORT_INTERVAL=3000 claude -p "what is 2+2" 

The output of the claude session is 4, meanwhile the server is completely silent, it received zero requests. Meanwhile using the same setup to point to the logs endpoint the server successfully receives the post request:

# while same server running as above, execute this 
CLAUDECODE="" OTEL_LOGS_EXPORTER=otlp OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://127.0.0.1:14318/v1/logs \
OTEL_EXPORTER_OTLP_LOGS_HEADERS="" OTEL_LOGS_EXPORT_INTERVAL=3000 \
claude -p "what is 2+2"

# ... SUCCESS: server in other session shows the post request for logs 
% python3 /tmp/capture_server.py  
POST /v1/logs | Content-Type: application/x-protobuf | 1506 bytes

Logs are working fine in the same setup, so OTEL_LOGS_EXPORTER=otlp is being picked up correctly. It seems specific to the metrics exporter.

franckey · 5 months ago

Confirming on Windows 11 Pro (Git Bash, VSCode extension).

Same setup: CLAUDE_CODE_ENABLE_TELEMETRY=1 + OTEL env vars in ~/.claude/settings.json, local Jaeger on http://localhost:4318.

  • Endpoint reachable (HTTP 405 on GET = expected)
  • No traces/metrics received by Jaeger
  • CLAUDE_CODE_ENABLE_TELEMETRY appears empty in the shell despite being set in settings.json env section

Tested with both http/protobuf and http/json protocols — no data exported in either case.

symplr-dlyons · 5 months ago

Deploying AWS usage monitoring from https://github.com/aws-solutions-library-samples/guidance-for-claude-code-with-amazon-bedrock and found a similar OTEL issue, but only with the following combination: Windows 11 + interactive mode + HTTPS.

I replaced the HTTPS OTEL listener with HTTP listener and interactive mode was able to send telemetry. I tested interactive Claude Code versions with WSL Ubuntu 24.04.3 LTS on the same computer and it worked as expected with both protocols.

OS: Windows 11
Shell: Powershell 7.5.4, cmd 10.0.26100.7840
Claude Code: 2.1.73, 2.1.76

Interactive mode = running claude.exe in shell to start session
Headless mode = claude.exe -p '${prompt string here}'

| OS | Monitoring Endpoint Protocol | Claude Code Mode | Telemetry Result |
|----------------|-------------------------------------|-------------------------|--------------------|
| Windows | HTTPS | Interactive | Fail |
| Windows | HTTP | Interactive | Pass |
| Windows | HTTPS | Headless | Pass |

ffma-glen-sampson · 5 months ago

I believe I have found the culprit OTEL_LOG_TOOL_DETAILS: 1

We were building out our skills repo today and were trying to trace skill uses.

The moment this was added today logs dropped

myrison · 4 months ago

Confirming HTTPS-specific silent failure on macOS — v2.1.91, http/json protocol.

Environment

  • Claude Code: v2.1.91 (built 2026-04-02)
  • OS: macOS (Darwin 25.3.0, Apple Silicon)
  • Shell: zsh (CLI, not VS Code/IDE)
  • Protocol: http/json
  • Endpoint: Custom HTTPS OTLP receiver (not Elastic/Jaeger/ADOT)
  • No proxy, no mTLS, no NODE_TLS_REJECT_UNAUTHORIZED, no OTEL_LOG_TOOL_DETAILS

Configuration (env vars sourced in shell)

CLAUDE_CODE_ENABLE_TELEMETRY=1
OTEL_EXPORTER_OTLP_ENDPOINT=https://<redacted>/meter/v2/otlp
OTEL_EXPORTER_OTLP_HEADERS=x-api-key=<redacted>
OTEL_EXPORTER_OTLP_PROTOCOL=http/json
OTEL_LOGS_EXPORTER=otlp

What I tested

| Test | Protocol | Result |
|------|----------|--------|
| Claude interactive session → http://localhost:19878 | HTTP | 2 events received (user_prompt, api_request) |
| Claude interactive session → https://<endpoint> | HTTPS | 0 events received |
| Claude --print mode → http://localhost | HTTP | Events received |
| Claude --print mode → https://<endpoint> | HTTPS | 0 events |
| Direct curl POST → same HTTPS endpoint | HTTPS | 1 event processed |
| Node.js fetch() → same HTTPS endpoint | HTTPS | 1 event processed |

The endpoint is fully reachable and processes events correctly when called directly. Only the OTel SDK's OTLPLogExporter inside Claude Code fails to deliver to HTTPS.

Debug log confirms init succeeds

[3P telemetry] isTelemetryEnabled=true (CLAUDE_CODE_ENABLE_TELEMETRY=1)
[3P telemetry] getOtlpLogExporters: types=["otlp"], protocol=http/json, endpoint=https://<redacted>
[3P telemetry] Created 1 log exporter(s)
[3P telemetry] Event logger set successfully

Additional data points

  • Long-running sessions started on v2.1.89 (before v2.1.91 auto-update) continue to send OTLP data to the same HTTPS endpoint successfully. New sessions started after the v2.1.91 update do not.
  • Increasing CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS=15000 and CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MS=15000 did not help.
  • NODE_OPTIONS="--dns-result-order=ipv4first" did not help.
  • An HTTP→HTTPS proxy workaround (Claude sends HTTP to localhost, proxy forwards HTTPS to real endpoint) does work.

This aligns with @symplr-dlyons's finding that HTTPS fails in interactive mode. It appears to also affect macOS (not just Windows), and specifically http/json protocol (not just http/protobuf).

JuanNephrota · 4 months ago

This is what I found on the Mac client. NOt sure if it's the same issue for LInux.

Root cause (hypothesis, with evidence)
The Bun-compiled binary does not include the OTLP exporter packages. The SDK's factory code dynamically require()s them at runtime, resolves to null/undefined, and a destructuring assignment throws — which is caught and swallowed.

Evidence — strings in the binary:

$ strings /Users//.local/share/claude/versions/2.1.113
| grep -oE '@opentelemetry/[a-z0-9/._-]+' | sort -u
@opentelemetry/api
Only the API package. No exporter packages.

Error strings baked into the binary (clearly caught, never surfaced):

Cannot destructure property 'OTLPMetricExporter' from null or undefined value
Cannot destructure property 'OTLPLogExporter' from null or undefined value
Cannot destructure property 'OTLPTraceExporter' from null or undefined value
Console exporter IS bundled (which is why it works):

$ strings /Users//.local/share/claude/versions/2.1.113
| grep -iE 'consolemetricexporter'
ConsoleMetricExporter
Installing the missing packages globally (npm i -g @opentelemetry/exporter-metrics-otlp-proto) and setting NODE_PATH=$(npm root -g) does not help — Bun-compiled binaries don't resolve externals at runtime the way a Node script would.

github-actions[bot] · 3 months ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

github-actions[bot] · 1 month ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.