ストーリー
高橋アーキテクトがホワイトボードに書いた。
障害調査の基本フロー
graph TD
S1["Step 1: 影響範囲の把握<br/>どのサービス? どのエンドポイント? どのユーザー?"]
S2["Step 2: タイムラインの特定<br/>いつから始まった? 何がトリガー?"]
S3["Step 3: エラーパターンの分析<br/>同じエラーが繰り返されている? 特定の条件?"]
S4["Step 4: 相関関係の発見<br/>直前にデプロイがあった? 外部サービスの障害?"]
S5["Step 5: 根本原因の特定<br/>コード? 設定? インフラ? 外部依存?"]
S1 --> S2 --> S3 --> S4 --> S5
実践テクニック
1. traceIdによるリクエスト追跡
// 1つのリクエストに関するすべてのログを取得
// CloudWatch Logs Insights
const traceQuery = `
fields @timestamp, service, level, message, duration
| filter traceId = "abc123def456"
| sort @timestamp asc
`;
// 結果例:
// 10:30:45.100 api-gateway INFO "Received POST /orders"
// 10:30:45.105 auth-service INFO "Token validated" 12ms
// 10:30:45.120 order-service INFO "Creating order ORD-001"
// 10:30:45.135 order-service INFO "Validating inventory"
// 10:30:45.200 inventory-svc WARN "Low stock for SKU-042" 65ms
// 10:30:45.250 payment-svc INFO "Charging payment"
// 10:30:48.250 payment-svc ERROR "Payment timeout" 3000ms ← ここ!
// 10:30:48.260 order-service ERROR "Order creation failed"
2. 時系列でのエラー集計
// エラースパイクの検出
const errorSpikeQuery = `
fields @timestamp
| filter level = "ERROR"
| stats count(*) as errorCount by bin(5m)
| sort @timestamp asc
`;
// 結果例:
// 10:00 errorCount: 3
// 10:05 errorCount: 2
// 10:10 errorCount: 145 ← スパイク発生!
// 10:15 errorCount: 230
// 10:20 errorCount: 180
3. エラーコード別の集計
// エラーの種類を把握
const errorBreakdown = `
fields errorCode, message
| filter level = "ERROR"
| filter @timestamp >= "2025-01-15T10:00:00Z"
| stats count(*) as cnt by errorCode
| sort cnt desc
`;
// 結果例:
// PAYMENT_TIMEOUT: 180
// CONNECTION_REFUSED: 45
// VALIDATION_ERROR: 12
// UNKNOWN: 3
4. デプロイとの相関
// デプロイイベントのログ
const deploymentCorrelation = `
fields @timestamp, message, version
| filter service = "deployment-system"
| filter @timestamp >= "2025-01-15T09:00:00Z"
| sort @timestamp asc
`;
// デプロイ直後にエラーが増えていないか確認
// 09:55 "Deployed payment-service v2.3.1"
// 10:10 エラースパイク開始 → v2.3.1のバグが原因の可能性大
ログベースのアラート設計
// エラー率ベースのアラート
interface LogBasedAlert {
name: string;
query: string;
threshold: number;
window: string;
severity: 'warning' | 'critical';
actions: string[];
}
const alerts: LogBasedAlert[] = [
{
name: 'High Error Rate',
query: 'filter level="ERROR" | stats count(*) as errors by bin(5m)',
threshold: 50, // 5分間で50件以上
window: '5m',
severity: 'critical',
actions: ['slack-oncall', 'pagerduty'],
},
{
name: 'Payment Failures',
query: 'filter service="payment" and level="ERROR" | stats count(*) by bin(1m)',
threshold: 10,
window: '1m',
severity: 'critical',
actions: ['slack-oncall', 'pagerduty'],
},
{
name: 'Unusual Warn Spike',
query: 'filter level="WARN" | stats count(*) as warns by bin(10m)',
threshold: 200,
window: '10m',
severity: 'warning',
actions: ['slack-monitoring'],
},
];
トラブルシューティングのアンチパターン
| アンチパターン | 問題 | 正しいアプローチ |
|---|---|---|
| ログなしデバッグ | 勘に頼った原因推測 | ログデータに基づく分析 |
| grep地獄 | サーバーごとに手動検索 | 集中ログ管理で横断検索 |
| 後出しログ | 障害後にログを追加して再デプロイ | 事前に十分なログを仕込む |
| ログの海 | 大量のログで重要情報が埋没 | ログレベルとフィルタリングの適切な設定 |
| コンテキスト不足 | "Error occurred" だけのログ | orderId、userId等のコンテキスト付与 |
まとめ
| ポイント | 内容 |
|---|---|
| 調査フロー | 影響範囲 → タイムライン → パターン → 相関 → 根本原因 |
| traceId追跡 | 1リクエストの全ログを時系列で確認 |
| 集計分析 | エラースパイク、エラーコード別集計 |
| 相関分析 | デプロイ、外部サービスとの関連 |
チェックリスト
- 障害調査の基本フロー(5ステップ)を説明できる
- traceIdを使ったリクエスト追跡ができる
- エラーの時系列集計でスパイクを検出できる
- ログベースのアラート設計ができる
次のステップへ
次は演習「ログ基盤を設計しよう」です。これまで学んだ知識を使って、実際にログ基盤を設計してみましょう。
推定読了時間: 30分