テレメトリの宛先を managed settings で固定したはずなのに、コレクターに何も届かない。あるいは届いてはいるが、ログだけが別の宛先に吸い込まれている。この種の事故は「設定ミス」ではなく、Claude Code が起動時に変数をどう解決するか(settings precedence)を知らないことから起きます。本稿は 2026-10-27 時点の公式ドキュメントで確認できる解決ルールをもとに、原因を切り分けて直すまでの手順を 1 本通します。
症状:設定したのに届かない、あるいは一部だけ逸れる
典型は 2 つです。ひとつは「管理者が managed settings に OTEL エンドポイントを入れたのにコレクターが空」。もうひとつは「メトリクスは来るのにログだけ開発者のローカル宛先に流れている」。後者はコンプライアンス上やっかいで、監査対象のイベントが管理外のコレクターに届いてしまいます。
起動時に何が削除されるのか
Claude Code は起動時に、managed settings のテレメトリ変数と競合する開発者設定の変数を取り除きます。
Claude Code removes conflicting developer-set variables at startup and logs a warning in the debug log.
起動時に競合する開発者設定変数を削除し、その旨を debug log に警告として残す、という挙動です。ここが診断の起点になります。削除は変数の種類ごとに連鎖します。OTEL_EXPORTER_OTLP_ENDPOINT を managed settings に置くと開発者設定のシグナル別エンドポイントがすべて消え、OTEL_EXPORTER_OTLP_PROTOCOL を置くとシグナル別プロトコルが消え、HEADERS・CLIENT_KEY・CLIENT_CERTIFICATE を置くと該当するシグナル別バリアントに加え開発者設定のエンドポイント変数が消えます。
バージョンで挙動が変わる:v2.1.217 と v2.1.223
この「宛先ピン留め」は比較的新しい機能で、エクスポーター宛先ロックには v2.1.223 以降が必要です。それ以前は違いました。
Before v2.1.217, every variable followed per-key settings precedence independently, so a signal-specific endpoint set in user settings or the shell redirected that signal away from the managed collector.
v2.1.217 より前は各変数が独立して per-key precedence に従ったため、ユーザー設定やシェルのシグナル別エンドポイントが managed collector を迂回できた、という記述です。つまり「昔は通っていた設定が今は消える」ことも、逆に「古い環境では宛先が守られない」こともあり得ます。診断の前に claude --version を確認してください。
宛先をピン留めする managed settings の完成形
まず受け側のローカルコレクターを用意します。空のディレクトリを作り、設定ファイルを置きます。
# otel-collector-config.yaml
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
grpc:
endpoint: 0.0.0.0:4317
exporters:
debug:
verbosity: detailed
service:
pipelines:
metrics:
receivers: [otlp]
exporters: [debug]
logs:
receivers: [otlp]
exporters: [debug]
traces:
receivers: [otlp]
exporters: [debug]
起動します(古いコレクターでは debug の代わりに logging エクスポーターを使います)。
docker run --rm -p 4317:4317 -p 4318:4318 \
-v "$(pwd)/otel-collector-config.yaml:/etc/otelcol/config.yaml" \
otel/opentelemetry-collector:latest
次に managed settings の env ブロックに以下を入れます。配置するファイルの場所は OS ごとに異なるため、設定リファレンス(settings precedence)に従ってください。テレメトリ収集には CLAUDE_CODE_ENABLE_TELEMETRY=1 が必須で、Claude Code には組み込みデフォルトのプロトコルが無いため OTEL_EXPORTER_OTLP_PROTOCOL も必須です。
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4318",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_TRACES_EXPORTER": "otlp"
}
}
エクスポーターセレクタ(OTEL_METRICS_EXPORTER など)を managed settings に明示的に入れているのは意図的です。これらは開発者設定対 managed settings 間では通常の per-key precedence に従うため、ロックしないと開発者が none に切り替えてシグナルを無効化できます。
届かないときの切り分け手順
デバッグログを書き出して起動します。
claude --debug-file ./debug.log
エラーの読み分けが肝心です。
Claude Code reports failures from the exporters you configure as [3P telemetry] errors, where 3P means third-party.
自分が設定したエクスポーターの失敗は [3P telemetry] エラーとして出ます。一方 [Anthropic telemetry] プレフィックスの行は Anthropic 側の運用テレメトリで、あなたのセットアップの問題ではありません。成功の判定は次の基準で行います(実際の表示文字列はバージョンで異なるため逐語は避けます)。
# 成功とみなす条件
# 1. collector の標準出力に claude_code.session.count のデータポイントが現れる
# 2. ./debug.log に [3P telemetry] で始まるエラー行が無い
# 3. プロンプトを1回送信すると logs パイプラインに claude_code.user_prompt が届く
メトリクスのセットアップ確認には claude_code.session.count(セッション開始時に出る)を、ログのみのセットアップにはプロンプト送信後の claude_code.user_prompt イベントを使います。
どのソースが効いたかを確定する
複数の管理ソース(managed settings、ポリシーヘルパー、ランチャー)が絡むと「どれが勝ったか」が見えにくくなります。ここで OTEL_LOG_MANAGED_SETTINGS=1(v2.1.274 以降、project/local 設定では有効化不可)を使うと、managed_settings_resolved イベントにリダクション済みの managed settings と、リダクション前の SHA-256 ダイジェストが付きます。このイベントは sources 属性を持ちます。
every managed source that delivers at least one policy key , highest priority first
ポリシーキーを 1 つ以上提供するすべての管理ソースが優先順位の高い順に並ぶ、という属性です。期待した宛先と違うソースが最上位にいれば、それが犯人です。
自分ならこう設計する
ここは docs の引き写しではなく運用上の判断です(事実主張ではなく設計意見として読んでください)。第一に、必要の有無にかかわらず 3 つのエクスポーターセレクタを managed settings で必ずロックします。ロックしないと OTEL_LOGS_EXPORTER=none で監査シグナルを静かに落とせるためで、これは利便性ではなくセキュリティ境界として扱うべきです。第二に、SHA-256 ダイジェストを設定のアテステーションとして使い、全端末で値を突き合わせてドリフトや改ざんを検出します。第三に、管理コンソールの Cowork 向け OpenTelemetry フォームを CLI もカバーすると誤解しないことです。これは Cowork セッション専用で、ターミナル CLI も Code タブもそこで指定したコレクターには送りません。
既知の限界
OTEL_LOG_MANAGED_SETTINGS は v2.1.274 以降が必要で project/local からは有効化できません。Claude Code は生成するサブプロセス(Bash ツール、hooks、MCP サーバー、言語サーバー)に OTEL_* を渡さないため、hooks から同じ変数でテレメトリを出させる設計は成立しません。リポジトリの .claude/settings.json 内の OTEL エクスポーター変数は無視されるため、リポジトリでテレメトリを有効化したり宛先を変えたりはできません(ただしエクスポーターセレクタでシグナルを off にすることは、managed settings 等がその変数を設定していない限り可能です)。なおデスクトップアプリやセルフホストランナーが OTLP エンドポイントを渡した場合も managed settings と同じく開発者設定変数を削除しますが、適用開始バージョンは出典に記載がなく未確認です。