Amazon CloudWatch Logsに関して、勉強したことを残します。
AWSでは多くのログをCloudWatch Logsでまとめて見ることができますが、何がどんなログなのかを全く理解していませんでした。
今回はCloudWatch Logsの仕組みと、代表的なログの形式、CloudWatch Logsに集めて何ができるのかを整理します。
CloudWatch Logsの基本
CloudWatch Logsはログを集めて、保存・検索・監視するためのサービスです。まず用語としてよく出るのが以下の3つ。
| 用語 | 内容 |
|---|---|
| ログイベント | 1件のログ |
| ログストリーム | 同じ出どころから出たログイベントの並び |
| ロググループ | ログストリームをまとめる単位 |
用語の説明だけだとイメージしづらいですが、1つのLambda関数を例にすると↓のような階層関係になります。
コンソールでもロググループ → ログストリーム → ログイベントと選んでいけば、最終的にログの生データにたどり着きます。
/aws/lambda/<関数名> ← ロググループ (この関数専用の置き場)
├── YYYY/MM/DD/[$LATEST]<実行環境AのID> ← ログストリーム (実行環境Aが出した分)
│ ├── INIT_START Runtime Version: ... ← ログイベント
│ ├── START RequestId: ...
│ ├── <コードの出力>
│ ├── END RequestId: ...
│ └── REPORT RequestId: ... Duration: ... ms ...
├── YYYY/MM/DD/[$LATEST]<実行環境BのID> ← ログストリーム (実行環境Bが出した分)
└── YYYY/MM/DD/[$LATEST]<実行環境CのID> ← ログストリーム (実行環境Cが出した分)
ログの中身は「時刻」と「文字列」だけ
ログイベントに入るのは、タイムスタンプとテキスト(UTF-8の文字列)の2つだけです。そして、**ログの形式はCloudWatch Logsではなく、ログを出すサービス側が決めます。**よってログの分析を行うには、「サービスごとのログの読み方」を知る必要があります。
Lambdaのログ
ログ形式がサービスごとに違うということで、Lambdaのログがどんなものか確認します。
Lambda関数のログは、何も設定しなければ/aws/lambda/<関数名>というロググループに出力されます。
INIT_START Runtime Version: python:*** Runtime Version ARN: arn:aws:lambda:***
START RequestId: *** Version: $LATEST
<コードの出力 (printやloggingの内容)>
END RequestId: ***
REPORT RequestId: *** Duration: *** ms Billed Duration: *** ms Memory Size: *** MB Max Memory Used: *** MB Init Duration: *** ms
ログの中身は大きく分けて以下の2種類。
-
システムログ: Lambdaが出すログ。 (
INIT_START/START/END/REPORTの行) -
アプリケーションログ: 関数のコードが出すログ。 (
printやloggingの出力で、STARTとENDの間に入る)
コードが何も出力しなくても、1回の実行につき最低3行(START, END, REPORT)は出力されます。(初回実行だけ、INIT関係のログもあり)
RequestIdが1回の実行ごとのIDなので、これを目印にすればどこからどこまでが同じ実行ログかが分かります。
前述の通りログストリームは実行環境ごとなので、同じ実行環境が使い回されている間は、何回実行しても同じストリームに追記されていきます。
Lambdaのログ形式はテキストの他にJSONも選べます。
出力先のロググループも指定できるので、複数の関数のログを1つのロググループにまとめることも可能です。(その場合、ログストリーム名に関数名が入るようです)
CloudWatch Logsに出せる主なログ
Lambda以外にも、多くのサービスがCloudWatch Logsにログを送れます。
自分が使いそうなものを中心に、公式ドキュメントを確認してまとめたのが以下の表です。(サービスによってはCloudWatch Logsの他に、Amazon S3やAmazon Data Firehoseも送信先に選べます)
| ログ | ログから分かること | CloudWatch Logs | S3 / Firehose |
|---|---|---|---|
| AWS Lambda ログ | 実行時間・消費メモリ・コードの出力 | ○ | ○ |
| Amazon API Gateway アクセスログ | 誰がどうAPIを呼んだか | ○ | |
| Amazon CloudFront アクセスログ | リクエストの時刻・応答関係 | ○ | ○ |
| Amazon Cognito ログ | メール/SMSの送信失敗など | ○ | |
| AWS Step Functions ワークフローログ | ワークフローの実行履歴 | ○ | |
| VPC フローログ | 通信の送信元・宛先・許可/拒否 | ○ | ○ |
| Amazon S3 サーバーアクセスログ | バケットへのリクエストの記録 | ○ | ○ |
| AWS CloudTrail ログ | 誰がどのAPIを実行したか | ○ | |
| AWS CodeBuild ログ | ビルドの各フェーズとコマンド出力 | ○ | |
| Amazon SNS ログ | メッセージ配信の成否と応答 | ○ | |
| Amazon Bedrock AgentCore Runtime | ランタイムの標準出力など | ○ | ○ |
| Amazon EventBridge (パイプ/イベントバス) | イベントの受信・配信の経過 | ○ | ○ |
| AWS WAF ログ | リクエストと一致したルール | ○ | ○ |
各サービスのログ形式
上記表にある、Lambda以外のサービスのログについて、全てではありませんが中身を確認したものを残します。
多くのサービスがデフォルトで無効となっており、必要に応じて形式やログに出力するフィールドを設定する必要があるようです。
API Gateway
上述したアクセスログの他に実行ログもあり、別々に有効化できます。
| 実行ログ | アクセスログ | |
|---|---|---|
| 内容 | リクエストを処理する過程 (エラーや実行トレース等) | 誰がどうAPIにアクセスしたか |
| ロググループ | API-Gateway-Execution-Logs_{rest-api-id}/{stage_name} |
自分で作成して指定 |
| 形式 | API Gatewayが決める。(1イベント1KBで切り捨て) | 自分でCLF, JSON等の形式を決める。 ($context.requestIdまたは$context.extendedRequestIdは必須) |
| 有効化 |
loggingLevelをERROR/INFOにして有効化 |
ステージに出力先と形式を設定して有効化 |
CloudFront アクセスログ
CloudFrontが受けたリクエストの詳細 (受信時刻、処理時間、サーバーの応答等)が分かります。用途としては応答時間やトラブルシューティングの分析。
デフォルトは無効で、ディストリビューションの設定で送信先や形式を指定して有効化します。
{
"date": "2024-11-14",
"time": "21:34:06",
"x-edge-location": "SOF50-P2",
"asn": "16509",
"timestamp(ms)": "1731620046814",
"origin-fbl": "0.251",
"origin-lbl": "0.251",
"x-host-header": "d111111abcdef8.cloudfront.net",
"cs(Cookie)": "examplecookie=value"
}
上記の例以外にもフィールドには様々なものを設定できるようです。
Cognito ログ
配信に対してと、ユーザーアクティビティに対しての2種類のログがあり。
デフォルトでは無効で、ロググループを指定する必要があります。(形式はjson)
通知の配信エラー (userNotification) |
ユーザーアクティビティ (userAuthEvents) |
|
|---|---|---|
| 何が分かるか | ユーザープールがSES / SNS経由で送るメール・SMSの配信エラー | サインイン・サインアウトなど認証操作の詳細とセキュリティ評価 |
| ログレベル | ERROR | INFO |
| 送信先 | CloudWatch Logs | CloudWatch Logs/Firehose/S3のいずれか |
| 条件 | Plusプラン不要 | Plusプラン + 脅威保護が有効 |
| 設定方法 | APIかSDKのみ (SetLogDeliveryConfiguration) |
APIまたはコンソール |
VPCフローログ
こちらもデフォルトでは無効。フローログを作成して、ロググループを指定すれば有効になります。(ログストリーム名は<ENIのID>-all)
2 123456789012 eni-0123456789abcdef0 203.0.113.12 10.0.0.10 49152 443 6 10 840 1700000000 1700000060 ACCEPT OK
2 123456789012 eni-0123456789abcdef0 198.51.100.7 10.0.0.10 51000 23 6 1 44 1700000000 1700000060 REJECT OK
2 123456789012 eni-0123456789abcdef0 - - - - - - - 1700000000 1700000060 - NODATA
出力されるログはスペース区切りのテキスト。デフォルト形式 (version 2)では以下の並びのようです。
version account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status
id以降のフィールドの内容は以下の通り。
| フィールド | 内容 |
|---|---|
| srcaddr / dstaddr | 送信元 / 宛先IP |
| srcport / dstport | 送信元 / 宛先ポート |
| protocol | プロトコル番号 |
| packets / bytes | 集約期間中のパケット数 / バイト数 |
| start / end | 集約期間内の最初 / 最後のパケットの時刻 (Unix秒) |
| action | ACCEPT / REJECT |
| log-status | OK / NODATA など |
S3 サーバーアクセスログ
バケットに対するリクエストが記録されます。 (バケット名、時刻、リクエスト元のIP、リクエストした主体、操作、オブジェクトのキーなど)
セキュリティやアクセスの監査、S3の請求の理解に使用。
| CloudWatch Logs | S3の汎用バケット | |
|---|---|---|
| 形式 | 構造化されたJSON | スペース区切りのテキスト |
| 検索 | Logs Insights | Athena |
| 料金 | ログの取り込み料金 | 保管料金のみ |
| 制約 | クロスアカウント / クロスリージョンに対応 | 同じアカウント・リージョンのバケットのみ |
79a59df9... amzn-s3-demo-bucket1 [06/Feb/2019:00:01:57 +0000] 192.0.2.3 79a59df9... DD6CC733AEXAMPLE REST.PUT.OBJECT s3-dg.pdf "PUT /amzn-s3-demo-bucket1/s3-dg.pdf HTTP/1.1" 200 - - 4406583 41754 28 "-" "S3Console/0.4" - ...
CodeBuild ログ
記事作成時点では、Buildプロジェクト作成時にログ有効化のオプションがONになっているので、チェックを外さない限りはログが出力されます。(ログストリーム名はビルドID)
[Container] YYYY/MM/DD hh:mm:ss.ssssss Running on CodeBuild On-demand
[Container] YYYY/MM/DD hh:mm:ss.ssssss Phase is DOWNLOAD_SOURCE
[Container] YYYY/MM/DD hh:mm:ss.ssssss Running command <buildspecに書いたコマンド>
<コマンドの出力>
[Container] で始まる行がCodeBuildのログ、それ以外がbuildspecのコマンドの出力になります。
AWS WAF
WAFが検査したリクエストの詳細と、そのリクエストがどう処理されたかが分かります。
形式はjsonで、主なフィールドは以下の通り。
| フィールド | 内容 |
|---|---|
action |
WAFがリクエストに適用した最終的なアクション (allow / block / CAPTCHA / challenge) |
httpRequest |
リクエストのメタデータ |
clientIp / country
|
リクエスト元のIPアドレス / 国 |
httpMethod / headers / args
|
HTTPメソッド / ヘッダー / クエリ文字列 |
httpSourceName |
リクエストの経路 (CF = CloudFront、APIGW = API Gateway、ALB、COGNITOIDP など) |
nonTerminatingMatchingRules |
マッチしたが処理を終了しなかったルール (countなど) |
rateBasedRuleList |
評価されたレートベースルール |
labels |
ルールがリクエストに付けたラベル |
デフォルトでは無効で、有効化にはロググループの指定が必要。Web ACLと同じリージョンであることや、ロググループ名を指定の形にする必要があるようです。
CloudWatch Logsでできること
ログをCloudWatch Logsに集めると、以下のようなことができます。Logs Insightsとメトリクスフィルターの2つはよく目にするイメージです。
| 機能 | できること |
|---|---|
| CloudWatch Logs Insights | クエリ言語でログを検索・集計 |
| メトリクスフィルター | ログのパターンを数えたり値を抜き出したりしてメトリクス化 (グラフやアラームに使える) |
| サブスクリプションフィルター | ログをリアルタイムで他のサービス(Lambda、Firehoseなど)に流す |
| Live Tail | 取り込まれるログをほぼリアルタイムで表示 |
| データ保護 | ログに含まれる機密データの検出とマスク |
| 保持期間の設定 | ログを残す期間をロググループごとに指定 |
| S3へのエクスポート | 長期保管や他のツールでの分析用に書き出し |
Logs Insightsでの検索・集計
前述の通り、ログイベントの中身はただの文字列ですが、Logs Insightsは一部のログについて、メッセージの中身を解釈してフィールドとして扱えるようにしてくれます。
| ログの種類 | 自動で検出されるフィールド |
|---|---|
| Lambda |
@requestId @duration @billedDuration @type @maxMemoryUsed @memorySize
|
| VPC Flow Logs |
srcAddr dstAddr srcPort dstPort protocol packets bytes action logStatus など |
| JSON形式のログ (CloudTrailなど) | JSONのキーがそのままフィールドになる |
| その他 |
@timestamp @message @logStream などの共通フィールドのみ |
LambdaやVPCフローログはテキスト形式のままでも、フィールド名を使って絞り込みや集計ができます。
例えばLambdaのロググループであれば、以下のクエリで実行回数や実行時間、コールドスタートの回数をまとめて確認できます。
SOURCE logGroups(namePrefix: ["ロググループ名"], class: "STANDARD") START=<集計開始点> END=<集計終了点> |
filter @type = 'REPORT'
| stats count(*) as invocations, avg(@duration) as avg_ms, max(@duration) as max_ms, max(@maxMemoryUsed/1000/1000) as max_mem_mb, count(@initDuration) as cold_starts
REPORTの行に書かれていたDurationやMax Memory Usedが、数値のフィールドとして取り出せるので、平均や最大値をそのまま計算できます。
エラーの発生状況を見たい場合は、メッセージに対する検索が使えます。
filter @message like /ERROR/ | stats count(*) as errors by bin(1d)
AIにクエリの記述を依頼することもできるので、慣れない間は頼った方が良さそうです。

