Claude Media
OTEL_METRICS_EXPORTERをprometheusにしてClaude Codeのメトリクスを直接スクレイプ

OTEL_METRICS_EXPORTERをprometheusにしてClaude Codeのメトリクスを直接スクレイプ

OTEL_METRICS_EXPORTER=prometheusにすると、Claude Codeのプロセスがlocalhost:9464/metricsを公開します。単位が落ちる条件、ホストとポートの変更、ポート衝突の見つけ方をまとめます。

OTEL_METRICS_EXPORTER=prometheusでは何が起きるか

OTEL_METRICS_EXPORTERにprometheusを指定すると、Claude Codeのプロセスがhttp://localhost:9464/metricsでメトリクスを公開します。OTLPのようにコレクターへ送り出すのではなく、Prometheusが取りに来る(pull)形です。コレクターを立てずに、手元のPrometheusだけで利用量とコストを見たい場面に向きます。

最小の設定は2行です。

export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=prometheus
claude

CLAUDE_CODE_ENABLE_TELEMETRYは有効化の必須スイッチです。OTLPで送る構成と違い、OTEL_EXPORTER_OTLP_PROTOCOLやエンドポイントの指定は要りません。送信先を持たないからです。OTLP側の全体像はClaude CodeのOpenTelemetryで利用量とコストを可視化にあります。

この記事が扱うのは、prometheus単独で使うときに引っかかる4点です。

つまずき

prometheus単独で引っかかる4点

  • 単位が落ちる

    USD・tokens・sの単位が付かなくなります。otlp,prometheusの併記なら残ります。

  • project設定では効かない

    ホストとポート、さらにエクスポーターの選択自体が、リポジトリ側の設定では無視されます。

  • ポートが衝突すると黙る

    既定では診断エラーが表に出ません。CLAUDE_CODE_OTEL_DIAG_STDERR=1で見えるようになります。

  • self-hostedは並列数で変わる

    --capacityが1のときだけ、セッション自身が9464を持ちます。

Prometheus側のscrape設定を書く

公開先が決まっているので、Prometheusの設定は静的ターゲットで足ります。次は一般的なprometheus.ymlの書き方に沿った例で、ジョブ名は任意です。

scrape_configs:
  - job_name: claude-code
    static_configs:
      - targets: ["localhost:9464"]

Claude Codeを起動したあと、Prometheusに任せる前にcurlで公開内容を見ておくと切り分けが楽です。

curl -s localhost:9464/metrics | grep claude_code

ここに何も出ないなら、Prometheusの設定より手前に原因があります。セッションを開始するとclaude_code.session.countが発行されるので、まず起動直後のセッションで見るのが確実です。

設定ファイルの検証は、Claudeに任せる作業として相性が良い部分です。prometheus.ymlを書かせたあと、promtool check configを実行させて出力を読ませる反復にすると、書式の誤りをその場で直せます。アラートルール側の検証手順はClaude CodeでPrometheusのアラートルールを書き、promtoolで検証するで扱っています。

prometheus単独だと単位が落ちる

OTEL_METRICS_EXPORTERにprometheusだけを書いたとき、Claude CodeはUSD・tokens・sの3つの単位をエクスポート内容から外します。スクレイプの出力をPrometheusのテキスト形式として正しく保つための処理です。

影響を受けるのは、単位を持つ次の3つです。

メトリクス単位prometheus単独
claude_code.cost.usage単位USDprometheus単独単位が付かない
claude_code.token.usage単位tokensprometheus単独単位が付かない
claude_code.active_time.total単位sprometheus単独単位が付かない

セッション数やコミット数のように単位を持たないメトリクスは、もともと単位が付きません。

同じ変数にotlp,prometheusのようにエクスポーターを併記すると、単位は残ります。OTLPで外部に送りつつ、手元でも見たい構成はこちらです。

export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp,prometheus
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

併記するとOTLP側の設定も必要になります。Claude CodeにはOTLPのプロトコルの既定値がないため、OTEL_EXPORTER_OTLP_PROTOCOLの指定は省けません。

PromQLでコストを集計するときは、Prometheus上の名前で書きます。セルフホスト環境のリファレンスにあるクエリは、コストのカウンターをclaude_code_cost_usage_totalと書いています。ドット区切りのメトリクス名が、アンダースコア区切りで公開される例です。prometheusだけの単独構成で実際に公開される名前は、クエリを書く前にcurl -s localhost:9464/metrics | grep costで確かめてください。

ホストとポートはproject設定では効かない

公開先を変えるのはOTEL_EXPORTER_PROMETHEUS_HOSTとOTEL_EXPORTER_PROMETHEUS_PORTです。9464が他のプロセスに使われているときは、PORTで別の番号を指定します。HOSTは、メトリクスを公開するホストを変える変数です。

ただし、この2変数はリポジトリの.claude/settings.jsonと.claude/settings.local.jsonに書いても無視されます。同じ扱いを受けるのは、OTEL_METRICS_EXPORTERをはじめとするエクスポーターの選択変数です。チェックアウトしたリポジトリが、テレメトリの有無や送り先を勝手に決められないようにするための仕様で、v2.1.282以降で適用されます。

リポジトリ側から許されるのは、テレメトリを止める方向の値だけです。OTEL_METRICS_EXPORTER=noneは、project設定でも効きます。

書く場所は次のいずれかです。

  • シェルの環境変数
  • ユーザー設定(~/.claude/settings.json)
  • 管理設定
  • --settingsで渡すファイル

