aws-cloudwatch-investigation について
本番インシデントに対応するエンジニア向けに、AWS CloudWatch の調査パターンをまとめたスキルです。ログやメトリクスのクエリ、アラームとデプロイの関連付け、影響範囲の特定、タイムラインの再構成を扱います。
主な機能
- 01Logs Insights によるエラー・遅延クエリ
- 02Lambda のコールドスタート・OOM・タイムアウト検出
- 03アラームとデプロイイベントの関連付け
- 04アカウントや依存関係をまたぐ影響範囲の特定
- 05インシデントタイムラインの再構成
活用シーン
- 01本番環境のエラーや遅延の急増を調査
- 02アラームと直近のデプロイの関連を評価
- 03複数サービスに及ぶ障害の共有依存先を特定
- 04ログ・メトリクス・変更を時系列に整理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ github/ awesome-copilot --skill aws-cloudwatch-investigationインストール後、Claude Code で/aws-cloudwatch-investigationを入力して読み込まれたか確認します。
詳細
AWS CloudWatch 調査スキル
CloudWatch Logs、Metrics、Alarms を使用して本番環境のインシデントを調査するための再利用可能なパターンです。これらのパターンは、インシデントのトリアージ中に組み合わせて使用できるように設計されています。
パターン 1:Logs Insights クエリテンプレート
エラー急増の検出
時間範囲内のエラーを種類ごとにグループ化し、上位のものを特定します。
fields @timestamp, @message, @logStream
| filter @message like /(?i)(error|exception|fatal|critical)/
| stats count(*) as errorCount by bin(5m), @logStream
| sort errorCount desc
| limit 20
オペレーション別の P99 レイテンシの内訳
どのオペレーションがレイテンシの急増を引き起こしているかを特定します。
fields @timestamp, @duration, operation
| filter ispresent(@duration)
| stats avg(@duration) as avgMs,
pct(@duration, 50) as p50Ms,
pct(@duration, 95) as p95Ms,
pct(@duration, 99) as p99Ms,
count(*) as invocations
by operation
| sort p99Ms desc
| limit 15
Lambda のコールドスタート検出
インシデント中のコールドスタートの影響を定量化します。
fields @timestamp, @duration, @initDuration, @memorySize, @maxMemoryUsed
| filter ispresent(@initDuration)
| stats count(*) as coldStarts,
avg(@initDuration) as avgInitMs,
max(@initDuration) as maxInitMs,
avg(@duration) as avgDurationMs
by bin(5m)
| sort @timestamp desc
メモリ不足(OOM)の検出
メモリ不足により終了した Lambda 関数またはコンテナを特定します。
fields @timestamp, @message, @logStream, @memorySize, @maxMemoryUsed
| filter @message like /Runtime exited|out of memory|OOMKilled|Cannot allocate memory|MemoryError/
| stats count(*) as oomEvents by @logStream, bin(10m)
| sort oomEvents desc
| limit 10
OOM 発生前のメモリ使用率の推移を確認するには:
fields @timestamp, @maxMemoryUsed, @memorySize
| filter ispresent(@maxMemoryUsed)
| stats max(@maxMemoryUsed / @memorySize * 100) as peakMemPct,
avg(@maxMemoryUsed / @memorySize * 100) as avgMemPct
by bin(5m)
| sort @timestamp desc
タイムアウトの検出
設定されたタイムアウトに達した呼び出しを特定します。
fields @timestamp, @duration, @logStream, @requestId
| filter @message like /Task timed out/ or @duration > 28000
| stats count(*) as timeouts by @logStream, bin(5m)
| sort timeouts desc
パターン 2:アラーム履歴とデプロイイベントの相関付け
手順
- アラームの状態遷移時刻を取得する — アラームが ALARM 状態に入った正確なタイムスタンプを記録します。
- CloudTrail をクエリする — [alarm_time - 30min, alarm_time] の時間範囲で、デプロイ関連イベントを検索します。
# CloudTrail Lake query for deployment events
SELECT eventTime, eventName, userIdentity.arn, requestParameters
FROM <event-data-store-id>
WHERE eventTime > '<alarm_time_minus_30m>'
AND eventTime < '<alarm_time>'
AND eventName IN (
'UpdateFunctionCode', 'UpdateFunctionConfiguration',
'UpdateService', 'CreateDeployment', 'RegisterTaskDefinition',
'CreateChangeSet', 'ExecuteChangeSet',
'StartPipelineExecution', 'PutImage'
)
ORDER BY eventTime DESC
-
相関の判定基準 — 次の条件を満たすデプロイを「相関あり」とします。
- アラームと同じサービス/リソースを対象としている
- アラームの状態遷移前 15 分以内に完了している
- デプロイ実行者の ID が CI/CD ロールと一致する(人間によるホットフィックスの適用ではない)
-
相関の確度を高める:
- 前回のデプロイサイクルで同じアラームが正常だったか確認します
- 同じ時間範囲に、他の環境変更(スケーリングイベント、設定変更)がなかったことを確認します
- 同じ時刻に開始したカナリア/合成モニターの失敗を探します
出力形式
Deploy Correlation:
Event: UpdateFunctionCode
Time: 2024-03-15T14:23:07Z (12 min before alarm)
Actor: arn:aws:sts::123456789012:assumed-role/github-actions-deploy/session
Resource: arn:aws:lambda:us-east-1:123456789012:function:payment-processor
Correlation: STRONG — same resource, CI/CD actor, alarm was OK prior cycle
パターン 3:影響範囲を絞り込む決定木
この決定木を使って、最も広い範囲から最も具体的な範囲へと、インシデントのスコープを体系的に絞り込みます。
START
|
v
[1] ACCOUNT — Which account(s) show the alarm?
| - Check: Are alarms firing in multiple accounts?
| - If yes → suspect shared service (SSO, networking, shared deployment pipeline)
| - If no → proceed to Region
v
[2] REGION — Which region(s) are affected?
| - Check: Same alarm in other regions?
| - If multi-region → suspect global service (IAM, Route53, S3 global)
| - If single-region → proceed to Service
v
[3] SERVICE — Which service namespace shows degradation?
| - Check CloudWatch namespace: AWS/Lambda, AWS/ECS, AWS/ApiGateway, etc.
| - If multiple services → suspect shared dependency (VPC, NAT, DNS, IAM)
| - If single service → proceed to Operation
v
[4] OPERATION — Which API action or function is failing?
| - For Lambda: which function name?
| - For ECS: which service/task definition?
| - For API GW: which stage/resource/method?
| - If all operations → suspect service-level issue (throttling, quota)
| - If specific operation → proceed to Resource
v
[5] RESOURCE — Which specific resource instance?
- Function ARN, Task ID, DB instance identifier
- This is your investigation target
- Proceed to log and trace analysis scoped to this resource
共通依存関係の調査
影響範囲が複数のサービスに及ぶ場合は、次の順に調査します。
- VPC/ネットワーク — NAT Gateway の ErrorPortAllocation、パケットドロップ、DNS 名前解決の失敗
- IAM/STS — AssumeRole の ThrottlingException、トークン発行のレイテンシ
- 下流の依存関係 — 共通データベース、キャッシュ、または外部 API
- デプロイパイプライン — 同じパイプライン実行から複数のサービスに同時にデプロイされていないか
- AWS サービスイベント — 対象リージョンの AWS Health Dashboard と Service Health を確認します
パターン 4:PromQL 形式のメトリクスクエリパターン
これらのパターンでは、CloudWatch のメトリクス演算と GetMetricData を使用して複合シグナルを構築します。ダッシュボードまたはプログラムからの取得に使うメトリクスクエリとして表現します。
エラー率のパーセンテージ
MetricDataQueries:
- Id: errors
MetricStat:
Metric:
Namespace: AWS/Lambda
MetricName: Errors
Dimensions: [{Name: FunctionName, Value: TARGET}]
Period: 60
Stat: Sum
- Id: invocations
MetricStat:
Metric:
Namespace: AWS/Lambda
MetricName: Invocations
Dimensions: [{Name: FunctionName, Value: TARGET}]
Period: 60
Stat: Sum
- Id: error_rate
Expression: "errors / invocations * 100"
Label: "Error Rate %"
レイテンシ異常の検出(ベースラインとの比較)
MetricDataQueries:
- Id: current_p99
MetricStat:
Metric:
Namespace: AWS/Lambda
MetricName: Duration
Dimensions: [{Name: FunctionName, Value: TARGET}]
Period: 300
Stat: p99
- Id: baseline_p99
MetricStat:
Metric:
Namespace: AWS/Lambda
MetricName: Duration
Dimensions: [{Name: FunctionName, Value: TARGET}]
Period: 300
Stat: p99
# Use StartTime/EndTime set to same window last week
- Id: anomaly_ratio
Expression: "current_p99 / baseline_p99"
Label: "Latency vs Baseline (ratio > 2 = anomaly)"
スロットリング圧力スコア
複数のスロットリングシグナルを、単一の圧力メトリクスにまとめます。
MetricDataQueries:
- Id: lambda_throttles
MetricStat:
Metric: {Namespace: AWS/Lambda, MetricName: Throttles}
Period: 60
Stat: Sum
- Id: api_gw_429s
MetricStat:
Metric: {Namespace: AWS/ApiGateway, MetricName: 4XXError, Dimensions: [{Name: ApiName, Value: TARGET}]}
Period: 60
Stat: Sum
- Id: dynamo_throttles
MetricStat:
Metric: {Namespace: AWS/DynamoDB, MetricName: ThrottledRequests, Dimensions: [{Name: TableName, Value: TARGET}]}
Period: 60
Stat: Sum
- Id: throttle_pressure
Expression: "lambda_throttles + api_gw_429s + dynamo_throttles"
Label: "Combined Throttle Pressure"
同時実行数の余裕
MetricDataQueries:
- Id: concurrent
MetricStat:
Metric: {Namespace: AWS/Lambda, MetricName: ConcurrentExecutions}
Period: 60
Stat: Maximum
- Id: headroom
Expression: "1000 - concurrent"
Label: "Remaining Concurrency (account limit 1000)"
パターン 5:インシデントタイムラインの再構築
手順
複数のソースからデータを統合して、正確なタイムラインを再構築します。
- タイムスタンプを収集する:
| ソース | クエリ | 得られる情報 |
|---|---|---|
| CloudWatch Alarms | Alarm history API | 状態遷移時刻 |
| CloudWatch Metrics | 1 分間隔の GetMetricData | 最初の異常発生時点 |
| CloudWatch Logs | earliest(@timestamp) を使った Logs Insights | 最初のエラー発生 |
| CloudTrail | 時刻でフィルタリングした LookupEvents | デプロイ/変更イベント |
| AWS Health | DescribeEvents | AWS 側のインシデント |
- タイムラインを作成する:
fields @timestamp, @message
| filter @message like /ERROR|WARN|timeout|refused|denied/
| stats earliest(@timestamp) as firstSeen, latest(@timestamp) as lastSeen, count(*) as occurrences
by @message
| sort firstSeen asc
| limit 20
- 発生順序を特定する:
Timeline:
T-15m: CloudTrail — UpdateFunctionCode by CI/CD role
T-12m: Logs — first error "Connection refused to payments-api.internal"
T-10m: Metrics — Error count crosses 5/min threshold
T-8m: Alarm — PaymentProcessorErrors enters ALARM
T-5m: Metrics — p99 latency spikes to 28s (timeout)
T-0: Current — error rate at 45%, alarm still firing
- 根本原因となったイベントを特定する — すべての症状に先行した最も早い変更を特定します。最初の症状からさかのぼり、直近の変更(デプロイ、設定変更、スケーリングイベント、外部依存関係の変化)を確認します。
注意事項
- CloudWatch メトリクスのタイムスタンプは期間の終了時刻です。14:05 の1分間のデータポイントは、14:04~14:05 の期間を対象としています。
- CloudTrail イベントの配信には、最大15分の遅延が発生する場合があります。取り込み時刻ではなく、
eventTimeを使用してください。 - ロググループのタイムスタンプは、エージェント/SDK のフラッシュ間隔によって異なります。30~60秒のクロックずれを考慮してください。
- アラーム状態の変化には、評価期間(期間 × 評価期間)に基づく組み込みの遅延があります。実際の異常は、それより前に始まっています。