Claude Media
Claude CodeのOTELタイムアウト2変数 — 終了時の欠落を防ぐ調整

Claude CodeのOTELタイムアウト2変数 — 終了時の欠落を防ぐ調整

CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MSとCLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MSの既定値、役割の違い、終了時にメトリクスが欠けるときの調整手順をまとめます。

CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MSはスパンを送り切るまでの待ち時間、CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MSは終了時にOpenTelemetryのエクスポーターが完了するまでの待ち時間です。既定値はそれぞれ5000ミリ秒と2000ミリ秒。セッションの最後のメトリクスがバックエンドに届かないときは、後者を延ばすのが公式の示す調整です。

2つのタイムアウト変数の役割と既定値

どちらもClaude CodeがOpenTelemetryで利用量とコストを送るときの「待ち時間の上限」を決める環境変数です。送信間隔を決める変数ではありません。

くらべる

2つのタイムアウト変数の違い

既定 5000

CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS

保留中のスパンをフラッシュするときのタイムアウト(ミリ秒)です。対象はスパン、つまりトレースです。

既定 2000

CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MS

終了時にOpenTelemetryエクスポーターが完了するまでのタイムアウト(ミリ秒)です。環境変数リファレンスには「終了時にメトリクスが落ちるなら増やす」と添えられています。

環境変数リファレンスの記述はこの1行ずつだけです。フラッシュ側の説明に出てくるのはスパンだけで、メトリクスやログへの影響は書かれていません。症状に合わせて選ぶと次のようになります。

症状まず触る変数前提
終了直前のメトリクスがバックエンドに無いまず触る変数CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MS前提環境変数リファレンスが「増やす」と明記している
トレースの末尾のスパンが欠けるまず触る変数CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS前提トレースが有効であること(CLAUDE_CODE_ENABLE_TELEMETRY=1、CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1、OTEL_TRACES_EXPORTERの3つ。後述)
途中経過がなかなか届かないまず触る変数送信間隔の変数前提タイムアウトの変数では変わらない

終了時にメトリクスが欠ける理由

メトリクスの既定の送信間隔は60秒(OTEL_METRIC_EXPORT_INTERVAL、既定60000ミリ秒)です。ログは既定5秒(OTEL_LOGS_EXPORT_INTERVAL)で、スパンのバッチ送信は既定5秒(OTEL_TRACES_EXPORT_INTERVAL)になります。

送信間隔が長いメトリクスは、セッション終了の時点で「まだ送っていない分」が残りやすい種類です。終了時にその残りを出し切るための猶予が、2000ミリ秒の終了タイムアウトにあたります。バックエンドへの経路が遅いと、2秒では送信が終わる前にプロセスが閉じます。

ここで注意したいのは、ドキュメントが因果まで説明しているわけではない点です。書かれているのは「既定は2000ミリ秒」「終了時にメトリクスが落ちるなら増やす」の2点だけです。上の説明はOpenTelemetryの一般的な仕組みからの読み解きなので、実環境では次の節の手順で効果を確かめます。

延ばし方と設定例

シェルで設定する場合は、起動前に環境変数を置くだけです。

export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MS=10000
claude

settings.jsonのenvに書くこともできます。ただしテレメトリを有効にするCLAUDE_CODE_ENABLE_TELEMETRYと、出力先を決めるOTEL_METRICS_EXPORTERなどは、ユーザー設定(~/.claude/settings.json)か管理設定に置く必要があります。プロジェクト設定とローカル設定に書いても無視されます。送信先とプロトコルは上のシェル例と同じく別に設定します。ユーザー設定に置いた例は次のとおりです。

{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_METRICS_EXPORTER": "otlp",
    "CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MS": "10000",
    "CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS": "10000"
  }
}

値は整数のミリ秒で、10000は10秒です。延ばした分だけ、終了のたびに最大でその時間だけプロセスの終了が遅れる可能性があります。この副作用についての記載はないので、対話セッションで終了が引っかかる感覚が出たら値を戻します。

置き場所の違いは、2つのタイムアウト変数にも関わります。環境変数リファレンスによると、テレメトリの有効化・送信先・内容の取得を決める変数はプロジェクト設定とローカル設定では無視されます。一方、OTEL_RESOURCE_ATTRIBUTESと、送信間隔・タイムアウト・圧縮の変数(例としてOTEL_METRIC_EXPORT_INTERVAL)は、プロジェクト設定とローカル設定からでも効くと書かれています。2つの変数は名前にTIMEOUTを含むので、この「タイムアウトの変数」に当たると読めますが、変数名を挙げた個別の記載はありません。リポジトリに置く設定で展開するチームは、反映を確かめてからにします。

FLUSH_TIMEOUTが効くのはトレースを有効にしたときだけ

CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MSの対象はスパンで、トレースは既定で無効です(beta機能)。無効のままこの値を変えても、何も起きません。有効にするには次の3つが要ります。

  • CLAUDE_CODE_ENABLE_TELEMETRY=1
  • CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1(ENABLE_ENHANCED_TELEMETRY_BETAでも受け付けられます)
  • OTEL_TRACES_EXPORTERに送り先を指定(console、otlp、none。noneは無効化)
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS=10000
claude

