TL

エグザンプラとメトリクス→トレース相関

p99が悪化したダッシュボードから、原因になった具体的な1リクエストのトレースへ即座に飛びたい人へ。ヒストグラムのバケットに代表トレースIDを添えるエグザンプラの仕組みと、集約された異常指標から個別トレースへ辿る相関の原理を解説します。

応用オブザーバビリティ分散トレーシングPrometheusOpenTelemetryメトリクスSRE最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.エグザンプラは、ヒストグラムの各バケットへ『そのバケットに入った代表サンプル1件のtraceID・値・タイムスタンプ』を添付する仕組み。集約で失われる個別の素性を、バケットごとに1点だけ残してメトリクスとトレースを橋渡しする。
  • 2.メトリクスは安価だが集約済みで個を捨て、トレースは個を保つが高価でサンプリングされる。エグザンプラはこの溝を埋め、p99バケットの遅いサンプルから実在する遅いトレースへ最短で飛ぶ導線を作る。カーディナリティを増やさないのが要点。
  • 3.OpenMetricsの行末『# traceID=... 値 タイムスタンプ』として露出し、Prometheusが別ストアに保持する。SDKはサンプリングで残ったスパンのIDを優先記録し、間引かれた異常を取りこぼさない設計が肝になる。

集約が捨てる「個」をどう取り戻すか

メトリクスとトレースは観測の二本柱ですが、得意分野が正反対です。メトリクスは時系列に集約された数値で、安価かつ全数集計できる代わりに、個々のリクエストの素性を捨てていますhttp_request_duration_seconds のヒストグラムを見れば「直近1分の p99 が 1.2 秒に悪化した」とは分かるが、その遅さを生んだ具体的な1リクエストがどれかは分かりません。逆にトレース(/devops/distributed-tracing/)は1リクエストの経路を全スパンで保持し個を語れるが、高価ゆえにサンプリングされ、全数は残りません。

この間に深い溝があります。ダッシュボードで異常な集約値を見つけても、そこから実在する1本のトレースへ飛ぶ手段がない。担当者はトレースストアを「同じ時間帯・同じエンドポイント・遅そうなもの」で手探りする羽目になります。**エグザンプラ(exemplar)**はこの溝を埋めるために設計された機構です。

エグザンプラの一行定義

エグザンプラとは、ヒストグラムの各バケットに添える「そのバケットを代表する実サンプル1件」へのポインタです。中身は通常 traceID(と spanID)、観測された生の値、タイムスタンプ。集約値そのものは従来どおり数を保ちつつ、バケットごとに1点だけ「この区間に入った本物のリクエストはこれ」という痕跡を残すことで、メトリクスとトレースを糸でつなぎます。

ヒストグラムの構造とエグザンプラの居場所

なぜ「ヒストグラム」なのかは、その内部構造を見ると分かります。Prometheus 流のヒストグラムは、観測値を境界値で区切った累積バケットのカウンタ群です(/devops/histogram-quantile-internals/)。le="0.1"le="0.5"le="1" … のように「ある境界以下だった観測数」を数え、各観測は対応するバケットのカウンタを +1 するだけ——値そのものは捨てられ、どのバケットに何件入ったかだけが残ります。

エグザンプラは、この「+1」のときにそのバケットへ代表サンプルを1件だけ書き留める拡張です。バケットごとに最新(または特定基準で選んだ)1件の {traceID, 値, 時刻} を保持する。だからp99に相当する高 le のバケットを開けば、そこに入った遅いリクエストの実トレースIDが手に入る。集約はそのままなのでデータ量の増加は「バケット数 × 1サンプル分」に抑えられ、時系列の本数(カーディナリティ)は一切増えません。これが設計上の核心です。

エグザンプラはカーディナリティを増やさない

個別リクエストを追うために traceID をメトリクスのラベルにするのは禁じ手です。traceID は事実上一意なので、ラベルにした瞬間に時系列が無限に分裂し、TSDB が破綻します(/devops/metrics-cardinality/)。エグザンプラが巧妙なのは、traceIDラベルではなくサンプルの付帯データとして、本体の時系列とは別の経路・別ストアに置く点。だから時系列の数は不変のまま、個への導線だけを追加できます。「相関のためにカーディナリティを払わない」のがエグザンプラの存在意義です。

OpenMetrics での表現とPrometheusの保持

エグザンプラは OpenMetrics 規格で露出形式が定義されています。ヒストグラムのバケット行の末尾に、ハッシュ記号区切りでラベル集合・値・タイムスタンプを並べます。

# OpenMetrics のエグザンプラ付きバケット行
http_request_duration_seconds_bucket{le="1.0"} 4423 # {trace_id="a1b2c3d4..."} 0.98 1718900000.123
#                                    ↑バケット   ↑件数  ↑エグザンプラのラベル        ↑生値 ↑時刻

ハッシュ以降がそのバケットのエグザンプラです。le="1.0" のバケットに 4423 件入っており、その代表として「trace_id=a1b2c3d4 のリクエストが値 0.98 秒で観測された」と添えられている。スクレイプ時に Prometheus はこの付帯部を解析し、時系列本体とは別のエグザンプラストアへ格納します。本体のサンプルは (時刻, 値) の数値列のまま、エグザンプラは「どの系列のどの時刻に、どの traceID が代表だったか」を別管理する——これが時系列の純粋さを保ったまま個を紐づける仕組みです。

観点メトリクス本体エグザンプラトレース
粒度集約(全数の統計)バケットごとに代表1件個別リクエストの全経路
コスト極小・全数保持バケット数分のみ高価・サンプリング必須
保持する情報件数・分布traceID・生値・時刻全スパン・属性・因果
カーディナリティラベル次第増やさない(別ストア)該当せず
役割異常の検知検知から個への橋渡し原因の究明

