相関 ID

分散システムで 1 つのリクエストに紐づく全ログを追跡するための一意な識別子

オブザーバビリティ分散システム

相関 ID とは

相関 ID (Correlation ID) は、分散システムにおいて 1 つのユーザーリクエストが複数のサービスを横断する際に、全サービスのログを紐づけるための一意な識別子である。UUID v4 が一般的に使われる。

マイクロサービスアーキテクチャでは、1 つの HTTP リクエストが API Gateway → 認証サービス → 注文サービス → 決済サービス → 通知サービスのように 5〜10 のサービスを経由することがある。相関 ID がなければ、障害発生時に「どのリクエストが」「どのサービスで」「なぜ失敗したか」を突き止めるのに、各サービスのログをタイムスタンプだけで照合する羽目になる。本番環境で秒間数百リクエストが流れている状況では、事実上不可能だ。

伝播の仕組み

相関 ID の基本的な流れは 3 ステップで構成される。

  1. エントリーポイント (API Gateway やロードバランサー) でリクエストごとに一意な ID を生成する
  2. 下流サービスへのリクエストヘッダー (X-Correlation-IDX-Request-ID) に ID を付与して伝播する
  3. 各サービスは受け取った ID を全ログ出力に含める
// 1. エントリーポイントで生成 or 受け取り
const correlationId = event.headers['x-correlation-id'] || crypto.randomUUID();

// 2. 全ログに自動付与 (Lambda Powertools の例)
const logger = new Logger({ persistentLogAttributes: { correlationId } });
logger.info('注文処理を開始', { orderId: '123' });
// 出力: {"correlationId":"a1b2c3...","message":"注文処理を開始","orderId":"123"}

// 3. 下流サービスへ伝播
await sqs.sendMessage({
  MessageBody: JSON.stringify({ ...payload, correlationId }),
  QueueUrl: QUEUE_URL,
  MessageAttributes: {
    'X-Correlation-ID': { DataType: 'String', StringValue: correlationId },
  },
});

ポイントは、HTTP ヘッダーだけでなく SQS メッセージ属性や EventBridge のイベントペイロードにも相関 ID を含めることだ。非同期処理の境界で ID が途切れると、追跡が不可能になる。

相関 ID とトレース ID の違い

混同されやすいが、相関 ID と分散トレーシングのトレース ID は役割が異なる。

観点 相関 ID トレース ID (X-Ray 等)
生成元 アプリケーションコード トレーシング SDK が自動生成
伝播方法 明示的にヘッダーやペイロードに含める SDK が自動的に伝播
用途 ログの横断検索 レイテンシ分析、サービスマップ
永続性 ログに残り続ける トレースの保持期間に依存

実務では両方を併用する。X-Ray のトレース ID でレイテンシのボトルネックを特定し、相関 ID で該当リクエストの詳細ログを CloudWatch Logs Insights で掘り下げる、という使い分けだ。

AWS サービスでの実装パターン

API Gateway

$context.requestId を相関 ID として使用できる。アクセスログのフォーマットに含めておけば、API Gateway のログと Lambda のログを紐づけられる。ただし、クライアントが独自の相関 ID を送ってくる場合は、クライアントの ID を優先し、API Gateway の requestId はサブ ID として扱う設計が柔軟だ。

X-Ray

X-Ray のトレース ID (1-xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx) は自動的にサービス間を伝播する。Lambda で X-Ray を有効にするだけで、API Gateway → Lambda → DynamoDB の呼び出しチェーンが可視化される。ただし X-Ray はサンプリングされるため、全リクエストを追跡するには相関 ID によるログベースの追跡が必要だ。

CloudWatch Logs Insights

相関 ID を構造化ログに含めておけば、1 つのリクエストに関する全ログを横断検索できる。

fields @timestamp, @log, @message
| filter correlationId = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
| sort @timestamp asc

複数のロググループ (API 用、注文処理用、決済用) を同時に検索できるため、サービスをまたいだリクエストの流れが時系列で把握できる。

よくある失敗パターン

非同期境界での途切れ

SQS や EventBridge を挟む非同期処理で相関 ID の伝播を忘れるケースが多い。同期的な HTTP 呼び出しでは意識しやすいが、メッセージキューを介すると「別のリクエスト」として扱ってしまいがちだ。メッセージ属性やイベントペイロードに必ず含める設計を最初から組み込む。

ログライブラリの設定漏れ

相関 ID を生成しても、一部のログ出力で含め忘れるケースがある。Lambda Powertools の Logger のように、一度設定すれば全ログに自動付与される仕組みを使うのが確実だ。console.log を直接使うと漏れる。

ID の衝突

UUID v4 の衝突確率は天文学的に低い (2^122 通り) が、タイムスタンプベースの短い ID を使うと衝突のリスクがある。本番環境では必ず UUID v4 か ULID を使う。

マイクロサービスやオブザーバビリティの技術書で、相関 ID を含む分散システムの可観測性設計が体系的に解説されている。

実践的な知識は関連書籍でも得られる。

関連用語