トレース専用の送り先はOTEL_EXPORTER_OTLP_TRACES_ENDPOINT、プロトコルはOTEL_EXPORTER_OTLP_TRACES_PROTOCOL、認証ヘッダーはOTEL_EXPORTER_OTLP_TRACES_HEADERSで、共通の設定を上書きできます。スパンのバッチ送信は既定5秒(OTEL_TRACES_EXPORT_INTERVAL)で、メトリクスよりずっと短い間隔です。管理設定の側から見ると、OTEL_METRICS_EXPORTER・OTEL_LOGS_EXPORTER・OTEL_TRACES_EXPORTERの3つの選択子は通常のキーごとの優先順位で扱われます(v2.1.223以降)。開発者の設定で信号を無効にしたり、コンソール出力に切り替えたりできるため、固定したい場合は管理設定にも同じ選択子を置きます。トレースが届かないときは、この上書きも疑う価値があります。

スパンにはプロンプト本文やツールの入力が既定で含まれず、含めたいときはOTEL_LOG_USER_PROMPTS=1などを別に設定します。

効いたかを確かめる手順

延ばした値が効いたかどうかは、終了直前の数値が増えるかで判断します。送信先を本番に向ける前に、コンソール出力と短い間隔で試す方法があります。

手順

終了時の欠落を再現して確かめる

  1. 1

    コンソール出力で、終了時にメトリクスが出るかを見る

    OTEL_METRICS_EXPORTER=console(console,otlpのようにカンマ区切りで併用もできます)にして、送信間隔は既定の60秒のままプロンプトを1つ送り、すぐ終了します。最後のメトリクスが画面に出るかを見てください。ここで何も出なければ、バックエンドに届かない以前に、設定の置き場所(ユーザー設定か管理設定か)や有効化の変数を疑います。

  2. 2

    OTLPに切り替え、同じ短いセッションで最後の値を確かめる

    OTEL_METRICS_EXPORTER=otlpと送信先を設定し、手順1と同じ操作をします。バックエンドにセッション最後の値があるかを確認します。無ければ、これが欠落の再現です。

  3. 3

    終了タイムアウトだけを変えて、手順2を繰り返す

    CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MSを2000から10000にして、同じ操作で最後の値を比べます。変えるのは1つだけにすると、効果の切り分けができます。

届かないときの原因調査には、2つの手段があります。claude --debug-file <path>で書き出したログでは、エクスポーターの失敗が[3P telemetry]のエラーとして出ます。CLAUDE_CODE_OTEL_DIAG_STDERR=1を設定すると、診断エラーを標準エラー出力へ書けます(v2.1.179以降)。タイムアウトの問題か、接続先や認証の誤りかは、この出力で見分けられます。

欠落が終了タイムアウトの問題とは限らない場合

終了時に何かが消える現象は、OpenTelemetryの送信以外にもあります。

  • SessionEndフックの時間切れ: 終了時のフックには別の予算があり、既定は1.5秒です。CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MSで上書きできます。フックの後始末が途中で切れる場合は、SessionEndフックの記事が参考になります
  • 終了時のメッセージ消失: 別の不具合として修正された例があります。v2.1.291のリリースノートを参照してください
  • プロトコルの未指定: Claude Codeに既定のプロトコルはありません。otlpを選んだ信号ごとに、OTEL_EXPORTER_OTLP_PROTOCOLか信号別のプロトコル変数を設定します(grpc、http/json、http/protobuf)。未設定のままタイムアウトを延ばしても改善しません
  • 管理設定による送信先の上書き: 管理設定でOTEL_EXPORTER_OTLP_ENDPOINTなどを指定している端末では、起動時に開発者が設定した信号別のエンドポイントや認証情報が取り除かれ、デバッグログに警告が出ます(エンドポイントの上書きに気づきにくい例です)
  • 送信先の設定ミス: エンドポイントやヘッダーが誤っていれば、タイムアウトを延ばしても届きません。ログ側の項目はOTEL_LOG_TOOL_DETAILSとTOOL_CONTENTの記事のように別変数で絞れます

終了を待つ時間の設定は、他にも用意されています。チーム機能の終了待ちを決める変数はCLAUDE_CODE_TEAM_TEARDOWN_PARK_TIMEOUT_MSの記事にあります。ここで扱った2変数とは対象が別で、OpenTelemetryの送信には関わりません。

調整の目安をどう置くか

2つの変数を、同時に大きくする必要はありません。メトリクスが欠けるなら終了側、スパンが欠けるならフラッシュ側と、症状に対応させて片方だけ上げます。上げる幅は倍々で試し、欠落が止まった値で止めます。

CI上の短いジョブのように、起動から終了までが数秒のセッションでは、定期送信が一度も走らずに終了時の送信だけが頼りになる場面があります。このような運用では、終了タイムアウトの余裕が結果に直結します。逆に、長く続く対話セッションでは定期送信ですでに届いている分が多く、終了時に残る未送信分は相対的に小さくなると考えられます。

関連する変数の全体像はClaude Codeの環境変数リファレンスにまとまっています。設定ファイルの置き方はClaude Code設定ガイドを参照してください。

この記事を共有:XはてブLinkedIn