メトリクス→トレースへ辿る相関の流れ

実際の調査動線はこうつながります。まず集約で異常を検知し、次にエグザンプラで代表トレースへ橋を架け、最後にトレースで根本原因を究明する——観測の三層を一本の線で貫きます。

1. ダッシュボードで検知   p99 latency が 0.5s → 1.2s に悪化(集約値)
2. 該当バケットを開く     le="1.0"〜"+Inf" の遅いバケットのエグザンプラを取得
3. traceID を取り出す     exemplar.trace_id = "a1b2c3d4..."
4. トレースへジャンプ     その traceID でトレースストアを直接引く
5. 原因を特定           遅延の主因スパン(DBクエリ、外部API待ち等)を可視化

要点は、手順2で**「遅いバケット」を狙って開けることです。エグザンプラはバケット単位で代表を持つので、p99 に効いている高 le のバケットからは実際に遅かったサンプルのID**が、低 le からは速かったサンプルのIDが得られる。「全体としてp99が悪い」という統計的事実から、「だからこの1本が遅かった」という具体例へ、推測なしで降りられます。これは原因究明の初手を大幅に短縮します。

エグザンプラは『代表』であって全数ではない

1バケットにつき保持される代表は通常ごく少数(多くは1件)です。だから「このバケットに入った遅いリクエストすべて」を列挙する用途には使えません。エグザンプラの役割は代表点への即時ジャンプであり、網羅的な抽出はトレース側のクエリやテールサンプリング(/devops/tail-sampling-statistics/)の仕事です。「異常の典型例を1つ、最短で掴む」のがエグザンプラ、「異常を漏れなく残す」のがテールサンプリング、と役割を分けて捉えると誤用が減ります。

取りこぼしを防ぐ:サンプリングとの整合

エグザンプラの落とし穴はサンプリングとの相互作用です。記録された traceID のトレースが、サンプリングで間引かれてストアに存在しなければ、ジャンプ先が空振りします。エグザンプラは「ここに遅いリクエストがいた」と告げるのに、その本体が消えている——観測として最も悔しい欠落です。

これを避ける定石が、サンプリングで残ると決まったスパンのIDを優先的にエグザンプラへ記録する設計です。OpenTelemetry の SDK では計装ライブラリがスパンの sampled フラグを参照でき、メトリクスのエグザンプラにはサンプリング済み(=保存される)コンテキストの traceID を選んで載せられます(/devops/opentelemetry-internals/)。とりわけ高遅延・エラーを必ず残すテールサンプリングと組み合わせれば、「異常バケットのエグザンプラが指す先には、必ず実トレースがある」状態を作れます。逆にヘッドサンプリングで結果と無関係に間引くと、エグザンプラだけ残ってトレースが無い空振りが頻発します。

試験・面接での要点

エグザンプラはヒストグラムの各バケットに代表サンプルの traceID・生値・時刻を添える機構で、集約された異常メトリクスから個別トレースへの導線を、カーディナリティを増やさずに作る——この一文が核心です。traceID をラベルにするとカーディナリティ爆発を起こすので、ラベルではなくサンプルの付帯データとして別ストアに置く点、OpenMetrics ではバケット行末にハッシュ区切りで露出する点、そしてサンプリングで残るスパンのIDを記録しないとジャンプ先が空振りする点を挙げられると上級者の加点になります。

まとめ

  • メトリクスは集約ゆえに個を捨て、トレースは個を保つが高価でサンプリングされる。エグザンプラはこの溝を埋め、集約値から代表トレースへの橋を架ける(/devops/observability-pillars-internals/)。
  • エグザンプラはヒストグラムの各バケットに代表サンプル1件traceID・生値・時刻)を添える。集約はそのまま、増えるのはバケット数分の付帯データだけ。
  • traceIDラベルにせず付帯データとして別ストアに置くので、カーディナリティを増やさずに個への導線を足せる。これが設計の核心。
  • OpenMetrics ではバケット行末のハッシュ区切りで露出し、Prometheus が別ストアに保持。p99 に効く高 le バケットを開けば実際に遅かったサンプルのIDが取れる。
  • 調査動線は**検知(集約)→橋渡し(エグザンプラ)→究明(トレース)**の三層を一本で貫く。
  • 落とし穴はサンプリングとの空振り。残ると決まったスパンのIDを記録し、テールサンプリングと組めば「異常バケットの指す先に必ず実トレースがある」状態を作れる。

DevOps/インフラ Article

エグザンプラとメトリクス→トレース相関を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

オブザーバビリティ

比較で見る軸

難易度: advanced / カテゴリ: DevOps/インフラ / タグ数: 6

導入後に効く点

メトリクスは安価だが集約済みで個を捨て、トレースは個を保つが高価でサンプリングされる。エグザンプラはこの溝を埋め、p99バケットの遅いサンプルから実在する遅いトレースへ最短で飛ぶ導線を作る。カーディナリティを増やさないのが要点。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
DevOps/インフラ
タグ数
6

判断チェックリスト

  • 自社の用途が「オブザーバビリティ / 分散トレーシング」に近いか確認する。
  • 強みである「エグザンプラは、ヒストグラムの各バケットへ『そのバケットに入った代表サンプル1件のtraceID・値・タイムスタンプ』を添付する仕組み。集約で失われる個別の素性を、バケットごとに1点だけ残してメトリクスとトレースを橋渡しする。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

オブザーバビリティ分散トレーシングPrometheusOpenTelemetryメトリクスオブザーバビリティ分散トレーシングPrometheus