OTEL_RESOURCE_ATTRIBUTES set via settings.json env or OS-level env var never applied to Claude Code's own OTLP export
OTEL_RESOURCE_ATTRIBUTES set via settings.json env or OS-level env var is never applied to Claude Code's own OTLP telemetry export
Summary
Custom OTEL_RESOURCE_ATTRIBUTES never appear on Claude Code's own outgoing claude_code.* OTLP metrics/logs, regardless of whether they are set via ~/.claude/settings.json's env key or as a real OS-level environment variable before launching claude. Only the built-in resource attributes (host.arch, os.type, os.version, service.name, service.version) are ever present. This happens while CLAUDE_CODE_ENABLE_TELEMETRY / OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_HEADERS are supplied via an org-level managed policy (admin console).
According to the documentation (monitoring-usage.md, server-managed-settings.md), OTEL_RESOURCE_ATTRIBUTES is explicitly not part of the signal-transport variable group (OTEL_EXPORTER_OTLP_*) that managed settings withhold/own — it should follow normal per-key precedence and merge in regardless of managed telemetry routing. That does not match what we observe.
Environment
- Reproduced on: Claude Code 2.1.235, Windows 10.0.19044 (also present, unconfirmed whether attempted, on 2.1.234 / Win 10.0.19042 and 2.1.138 / Win 10.0.26200 in the same fleet)
- Telemetry pipeline: self-hosted OTel Collector (
otel/opentelemetry-collector-contrib) receiving OTLP/HTTP, behind a Cloudflare Tunnel, withCLAUDE_CODE_ENABLE_TELEMETRY=1,OTEL_METRICS_EXPORTER=otlp,OTEL_LOGS_EXPORTER=otlp,OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf,OTEL_EXPORTER_OTLP_ENDPOINT,OTEL_EXPORTER_OTLP_HEADERSall supplied via managed/admin-console policy (highest-precedence settings tier). - Collector processors verified to NOT touch resource attributes (only a metric-name filter and one attribute upsert on a different key) — ruled out as the cause; confirmed by other built-in resource attributes (host.arch, os.type, etc.) passing through untouched.
Expected behavior
Setting OTEL_RESOURCE_ATTRIBUTES=device.id=...,git.email=...,git.name=...,department=... — via either env in ~/.claude/settings.json (user scope) or a real OS environment variable — should cause those key=value pairs to appear as resource attributes on every claude_code.* metric/log Claude Code exports, merged alongside the built-in ones.
Actual behavior
Across two independent, controlled tests, custom resource attributes never appear:
Test 1 — via ~/.claude/settings.json's env key:
- Wrote
OTEL_RESOURCE_ATTRIBUTESinto~/.claude/settings.json→env.OTEL_RESOURCE_ATTRIBUTES(confirmed written correctly, value persisted, read back correctly by a manual--check). - Fully quit Claude Code, relaunched (confirmed via a
SessionStarthook's own log that at least 2 fresh session starts occurred after the write, ~13:21 and ~13:24 UTC). - Result: 520 subsequent
claude_code.*events for that account over the following ~70 minutes — 0 of 520 carried the custom resource attributes. Resource attribute set on every single event was onlyhost.arch, os.type, os.version, service.name, service.version.
Test 2 — via genuine OS-level environment variable (bypassing settings.json entirely):
- In the same PowerShell session:
$env:OTEL_RESOURCE_ATTRIBUTES = "device.id=...,device.hostname=...,git.email=...,git.name=...,department=..." - Launched
claudefrom that same shell. - Result: new telemetry batches confirmed arriving (session was live and exporting), but again 0 events carried the custom resource attributes.
Both tests used the same attribute string and the same account. Result was identical and deterministic in both cases — 0% pass-through.
Data point of note
The value being tested (device.id=837bea303ea10bb298fadfdf7345714d1899085bb3188eefd460a7a7c6fc04be,device.hostname=w010955143,git.email=sangtt@fpt.com,git.name=W010955143\ISC-SangTT,department=QA) was verified byte-for-byte correct in ~/.claude/settings.json at the time of both tests — this is not a "value never got written" issue, it's a "written/set value never reaches the exporter" issue.
Hypothesis (unconfirmed)
Given both the settings.json-scoped and OS-level-scoped tests failed identically, the likely cause is not a settings-precedence issue but something in the OTLP resource-attribute assembly path itself — e.g. the resource attributes may be captured once at process/SDK initialization from a snapshot that predates env application, or OTEL_RESOURCE_ATTRIBUTES may be silently dropped somewhere in resource construction specifically when telemetry routing (OTEL_EXPORTER_OTLP_*) originates from managed settings. We could not confirm either root cause from the client side alone.
Impact
This blocks any workflow that relies on OTEL_RESOURCE_ATTRIBUTES to attach per-device/per-user identity metadata (device fingerprint, local git identity, team/department tags) to telemetry in an organization running Claude Code under a centrally managed OTLP endpoint — a documented, intended use case per monitoring-usage.md.
Request
Please confirm whether this is a known regression, and if so which version introduced it. Note: our controlled tests (both attempts to actually set OTEL_RESOURCE_ATTRIBUTES) were only run against 2.1.235; two other accounts on 2.1.234 and 2.1.138 in the same fleet also show only the built-in resource attributes, but we have not confirmed those accounts ever attempted to set OTEL_RESOURCE_ATTRIBUTES — that observation is not part of the reproduction, just a note in case it's useful. Happy to provide the raw OTLP JSON export files (out/telemetry.json) if useful for repro.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