Claude CodeのOTEL_LOG_TOOL_DETAILSとTOOL_CONTENTで見える範囲
OTEL_LOG_TOOL_DETAILSはツール引数と実名を、OTEL_LOG_TOOL_CONTENTはツールの出力をOpenTelemetryに載せます。違い、前提条件、設定できる場所をまとめます。
OTEL_LOG_TOOL_DETAILSとOTEL_LOG_TOOL_CONTENTは何を載せる変数か
OTEL_LOG_TOOL_DETAILSとOTEL_LOG_TOOL_CONTENTは、Claude CodeのOpenTelemetry出力に「ツールが何をしたか」の中身を足す環境変数です。どちらも既定は無効で、1を設定したときだけ有効になります。
役割は分かれています。
| 変数 | 足されるもの | 前提 |
|---|---|---|
OTEL_LOG_TOOL_DETAILS | 足されるものツールの入力引数、MCPサーバー名、エラー文字列、エージェントやスキルの実名など | 前提特になし(メトリクス・ログ・トレースに効く) |
OTEL_LOG_TOOL_CONTENT | 足されるものツールが返した内容(tool.outputスパンイベント) | 前提トレーシングの有効化が必要 |
前者は「何を渡したか、誰が呼んだか」、後者は「何が返ってきたか」を担います。同じ「ツールの詳細」でも出所が違うので、片方だけ入れて期待した項目が出ない、という行き違いが起きやすい組み合わせです。
エクスポーター自体の立ち上げ方はClaude CodeのOpenTelemetryで利用量とコストを可視化にまとめています。ここでは、その上に重ねる2つの内容系スイッチだけを扱います。
OTEL_LOG_TOOL_DETAILS=1で増える情報
OTEL_LOG_TOOL_DETAILS=1は、1つの変数で複数の出力先に効きます。増える主な情報は次のとおりです。
TOOL_DETAILSで実値になる情報
ツールの入力
tool_resultイベントのtool_input(JSON化した引数)とtool_parameters。Bashのコマンド文字列やファイルパスもここに入ります。名前の実値
MCPサーバー名とツール名、ユーザーが作ったワークフロー名、スキル名、プラグイン名、エージェント名。
失敗時の詳細
ツール失敗時の
errorが、カテゴリ文字列から完全なエラーメッセージに変わります。MCP接続失敗のerrorも同様です。コストとトークン
コストとトークンのカウンターで、
agent.nameやskill.nameなどが伏せ字でなく実名になります。
既定では何に丸められるか
無効のままでも、イベントは出ます。丸められるのは中身です。
- ユーザー設定のMCPサーバーを呼んだ
tool_resultとtool_decisionでは、tool_nameが文字列mcp_toolに固定され、引数は省かれる mcp_server_connectionではserver_nameとエラーメッセージが省かれるskill.nameはユーザー定義スキルでcustom_skill、agent.nameはユーザー定義エージェントでcustom、サードパーティのプラグイン名はthird-partyになるuser_promptのcommand_nameは、カスタム・プラグイン・MCPのコマンドがcustomかmcpにまとまる
例外が1つあります。Claude Desktopの内蔵サーバーを、Claude Desktopが管理するセッションで呼んだ場合は、フラグが無効でもtool_decisionとtool_resultにmcp_server_nameとmcp_tool_nameが出ます。この例外はv2.1.214以降で、ユーザー設定のMCPサーバーには当てはまりません。
SIEMやダッシュボードで「どのMCPサーバーが使われたか」を引きたいのにmcp_toolしか並ばないときは、まずこの変数が未設定でないかを確かめます。
有効にしても、引数が丸ごと残るわけではありません。tool_inputは、512文字を超える値が個別に切り詰められ、全体も約4K文字に収まるよう制限されます。長いコマンドやファイルの中身まで復元したいときは、この変数ではなく次節のツール出力側を使います。
v2.1.273より前との違い
名前の実値化は、コストとトークンのカウンターについてv2.1.273から入っています。それ以前はOTEL_LOG_TOOL_DETAILS=1でも伏せ字の値が出ていました。古いバージョンと混ぜて集計するとagent.nameの値が食い違うので、バージョンをそろえてから比べます。
api_refusalイベントのcategoryも、この変数が有効で、かつhas_categoryがtrueのときだけ載ります。拒否を数える手順はClaude CodeのOTelでapi_refusalイベントから拒否を数えるで扱っています。
OTEL_LOG_TOOL_CONTENT=1はトレーシングが前提
OTEL_LOG_TOOL_CONTENTが効くのは、トレース(ベータ機能)の側です。メトリクスやログだけを有効にしていても、この変数は何も足しません。
トレーシングを有効にするには、CLAUDE_CODE_ENABLE_TELEMETRY=1に加えてCLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1を設定し、OTEL_TRACES_EXPORTERで送信先を選びます。この状態でOTEL_LOG_TOOL_CONTENT=1を足すと、claude_code.toolスパンにtool.outputというスパンイベントが付きます。
tool.outputが記録される呼び出し
Read、Bash、WebFetch、WebSearch、MCPツールの呼び出しが対象です。MCPツール・WebFetch・WebSearchの記録にはv2.1.283以降が必要です。Edit、Write、およびその他のツールは次のとおりで、条件が分かれます。
| ツール | 記録の条件 |
|---|---|
| Read、Bash | 記録の条件OTEL_LOG_TOOL_CONTENT=1で記録 |
| Edit、Write | 記録の条件OTEL_LOG_TOOL_DETAILS=1も同時に必要 |
| その他のツール | 記録の条件記録されない |
Edit・Writeだけは、OTEL_LOG_TOOL_DETAILSが属性ではなくイベントそのものの条件になります。変更差分を残したいときは、両方を立てます。
記録されない場合
次のケースでは、変数を立てていてもtool.outputは出ません。
- 呼び出しがエラーになった場合(成功して返ったときにだけ書かれる)
- Readが画像やPDFを返した場合、または内容が変わっていないファイルの再読み込みだった場合
- WebFetchやWebSearchが待機メッセージのためにバックグラウンドへ回された場合(後から届く結果も記録されない)
属性とサイズの上限
イベントの属性は、content(Readの返したテキスト)、output(Bashの結合出力やMCPなどの返却結果)、diff(Editの差分)、file_path、bash_commandです。このうちdiff、file_path、bash_commandはOTEL_LOG_TOOL_DETAILSも必要で、contentもWriteの場合は同じです。各属性は既定60KBで切り詰められ、<属性名>_truncatedと<属性名>_original_lengthが付きます。切り詰めの上限を調整する変数はOTEL_ATTRIBUTE_VALUE_LENGTH_LIMITとはで説明しています。
2つの変数は「どこで設定したか」で効きが変わる
どちらの変数も、シェル、ユーザー設定、管理設定のいずれかで設定したときだけ有効になります。リポジトリの.claude/settings.jsonや.claude/settings.local.jsonのenvに書いた値は無視されます。
これは、チェックアウトしたリポジトリがセッションの内容を外部へ流す設定を勝手に持ち込めないようにするための扱いです。コンテンツ系の変数だけでなく、CLAUDE_CODE_ENABLE_TELEMETRY、エクスポーター選択、OTEL_EXPORTER_OTLP_*の接続先もまとめて同じ扱いです。この無視はv2.1.282以降です。
例外は、オフにする方向の値です。
none: 3つのエクスポーター選択変数(OTEL_LOGS_EXPORTER、OTEL_METRICS_EXPORTER、OTEL_TRACES_EXPORTER)に対して0などのオフ値:OTEL_LOG_USER_PROMPTS、OTEL_LOG_TOOL_CONTENT、OTEL_LOG_TOOL_DETAILSに対して
オフ値は、ユーザー設定の同じ変数を上書きできます。ただし、起動元の環境、--settingsファイル、管理設定で設定された値は上書きできません。リポジトリ側から「このプロジェクトでは中身を出さない」と絞ることはできても、広げることはできない設計です。
設定が効いていないとき
プロジェクト設定に書いたまま「出ない」と悩むケースが典型です。ローカルの対話セッションでは、起動時にこの種の変数が無視されたという通知が出ます。/statusかclaude doctorで、無視された変数名とオフにした変数名を確かめられます(値は表示されません)。
claude doctor対話セッションの中なら/statusでも同じ内容を見られます。表示された変数名が、自分がプロジェクト設定のenvに書いたものと一致していれば、原因は設定場所です。値をユーザー設定か管理設定へ移して、セッションを開き直します。
-pによる非対話実行やAgent SDKのセッションでは通知が出ません。アップグレード後にコレクターへデータが届かなくなったら、変数をユーザー設定、管理設定、ジョブの環境変数のいずれかへ移します。
設定例
次の例は、シェルでMCPとBashの呼び出し詳細をログに載せる最小構成です。
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://localhost:4318/v1/logs
export OTEL_LOG_TOOL_DETAILS=1
claude組織で配る場合は、管理設定のenvに置きます。次はログの送信先を自社のSIEM向けに固定し、ツール詳細を有効にした形の例です(エンドポイントとトークンは差し替えます)。
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_LOG_TOOL_DETAILS": "1",
"OTEL_EXPORTER_OTLP_LOGS_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": "https://siem.example.com:4318/v1/logs",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer your-siem-token"
}
}ツール出力まで残すなら、トレースの設定を足します。
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",
"OTEL_TRACES_EXPORTER": "otlp",
"OTEL_LOG_TOOL_DETAILS": "1",
"OTEL_LOG_TOOL_CONTENT": "1"
}
}トレースだけ見たい場合も、OTEL_LOG_TOOL_CONTENTだけではEdit・Writeの出力が出ないことに注意します。
有効化の前に決めること
どちらの変数も、有効にするとセッションそのものに近い情報が外へ出ます。ツール引数にはBashのコマンドやファイルパスが入り、ツール出力にはファイルの中身やコマンドの出力が入ります。送信先は設定したOTelエンドポイントだけで、Anthropicには送られません。それでも、値に機微な情報が混ざる可能性は残ります。
判断の軸は3つです。
- 目的: 「誰がどのMCPを使ったか」の監査なら、
OTEL_LOG_TOOL_DETAILSだけで足ります。出力内容の調査まで要るときに限ってOTEL_LOG_TOOL_CONTENTを足す - 受け側: コレクターとバックエンドが、ソースコードやコマンド出力を保管してよい場所か。保存期間とアクセス権を決めておく。ツール内容の属性は既定で60KBまで届くので、属性値の上限が64KB程度のバックエンドなら収まる一方、上限がそれより小さいと受け側で欠けることがある
- 期間: 常時ではなく調査期間だけ有効にする運用もできる。管理設定でユーザーが外せない固定値にするか、各自のシェルに任せるかで、運用は変わる
OTEL_LOG_RAW_API_BODIESを有効にすると、この2つとOTEL_LOG_USER_PROMPTSが明かす内容への同意を含むものとして扱われます。API本文は会話履歴全体を含むため、まずツール詳細だけで足りるかを確認してからにします。
ユーザーの識別属性とこの変数の関係はClaude Code OTELユーザー特定で操作を監査ログに紐づけるに、管理設定側の記録はOTEL_LOG_MANAGED_SETTINGSで管理設定の解決結果を監査ログに残すにあります。
まとめ
OTEL_LOG_TOOL_DETAILSは入力側と名前の実値、OTEL_LOG_TOOL_CONTENTは出力側です。後者はトレーシングが前提で、Edit・Writeは前者も要ります。どちらもプロジェクト設定では有効にならないので、効果が見えないときは設定場所を先に疑います。