保持期間とログの置き場所
最後に、ログを溜めていく上で気を付けたい点を2つ。
保持期間はデフォルトで無期限
ロググループの保持期間は、何も設定しなければ無期限。(1日〜10年の範囲で設定可能)
取り込みの料金は1回きりですが、保管の料金はログを消すまでかかり続けるので、必要な期間を決めて設定しておくのが良さそうです。
あまり見ないログには別の置き場所もある
- ロググループのクラスを
Infrequent Accessにすると、取り込みの料金が安くなりますが、使える機能が絞られる点に注意。(Logs Insightsでの検索は可能。メトリクスフィルターやLive Tailが使えない)
⇒ 普段は見ないけどトラブル時には検索したいようなログ向き?(クラスはロググループを作成すると変更できない点に注意) - VPCフローログなど一部のログは、CloudWatch Logsではなく、S3などを送信先に選ぶこともできます。コストは低くなりますが、CloudWatch Logsの機能では扱えなくなり、分析にはAmazon Athenaなど別の仕組みが必要になります。
まとめ
CloudWatch Logsの仕組みと、代表的なサービスのログ、CloudWatch Logsでできることを整理しました。
- ログはロググループ(設定単位) → ログストリーム(実行環境) → ログイベント(生のログデータ)の階層構造を持つ
- ログイベントの中身は時刻とテキストだけ、ログ形式は出力するサービスごとで変わる
- Lambdaは
REPORTの行、VPC Flow Logsはactionを見れば、実行状況や通信の許可/拒否が分かる - Lambda以外の多くのログは、サービス側で有効化しないとCloudWatch Logsに出力されない
- Logs Insightsを使えば、LambdaやJSON形式のログをフィールド名で検索・集計できる
- 保持期間はデフォルトで無期限なので、ロググループごとに設定しておく