Claude CodeのOTLPメトリクスをdeltaからcumulativeに変える
Claude CodeのOTLPメトリクスは既定でdeltaです。OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCEでcumulativeに変える条件と設定をまとめます。
Claude CodeがOTLPで送るメトリクスは、既定ではdelta(差分)です。バックエンドが累積値(cumulative)を前提にしているなら、OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=cumulative を1行足すだけで切り替わります。
テレメトリを有効にして送信先を決める導入手順は、Claude CodeのOpenTelemetryで利用量とコストを可視化にあります。この変数は、Claude Codeの監視ドキュメントでは「Common configuration variables」表の1行にしか載っていません。何が変わるのか、どんなバックエンドで切り替えるのかは、OpenTelemetry仕様のデータモデルを合わせて読むと見えてきます。
切り替えは1変数で済む
ドキュメントの記載は次のとおりです。
| 項目 | 内容 |
|---|---|
| 変数名 | 内容OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE |
| 既定値 | 内容delta |
| 指定できる値 | 内容delta / cumulative |
| 切り替える目安 | 内容バックエンドがcumulative temporalityを期待するとき |
設定例です。シェルで指定する場合は、OTLPの接続先と一緒に置きます。
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=cumulative
claudesettings.json の env に置く形も使えます。管理設定の例は、ドキュメントでも env にOTEL変数を並べる形で示されています。
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.example.com:4318",
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": "cumulative"
}
}注意点が1つあります。OTLPエクスポーターを使うときは、プロトコルの指定が必須です。Claude Codeには既定のプロトコルがなく、OTEL_EXPORTER_OTLP_PROTOCOL かメトリクス専用の OTEL_EXPORTER_OTLP_METRICS_PROTOCOL のどちらかを設定する必要があります。
deltaとcumulativeは何が違うのか
OpenTelemetryのデータモデルでは、SumとHistogramの各データポイントが開始時刻(StartTimeUnixNano)を持ちます。この開始時刻の動き方がtemporalityの違いです。
開始時刻の動き方
delta
連続するデータポイントが、開始時刻を前へ進めます。区間は(T0, T1]、(T1, T2]、(T2, T3]のように重なりません。1点が「その区間で増えた分」を表します。
cumulative
連続するデータポイントが、同じ開始時刻を繰り返します。区間は(T0, T1]、(T0, T2]、(T0, T3]のように伸びます。1点が「開始からの合計」を表します。
仕様はそれぞれの向き不向きにも触れています。
- cumulativeは、Prometheusが代表例として挙げられています。送信側が過去の測定値をすべて覚えておく必要があり、そのメモリ負荷は系列の数(カーディナリティ)に比例します。一方、収集が途切れても欠損は累積値から自然に埋まります
- deltaは、Statsdが代表例です。サンプリングが成り立ち、カーディナリティのコストを送信側の外に移せます
- 送信側がdeltaで出し、受信側が累積に変換する構成も仕様の想定内です。Collectorがdeltaをcumulativeに変換する構成が、仕様のユースケースに挙がっています
Claude Codeのドキュメントが既定をdeltaにしている理由は、書かれていません。ただ、利用者の端末ごとに多数の session.id や user.account_uuid が付く構成では、送信側に状態を持たせないdeltaの性質と相性がよいと読めます。
OpenTelemetry仕様のOTLPメトリクスエクスポーターは、この変数の既定値をcumulativeとしています。Claude Codeの既定(delta)は、仕様の既定と逆です。そのため、OTel SDKの既定を前提に作ったダッシュボードやバックエンド設定をそのまま使うと、値の意味がずれる可能性があります。
cumulativeに切り替えるかの判断軸
切り替えの要否は、データの行き先で決まります。判断を3つの問いに分けます。
切り替えるかの見分け方
- Q送り先はdeltaを受け付けるバックエンドか、Collector経由でdelta→cumulativeに変換する構成か?答えがいいえのとき答えがはい
deltaのままで届きます。切り替えは不要です。
- Qバックエンドのドキュメントが「cumulative temporalityを期待する」と明記しているか?答えがいいえのとき答えがはい
明記があれば
cumulativeに変えます。明記がなければ、まず既定のdeltaで取り込み、グラフの形を確かめます。
cumulativeに切り替える
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=cumulative を設定し、再起動して反映を確かめます。
切り替えたあとはクエリ側の考え方も変わります。ここから先は、データモデルの定義から言えることです。
- delta: 各点がすでに「区間の増分」なので、期間内の点を足せば使用量になります
- cumulative: 各点が「開始からの合計」なので、期間の使用量は差を取る(rate / increase系の関数を使う)形になります。プロセスが再起動すると開始時刻が変わるため、バックエンドがその境界を扱えるかも確認ポイントです(次の節で詳しく見ます)
Claude Codeのメトリクスには、claude_code.token.usage や claude_code.cost.usage のようにコスト集計の中心になるものがあります。コストのダッシュボードを使い回す場合は、temporalityを切り替えたあとにクエリ側の集計関数も見直します。
再起動のたびにcumulativeの系列はどう見えるか
claude を終了して起動し直すと、新しいプロセスが新しい系列を始めます。データモデルでは、系列の最初の点で StartTimeUnixNano が TimeUnixNano より小さければ、既知の開始時刻から始まる「本物のリセット」です。ゼロが起点になるので、初期値を記録する必要はありません。
cumulativeでは、再起動のたびに合計が0から数え直されます。クエリ側は、値が前の点より下がったところをリセットとして扱えなければなりません。rate系の関数がこの前提で作られている場合は、そのまま使えます。
一方、開始時刻が分からないまま系列が再開する場合は、StartTimeUnixNano と TimeUnixNano が同じ値の、長さゼロの点で表します。この点は、それ以前に報告された点のことは何も分からず、データが欠けた可能性があることを示します。最初のこの点が失われると、2点目の増分が実際より多く数えられる恐れがあります。
deltaの場合、点ごとに区間が閉じています。各点の StartTimeUnixNano は直前の点の TimeUnixNano と一致するため、途切れた区間は、どの点にも覆われない時間帯(gap)として現れます。仕様はこの時間帯を「暗黙に未定義」としています。cumulativeのように後続の累積値が欠けた分を埋めることはなく、欠けた区間の増分は、バックエンドから見えません。
終了時にメトリクスが送り切れない問題は、Claude CodeのOTELタイムアウト2変数が扱っています。deltaで欠損が出るときは、その設定も合わせて確認する価値があります。
メトリクス専用の上書き変数との関係
同じ表には、OTLPの設定を信号ごとに上書きする変数が並んでいます。temporalityの変数は名前に METRICS が入っているので、メトリクスにだけ効きます。ログ側のエクスポーターには、対応するtemporality変数が表にありません。
| 変数 | 役割 | 汎用変数との関係 |
|---|---|---|
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL | 役割メトリクスのプロトコル | 汎用変数との関係汎用の OTEL_EXPORTER_OTLP_PROTOCOL を上書き |
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT | 役割メトリクスの送信先 | 汎用変数との関係汎用の OTEL_EXPORTER_OTLP_ENDPOINT を上書き |
OTEL_EXPORTER_OTLP_METRICS_HEADERS | 役割メトリクスの認証ヘッダー | 汎用変数との関係汎用の OTEL_EXPORTER_OTLP_HEADERS と統合(merge) |
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE | 役割メトリクスのtemporality | 汎用変数との関係汎用の対応変数なし(既定 delta) |
上書きと統合は挙動が違います。ドキュメントは、プロトコルとエンドポイントは「信号別の変数があればそちらを使う」、ヘッダーは「汎用ヘッダーに信号別ヘッダーを統合する」と書き分けています。ヘッダーを汎用側で共通にしておき、メトリクスだけ追加のトークンを足す、といった使い方ができます。
メトリクスとログを別のバックエンドへ送る構成と組み合わせると、メトリクス側だけをcumulative前提の基盤にできます。ゲートウェイ経由で送る構成は、Claude apps gatewayのテレメトリ設定に別途まとまっています。ドキュメントの「メトリクスとログを別の送信先へ」の例を土台にした形です。
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://metrics.example.com:4318
export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=cumulative
export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://logs.example.com:4317managed settingsで送信先を固定する構成では、ドキュメントの「How managed settings lock the OTLP destination」に、削除される変数の規則があります。エンドポイント、プロトコル、認証情報が対象で、temporalityの変数は一覧に載っていません。temporalityの変数は削除の対象外と読めるため、管理設定側にも書いておけば、削除規則の変化に左右されません。
切り替えが効いたかを確かめる
反映の確認は、ドキュメントの方法をそのまま使えます。セッション開始時に出る claude_code.session.count がバックエンドに届くかを見ます。
export OTEL_METRIC_EXPORT_INTERVAL=10000 # 既定は60000ms。確認中だけ短くする
claude1回目と2回目のセッションを起動し、同じ系列の点がどう並ぶかを比べます。cumulativeなら点が合計として積み上がります。deltaなら各点が区間の増分です。
何も届かないときは、claude --debug-file <path> で起動します。エクスポーターの失敗は [3P telemetry] の接頭辞で記録されます。[Anthropic telemetry] の行は、Anthropic側の別の運用テレメトリの記述で、自分の設定の失敗ではありません。
よくある疑問
LowMemory も指定できますか
OpenTelemetry仕様のOTLPエクスポーターには、Cumulative・Delta・LowMemory の3値が定義されています。Claude Codeのドキュメントに載っているのは delta と cumulative の2値です。LowMemory を指定したときの挙動は、ドキュメントに記載がなく未定です。
PrometheusエクスポーターもTemporalityを設定しますか
OTEL_METRICS_EXPORTER=prometheus は、http://localhost:9464/metrics でスクレイプさせる別の経路です。このtemporalityの変数は名前のとおりOTLPエクスポーター向けで、Prometheus経路との関係はドキュメントに記載がありません。Prometheusは仕様でcumulativeの代表例とされています。OTLPでPrometheus系の基盤に入れる場合にだけ、この変数を検討します。
まとめ
Claude CodeのOTLPメトリクスは既定がdeltaで、仕様の既定(cumulative)とは逆です。バックエンドが累積前提のときだけ、OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=cumulative を足します。この変数はメトリクス専用で、ログには効きません。切り替えたら、クエリの集計(増分を足すのか、累積の差を取るのか)も一緒に見直します。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。