ひとことで言うと#
**ログ(何が起きたか)、メトリクス(どのくらい起きているか)、トレース(どこで起きたか)**の3つの信号を組み合わせて、複雑なシステムの内部状態を外部から理解可能にする手法。「予想していなかった問題」にも対応できる力を持たせる。
押さえておきたい用語#
- 構造化ログ
- JSON形式などでキーバリューペアとして記録されるログ。検索性・フィルタリング性に優れる。
- スパン(Span)
- 分散トレーシングにおいて、1つのサービスでの処理の開始から終了までの区間を表す単位。
- トレースID
- 1つのリクエストが複数サービスを横断する際に一貫して付与される識別子。ログとトレースの紐付けに使う。
- OpenTelemetry
- メトリクス・ログ・トレースをベンダー中立で収集するための標準仕様とSDK。CNCFのプロジェクト。
- サンプリング
- 全データではなく一部のデータだけを収集・保存すること。コスト管理のために必要。
オブザーバビリティの3本柱の全体像#
こんな悩みに効く#
- 障害が発生しても、原因特定に何時間もかかる
- 「どこかが遅い」のはわかるが、どのサービスが原因か特定できない
- ダッシュボードはあるが、未知の問題を調査する手段がない
基本の使い方#
数値で表せる時系列データを収集・可視化する。
- RED メトリクス: Rate(リクエスト率)、Errors(エラー率)、Duration(所要時間)
- USE メトリクス: Utilization(使用率)、Saturation(飽和度)、Errors
- Prometheus、Datadog、CloudWatchなどで収集
- ダッシュボードとアラートを設定する
ポイント: メトリクスは「異常の検知」に強い。「いつもより遅い」「エラーが増えた」を最初に教えてくれる。
個々のイベントの詳細情報を構造化ログとして記録する。
- JSON形式の構造化ログで、検索・フィルタリングを容易にする
- リクエストID、ユーザーID、タイムスタンプなどのコンテキストを付与する
- ログレベル(ERROR, WARN, INFO, DEBUG)を適切に使い分ける
- ELK Stack、Loki、CloudWatch Logsなどで集約する
ポイント: ログは「何が起きたかの証拠」。構造化されていなければ使い物にならない。
1つのリクエストが複数サービスを通過する流れを可視化する。
- OpenTelemetry でトレースデータを生成する
- Jaeger、Zipkin、AWS X-Rayなどで可視化する
- スパン(各サービスでの処理時間)を確認し、ボトルネックを特定する
ポイント: マイクロサービス環境では、トレースなしでの障害調査はほぼ不可能。
メトリクス → トレース → ログの順で掘り下げるワークフローを構築する。
- メトリクスで異常を検知 → 該当時間帯のトレースを検索 → 遅いスパンのログを確認
- トレースIDをログに含め、ログからトレースにジャンプできるようにする
- ダッシュボードからワンクリックで関連データに遷移できるUI
ポイント: 3つの柱が「つながって」初めて真のオブザーバビリティが実現する。
具体例#
メトリクスで異常検知: 注文APIのp99レイテンシが通常200ms → 3秒に悪化。Grafanaのダッシュボードでアラート発報。
トレースでボトルネック特定: 該当時間帯のトレースを検索。注文API → 在庫サービス → 決済サービスの流れで、在庫サービスのスパンが2.8秒かかっていることを発見。
ログで根本原因特定: 在庫サービスのログをトレースIDで検索。「Database connection pool exhausted, waiting for available connection」というWARNログを発見。DB接続プールが枯渇していた。
結果: DB接続プールのサイズを20 → 50に拡大し、接続リークしていたクエリを修正。検知から原因特定まで15分で完了。
状況: 12のマイクロサービスがそれぞれ異なるログ形式・異なる監視ツールを使用。障害調査時に6つのダッシュボードを行き来する必要があり、平均調査時間が2時間。
統合導入:
- 全サービスにOpenTelemetry SDKを導入
- メトリクス → Prometheus + Grafana
- ログ → Loki(トレースID付き構造化ログ)
- トレース → Jaeger(Grafana Tempoに連携)
- Grafanaでメトリクス→トレース→ログをワンクリック遷移可能に
結果: 障害調査の平均時間が2時間から18分に短縮。「メトリクスで異常を見つけたらトレースをクリック、遅いスパンのログを確認」という一貫したワークフローが全エンジニアに定着。
状況: 全トレースを保存した結果、月間のJaegerストレージコストが120万円に。ログも全量保存で月80万円。合計200万円/月。
最適化:
- トレース: 正常リクエストは1%サンプリング、エラーリクエストは100%保存
- ログ: DEBUGログは開発環境のみ、本番はINFO以上
- メトリクス: リテンションを90日→30日に変更(長期はS3にアーカイブ)
結果: コストが200万円/月から45万円/月に削減。障害調査に必要なデータは100%保持されており、調査品質に影響なし。
やりがちな失敗パターン#
- ログを構造化しない — テキスト形式の非構造化ログは検索性が悪く、大量のログから必要な情報を見つけられない。JSON形式の構造化ログを標準にすること
- 3つの柱をバラバラに運用する — メトリクス、ログ、トレースが別々のツールで連携していないと、調査に時間がかかる。トレースIDで3つを横断検索できる仕組みを作ること
- すべてのデータを保存しようとする — ログとトレースを全量保存するとコストが爆発する。サンプリングとリテンションポリシーを適切に設定すること
- 導入して満足する — ツールを入れただけでは障害対応は速くならない。調査のワークフロー(メトリクス→トレース→ログ)をチームで訓練すること
まとめ#
オブザーバビリティの3本柱(メトリクス・ログ・トレース)は、複雑なシステムの 「今何が起きているか」 を理解するための基盤。3つを個別に導入するだけでなく、相互に連携させることで、未知の問題にも迅速に対応できる体制を作ろう。