ユーザー設定に書く場合は、次の形になります。

{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_METRICS_EXPORTER": "prometheus",
    "OTEL_EXPORTER_PROMETHEUS_PORT": "9465"
  }
}

落とし穴

project設定に書いても、非対話の実行では警告が出ない

対話セッションなら、無視された変数があると起動時に通知が出ます。/statusかclaude doctorを実行すると、無視された変数の名前が一覧で見えます(値は出ません)。-pによる非対話実行やAgent SDKのセッションでは通知が出ません。アップグレード後にメトリクスが空になったら、変数をユーザー設定や管理設定、ジョブの環境、--settingsのファイルのいずれかへ移します。

ホストとポートの既定値として、ドキュメントに載っているのはhttp://localhost:9464/metricsというURLだけです。ホスト変数の既定値を表で示した記載はありません。ポートだけを変えたいなら、PORTのみを設定して、URLがどうなるかをcurlで確かめるのが確実です。

ポート衝突は診断エラーを出さないと見えない

Prometheusのエクスポーターが9464を取れなかったとき、既定ではエラーが表に出ません。OpenTelemetryエクスポーターの診断エラーは、--debugを付けたときにだけ現れます。ポートの衝突のような設定ミスは、気づかないうちに失敗するわけです。

CLAUDE_CODE_OTEL_DIAG_STDERR=1を設定すると、診断エラーが標準エラー出力に書かれます。v2.1.179以降で使えます。

CLAUDE_CODE_OTEL_DIAG_STDERR=1 claude

衝突の原因は、ほかのサービスだけとは限りません。同じ既定ポートのまま別のターミナルでもう1つセッションを起動した場合も、同じ9464を取り合う構図になります。複数のセッションを並べて見たいときは、起動するシェルごとにOTEL_EXPORTER_PROMETHEUS_PORTを変え、targetsにその数だけポートを並べる考え方になります。

エクスポーターの失敗は、claude --debug-file <path>で出力したログにも[3P telemetry]として残ります。[Anthropic telemetry]で始まる行はAnthropic側の運用テレメトリで、自分の設定の不具合とは無関係です。

つまずいたときの切り分けは、上から順に確かめます。

切り分け

9464/metricsが空のときの切り分け

  1. QOTEL_METRICS_EXPORTERとポートの変数を、project設定に書いていますか?
    答えがいいえのとき

    その変数は無視されています。シェルかユーザー設定、管理設定、--settingsのファイルへ移します。

    答えがはい
  2. QCLAUDE_CODE_ENABLE_TELEMETRYを1にしていますか?
    答えがいいえのとき

    有効化の必須スイッチです。これを設定します。

    答えがはい
  3. QCLAUDE_CODE_OTEL_DIAG_STDERR=1で起動して、エラーが出ていませんか?
    答えがいいえのとき

    ポート衝突が疑わしい状態です。OTEL_EXPORTER_PROMETHEUS_PORTで別のポートを指定します。

    答えがはい

curlで見える状態

curl -s localhost:9464/metrics | grep claude_codeに行が出れば、あとはPrometheus側の設定の話です。

セッションごとに系列が増える点とself-hostedでの違い

Prometheusに入るメトリクスには、属性がラベルとして付きます。OTEL_METRICS_INCLUDE_SESSION_IDの既定はtrueで、session.idが属性に含まれます。セルフホスト環境のリファレンスは、9464上のsession_idラベルにClaude Code自身のsession.idが入ると書いています。セッションが増えるほど系列も増える構造です。系列数を抑えたいときはfalseにします。

追加できる属性として、OTEL_METRICS_INCLUDE_ENTRYPOINTやOTEL_METRICS_INCLUDE_VERSIONもあります。どれも既定は無効です。仕組みと選び方はOTEL_METRICS_INCLUDE_ENTRYPOINTとはで整理しています。

self-hostedのRunner環境では、--capacityの値で動きが分かれます。

--capacityセッションの子プロセスメトリクスの出どころ
1(既定)セッションの子プロセス自分でポート9464にエンドポイントを持つメトリクスの出どころ各セッションの9464
2以上セッションの子プロセスRunnerが、子のカウンターとゲージを自身の/metricsに再公開するメトリクスの出どころRunnerの/metrics

capacityが2以上のときは、RunnerのホストでOTEL_METRICS_EXPORTER=prometheus、セッション側でCLAUDE_CODE_ENABLE_TELEMETRY=1を設定します。ヒストグラムは中継されません。フラグと環境変数の対応はClaude Codeセルフホスト環境のCLIフラグ・メトリクスリファレンスにまとめています。

9464を直接スクレイプしてRunnerのメトリクスと突き合わせるときは、結合キーに注意が要ります。Claude Code側のsession_idはRunnerの系列と一致しないため、ccr_session_idで結合します。この属性の読み方はccr.session.idでクラウドセッションのテレメトリを特定する方法に詳しくあります。

まとめ

prometheus単独は、コレクターなしで手元のPrometheusに繋げる最短の構成です。代わりに、単位が落ちること、設定の置き場所がproject設定ではないこと、ポート衝突が黙って起きることの3点を前提にします。USDやtokensの単位を後段で使いたいなら、otlp,prometheusの併記が分かれ目です。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. code.claude.com/docs/en/monitoring-usage
  2. code.claude.com/docs/en/settings-reference
  3. code.claude.com/docs/en/env-vars
  4. code.claude.com/docs/en/self-hosted-environments-reference
この記事を共有:XはてブLinkedIn