ccr.session.idでクラウドセッションのテレメトリを特定する方法
クラウドセッションにはccr.session.idが自動で付き、Claude Tagはapp.entrypointで分けられます。Desktop SSHのhost.nameは管理設定に直書きします。
Claude CodeのOpenTelemetryデータで、クラウドセッションとDesktop SSHセッションを見分けるには、それぞれ別の属性を使います。クラウドセッションにはccr.session.idが既定で付きます。Claude TagのセッションはOTEL_METRICS_INCLUDE_ENTRYPOINT=trueでapp.entrypointがclaude-in-slackになります。Desktop SSHのセッションにはマシン名が付かないので、OTEL_RESOURCE_ATTRIBUTESでhost.nameを自分で書きます。
この3つは設定する場所も、届かなくなる理由もそれぞれ違います。ユーザー単位の特定はClaude Code OTELユーザー特定で扱っているので、ここでは「どの実行環境で動いたか」の特定に絞ります。
クラウドセッションの識別は既定で付く
クラウドセッションのメトリクスとイベントには、標準属性としてsession.id、ccr.session.id、organization.idが付きます。追加の設定なしで、セッション単位や組織単位の絞り込みができます。
ccr.session.idの値は、そのセッションの環境変数CLAUDE_CODE_REMOTE_SESSION_IDと同じです。クラウド環境で動くセッションにだけ付く属性なので、ローカルのCLIセッションのデータには出てきません。
制御する変数はOTEL_METRICS_INCLUDE_SESSION_IDです。既定はtrueで、session.idとccr.session.idの両方をまとめて切り替えます。ccr.session.idだけを外す変数はありません。
| 属性 | 意味 | 付く条件 |
|---|---|---|
session.id | 意味セッションの一意な識別子 | 付く条件OTEL_METRICS_INCLUDE_SESSION_IDがtrue(既定) |
ccr.session.id | 意味クラウドセッションの識別子 | 付く条件同上。クラウド環境で動くセッションのみ |
organization.id | 意味組織のUUID | 付く条件認証済みで取得できるとき常に |
ccr.session.idからセッションのURLを組み立てる
集計や障害調査で「このデータポイントはどのセッションか」を開いて確かめたいときは、ccr.session.idをトランスクリプトのURLに変換します。変換のルールは、値の先頭にあるcse_をsession_に置き換えることです。
セッション内で試すなら、次のコマンドが使えます。環境変数の値から、claude.ai上のトランスクリプトURLを作ります。
echo "https://claude.ai/code/${CLAUDE_CODE_REMOTE_SESSION_ID/#cse_/session_}"テレメトリ側でこの変換をしたいときも考え方は同じです。ダッシュボードのデータリンクやアラートの通知文に、ccr.session.idのcse_をsession_へ置換したURLを仕込んでおくと、異常なセッションの会話をそのまま開けます。
なお、クラウドセッションでClaudeが作るコミットにはClaude-Session: <url>というgit trailerが入り、PR本文にもセッションURLが載ります。テレメトリのIDとgit履歴上のURLは同じセッションを指すので、PRからテレメトリを、テレメトリからPRをたどれます。trailerとPR本文のリンクを消したいときは、設定attribution.sessionUrlをfalseにします。この設定はテレメトリの属性には影響しません。
Claude Tagのセッションはapp.entrypointで分ける
Claude Tagのチャンネルで動くセッションも、クラウド環境で動くのでccr.session.idは付きます。ただ、通常のクラウドセッションとの区別にはなりません。区別したいときはOTEL_METRICS_INCLUDE_ENTRYPOINT=trueを設定します。
すると、メトリクスにapp.entrypointが付き、Claude Tagのセッションでは値がclaude-in-slackになります。この変数は既定でfalseです。起動経路の値の一覧はOTEL_METRICS_INCLUDE_ENTRYPOINTとはにまとめています。
もう1点、見落としやすい制約があります。Claude Tagのチャンネルセッションでは、Claudeは特定のメンバーではなく組織の共有ID(shared identity)として動きます。そのため、user.*属性は「誰がClaudeをタグ付けしたか」の根拠になりません。
テレメトリ設定を届ける場所は2つ
クラウドセッションは、利用者の端末ではなくクラウド環境で動きます。端末にある管理設定ファイルやシェルプロファイルは、クラウドセッションのテレメトリを設定しません。CLAUDE_CODE_ENABLE_TELEMETRYとOTEL_*変数は、次のどちらかに置きます。
| 置き場所 | 届く範囲 | Claude Tag |
|---|---|---|
サーバー管理設定のenvブロック | 届く範囲利用者の端末と、Claude Tag以外のクラウドセッション | Claude Tag届かない |
| クラウド環境の環境変数 | 届く範囲その環境で動くセッションだけ | Claude Tag届く |
Claude Tagのセッションにも同じ設定を流したいときは、環境変数の側を使います。チャンネルのセッションは組織レベルの環境で動くため、共有環境(組織の既定、またはチャンネルに固定したもの)に設定を入れます。
環境変数に資格情報を置かない
環境変数は、その環境を使う人なら誰でも読めます。OTEL_EXPORTER_OTLP_HEADERSに入れるコレクターのトークンのような資格情報は、置かない構成にします。環境に登録するネットワークシークレットも代わりになりません。Claude Code自身のテレメトリ送信は、シークレットが付かないリクエストの1つだからです。
コレクターが認証を求めるなら、エクスポート設定の全体をサーバー管理設定で配ります。管理設定で資格情報を設定すると、Claude Codeは管理設定の外で設定されたエンドポイント変数を取り除き、送信先が差し替えられないようにします。OTEL_EXPORTER_OTLP_HEADERSを管理設定で配ると、開発者側で設定したエンドポイント変数はすべて取り除かれます。
コレクターに到達できるようにする
テレメトリの送信はセッションのネットワーク経由で行われます。OTEL_EXPORTER_OTLP_ENDPOINTのホストに届くかどうかは、環境のネットワークアクセスレベルで決まります。到達できないレベルを選んでいるなら、コレクターのドメインを環境の許可リストに足します。サーバー管理設定には、環境の許可リストにドメインを足す手段がありません。
Coworkは別枠です。Coworkのセッションはサーバー管理設定を受け取らないため、envブロックに書いてもテレメトリは設定されません。
セットアップスクリプトでexportしたOTEL_RESOURCE_ATTRIBUTESは届かない
クラウドセッションに独自の属性を足したいときは、OTEL_RESOURCE_ATTRIBUTESを他のOTEL_*変数と同じ場所に置きます。ここで落とし穴になるのが、環境のセットアップスクリプトです。
セットアップスクリプトでexportしても、値はClaude Codeに届きません。スクリプトはClaude Codeの起動前に走る別のBashスクリプトで、exportした変数はスクリプトの終了とともに消えるからです。
OTEL_RESOURCE_ATTRIBUTESの置き場所
届かない置き方
環境のセットアップスクリプトにexport OTEL_RESOURCE_ATTRIBUTES="team.id=platform"と書く。エラーは出ませんが、属性はデータに現れません。
届く置き方
環境の環境変数にOTEL_RESOURCE_ATTRIBUTES=team.id=platformを書く。サーバー管理設定を使うなら、envブロックに入れます。
環境変数は.env形式で、1行に1組のKEY=valueです。値に#を含むなら引用符で囲みます。囲まないと、#から後ろがコメントとして落ちます。
Desktop SSHではhost.nameを自分で付ける
Desktop SSHセッションのメトリクスとイベントには、セッションがどのリモートマシンで動いたかを示す情報がありません。複数のビルドホストを登録している組織では、マシンごとに名前を付ける必要があります。
手順は、各リモートマシンの管理設定ファイルで、テレメトリを有効にするenvブロックにOTEL_RESOURCE_ATTRIBUTESを足すことです。SSHセッションは、リモートホストの管理設定ファイルを読みます。ローカルのPCに置いたファイルではありません。
次はマシン名をbuild-7にする例です。
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.example.com:4317",
"OTEL_RESOURCE_ATTRIBUTES": "host.name=build-7"
}
}名前はマシンごとのファイルに、文字列として書き出します。Claude Codeは値を展開しません。host.name=$(hostname)と書けば、その文字がそのまま届きます。台数が多い場合は、ファイルを各マシンに配る処理の側でホスト名を埋め込む形になります。
他に値を設定する経路がなければ、host.nameはリソースブロックに載ります。Desktop SSHセッションだけでなく、そのマシン上のCLIでも同じです。データポイントやイベントのラベルとしてどこに現れるかは、OTEL_RESOURCE_ATTRIBUTESの共通の挙動に従います。カスタム属性は各メトリクスとイベントに付き、OTLPのリソースブロックにも入ります。標準属性と同じキーを書いても、vcs.*以外は組み込みの値が優先されます。
host.nameが届かないときの切り分け
名前が届かないときは、次の4つを順に見ます。
| 原因 | 症状の背景 | 直し方 |
|---|---|---|
| Desktopを動かすPCで設定した | 症状の背景Desktopは、そこで設定した値をSSHセッションへ渡さない | 直し方リモートホストの管理設定ファイルに書く |
| ログインファイルでexportした | 症状の背景/etc/profileなどを読むのはログインシェルだけ。DesktopはClaude Codeをログインシェル経由で起動しない | 直し方管理設定のenvに書く |
| 値にスペースがある | 症状の背景キーが1つもイベントやデータポイントに付かず、エラーも出ない | 直し方スペースを除き、アンダースコアかキャメルケースにする |
| 起動環境が先に変数を設定している | 症状の背景Desktopが起動したセッションでは、起動環境の変数が設定ファイルより優先される | 直し方デバッグログで無視された変数を確かめる |
最後の行は、サードパーティ版のDesktop配布にも関わります。配布側がOTLPエンドポイントを環境に指定していると、その環境にはDesktop自身のOTEL_RESOURCE_ATTRIBUTESが入ります。管理設定の値は無視されます。無視された変数の名前はデバッグログに出るので、まずそこを見ます。
スペース入りの値は黙って全部落ちる
3行目は特に厄介です。OTEL_RESOURCE_ATTRIBUTESはカンマ区切りのkey=value形式で、値にスペースを含められません。user.organizationName=My Companyのような値が1つ混ざると、他のキーも含めて何も付かず、エラーも出ません。
使える文字は、制御文字、空白、二重引用符、カンマ、セミコロン、バックスラッシュを除くUS-ASCIIです。範囲外の文字はパーセントエンコードします。
# 動かない例(スペース入り、引用符で囲んでも同じ)
export OTEL_RESOURCE_ATTRIBUTES="org.name=My Company"
# 動く例
export OTEL_RESOURCE_ATTRIBUTES="org.name=My_Company"
export OTEL_RESOURCE_ATTRIBUTES="org.name=My%20Company"引用符で囲んでもスペースの問題は解決しません。org.name="My Company"は、引用符を含んだ文字列がそのまま値になります。
どの識別子をどこで設定するか
| 実行環境 | 識別に使う属性 | 設定する場所 |
|---|---|---|
| クラウドセッション | 識別に使う属性ccr.session.id(既定で付く) | 設定する場所設定不要。OTEL_*はサーバー管理設定かクラウド環境の環境変数 |
| Claude Tagのセッション | 識別に使う属性app.entrypoint=claude-in-slack | 設定する場所クラウド環境の環境変数にOTEL_METRICS_INCLUDE_ENTRYPOINT=true |
| Desktop SSHセッション | 識別に使う属性host.name(自分で命名) | 設定する場所リモートホストの管理設定のenv |
Desktop SSH側の接続先制限はsshHostAllowlist、セッションを開く導線はClaude DesktopのSSHリンクで扱っています。テレメトリの全体設定はClaude CodeのOpenTelemetryで利用量とコストを可視化が入口になります。
まとめ
迷ったときの順番は、まずccr.session.idで足りるかを見ることです。Claude Tagの区別が要るならapp.entrypoint、SSHでマシンを分けたいならhost.nameを足します。
属性が届かないときは、値の書式より先に、設定を置いた場所がClaude Codeの起動側から見えているかを疑うのが近道です。コレクターの認証が絡む場合は、環境変数ではなく管理設定に寄せます。