API GatewayのアクセスログをLogs Insightsで分析する
はじめに
API Gatewayの利用状況を把握するために、アクセスログを分析したいというニーズは非常に多いです。例えば、「時間帯別のリクエスト数を知りたい」「特定のエラーが多発しているエンドポイントを特定したい」といったケースです。
AWSでは、CloudWatch Logs Insightsを使うことで、ログデータを柔軟にクエリし、分析・可視化できます。そして、ログをJSON形式で出力しておくことで、この分析が格段に簡単です。
課題:デフォルトログ形式の不便さ
API Gatewayのデフォルトのアクセスログ形式は、そのままでは分析しにくいことがあります。特定のIPアドレスからのリクエスト数や、特定のエンドポイントへのアクセス数を集計したい場合、テキストベースのログではクエリが複雑になりがちです。
ログをJSON形式で出力することで、各フィールド(ip, status, resourcePathなど)がキーと値のペアとして構造化されるため、CloudWatch Logs Insightsでの分析が非常に容易になります。
SAMでのJSONアクセスログ設定
AWS SAMのtemplate.ymlでAPI Gateway (AWS::Serverless::Api) のアクセスログを設定するには、AccessLogSettingプロパティを使用します。
「Format must be a single line」エラーの回避
ここで最も重要なポイントは、Formatプロパティの指定方法です。YAMLファイル内で複数行にわたるJSON文字列をそのまま記述しようとすると、デプロイ時に「Format property must be a single line」というエラーが発生します。
これを回避するには、JSONオブジェクト全体をエスケープなどせず、1行の文字列として記述する必要があります。
template.yml の設定例
以下に、template.ymlの記述例を示します。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: API Gateway with JSON access logging
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
AccessLogSetting:
DestinationArn: !GetAtt MyApiLogGroup.Arn
# JSONオブジェクトを1行の文字列として記述する
Format: '{"requestId":"$context.requestId","ip":"$context.identity.sourceIp","caller":"$context.identity.caller","user":"$context.identity.user","requestTime":"$context.requestTime","httpMethod":"$context.httpMethod","resourcePath":"$context.resourcePath","status":"$context.status","protocol":"$context.protocol","responseLength":"$context.responseLength"}'
MyApiLogGroup:
Type: AWS::Logs::LogGroup
Properties:
# ロググループ名を明示的に指定
LogGroupName: /aws/api-gateway/my-api-json-log
RetentionInDays: 14
この設定により、API Gatewayへのすべてのアクセスが、指定したFormatに従ってJSON形式でCloudWatch Logsの/aws/api-gateway/my-api-json-logロググループに出力されます。
CloudWatch Logs Insightsでのクエリ実行
アクセスログがJSON形式で出力されるようになると、Logs Insightsでのクエリが非常にシンプルになります。ログの各フィールドは、クエリ内で直接参照できます。
1時間ごとのリクエスト数を集計する
fields @timestamp, status
| stats count(*) as requests by bin(1h)
| sort @timestamp asc
bin(1h)で1時間単位のバケットを作成し、その期間内のリクエスト数を集計しています。
このように出力します。

ステータスコード別のリクエスト数を集計する
stats count(*) as requestCount by status
| sort requestCount desc
アクセス元IPアドレスのトップ10を調べる
stats count(*) as requestCount by ip
| sort requestCount desc
| limit 10
CloudWatchダッシュボードでの可視化
Logs Insightsで実行したクエリの結果(グラフやテーブル)は、簡単にCloudWatchダッシュボードに追加できます。
クエリ実行後、**「ダッシュボードに追加」**ボタンをクリックし、既存または新規のダッシュボードにウィジェットとして保存します。これにより、APIの利用状況をリアルタイムで監視するダッシュボードを簡単に作成できます。

