3 本柱をつなぐ
🐱 この章の目次
なぜ相関が必要か
Metrics は「異常が起きている」を示し、Logs は「何が起きたか」を記録し、Traces は「どこで遅延したか」を可視化します。 これら 3 つを trace_id で紐づけることで、アラートからログ、ログからトレースへとシームレスに掘り下げる調査フローが実現します。 相関なしでは、3 つのシグナルがバラバラに存在し、調査のたびに手動でタイムスタンプを突き合わせる作業が発生します。
trace_id と span_id による紐づけ
すべてのログに trace_id と span_id を付与するのが相関の基本です。
import structlog
from opentelemetry import trace
def add_trace_context(logger, method_name, event_dict):
span = trace.get_current_span()
ctx = span.get_span_context()
if ctx.is_valid:
event_dict["trace_id"] = format(ctx.trace_id, "032x")
event_dict["span_id"] = format(ctx.span_id, "016x")
return event_dict
structlog.configure(
processors=[
add_trace_context,
structlog.processors.JSONRenderer(),
]
)
これにより、Loki で {trace_id="abc..."} と検索するだけで関連ログをすべて取得できます。
Exemplar でメトリクスからトレースへ
Exemplar は、メトリクスの個々のデータポイントに trace_id を紐づける Prometheus の機能です。 たとえば P99 レイテンシが急上昇したとき、その原因となった具体的なリクエストのトレースへ直接ジャンプできます。
# Grafana 上で Exemplar を有効にすると、グラフ上にドットが表示される
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
Grafana では Exemplar のドットをクリックすると、対応する Jaeger/Tempo のトレース画面に遷移します。
オブザーバビリティパイプライン
オブザーバビリティパイプライン は、各シグナルの収集・変換・ルーティングを統一的に行う基盤です。 OpenTelemetry Collector がこの役割を担い、アプリケーションから OTLP で受け取ったデータを各バックエンドに振り分けます。
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
exporters:
prometheus:
endpoint: 0.0.0.0:8889
loki:
endpoint: http://loki:3100/loki/api/v1/push
otlp/tempo:
endpoint: tempo:4317
service:
pipelines:
metrics:
receivers: [otlp]
exporters: [prometheus]
logs:
receivers: [otlp]
exporters: [loki]
traces:
receivers: [otlp]
exporters: [otlp/tempo]
実践: レイテンシスパイクの根本原因調査
具体的な調査フローを示します。
- Grafana のダッシュボードで P99 レイテンシの急上昇を検知する
- Exemplar をクリックして、遅延した具体的なトレースを Tempo で開く
- トレース内で最も時間を消費している Span(例:
db-query8 秒)を特定する - その Span の trace_id で Loki を検索し、
slow query detectedのログを見つける - ログの SQL とパラメータから、インデックス欠落が原因であると特定する
このように 3 本柱を trace_id で相関させることで、「通知→原因特定→対策」のループを数分で回せます。