title: ALB アクセスログ(S3 出力と Athena 集計) lang: ja —
Application Load Balancer の行単位のアクセスログは Amazon S3 に出力する。CloudWatch Logs への直接配信はサポートされない(メトリクスは別途 CloudWatch に標準出力)。ここではマネジメントコンソール(GUI)での手順をまとめる。
公式: Application Load Balancer のアクセスログを有効にする
s3://バケット名/ またはプレフィックス付き s3://バケット名/任意プレフィックス/)。実際は、その下に、/AWSLogs/[アカウントID]/elasticloadbalancing/[リージョン]/yyyy/mm/dd となるのでバケット名だけでよい。プレフィックスに AWSLogs という文字列を含めない(ALB の制約)。
ログは 数分遅れて S3 に到着することがあり、リアルタイム用途ではない。アプリのレイテンシへの影響は通常は問題にならない設計となっている。
バケットを用意し、ALB のログ配信サービスが書き込めるようにする必要がある。
公式ページの バケットポリシー の節のサンプルをコピーし、次を自環境用に差し替えて S3 のバケット アクセス許可 → バケットポリシー に貼る。
ap-northeast-1)Principal は logdelivery.elasticloadbalancing.amazonaws.com(公式の最新手順に従う)。
保存後、しばらく待ってバケット内にログオブジェクトが増えるか確認する。公式手順にある ELBAccessLogTestFile の有無で権限検証できる。
S3 上の gzip ログを Athena からクエリする。テーブルは Glue データカタログ上の外部テーブル定義であり、データ本体は常に S3 にある。
CREATE DATABASE でデータベースを 1 つ作成し、選択する。CREATE EXTERNAL TABLE は、次の公式の DDL をそのままコピーし、LOCATION だけ自環境の S3 に合わせて変更するのが安全である。
このページの CREATE TABLE 例には PARTITIONED BY がなく、パーティション用の列(year / month / day など)は定義されない。 日付で絞るときは、同じ DDL に含まれる行の time 列を使う(下記「日付で絞る」の time 列 の例)。
LOCATION の例(アカウント ID・プレフィックス・リージョンは置き換え):
s3://バケット名/プレフィックス/AWSLogs/アカウントID/elasticloadbalancing/リージョン/
DROP TABLE した・別リージョンで開いている・ログ形式や S3 パスを変えた、などのときだけ再作成や定義変更が必要。year / month / day といったパーティション列付きのテーブルにしたい場合は、パーティション投影の設定 の DDL を使う(スキャン費用・速度の改善。基本の作成ページとは別手順)。公式 DDL では URL 部分は request_url 列として取れる想定。特定パス配下だけ数えたい場合のイメージ:
SELECT count(*) AS cnt
FROM alb_access_logs
WHERE request_url LIKE '%/parent/sub%';
内訳:
SELECT request_url, count(*) AS n
FROM alb_access_logs
WHERE request_url LIKE '%/parent/sub%'
GROUP BY request_url
ORDER BY n DESC
LIMIT 50;
time 列で絞る(基本の公式 DDL の場合こちら) … 公式 DDL に含まれる time(リクエスト時刻の文字列)を使う。形式はログ仕様どおりだが、ISO 8601 風なら日付部分の比較で足りることが多い。
-- 例: 2026-05-11 の1日分(time の先頭が yyyy-mm-dd 形式である前提)
SELECT count(*) AS cnt
FROM alb_access_logs
WHERE request_url LIKE '%/parent/sub%'
AND substr(time, 1, 10) = '2026-05-11';
-- 例: 期間(多日)
SELECT count(*) AS cnt
FROM alb_access_logs
WHERE request_url LIKE '%/parent/sub%'
AND substr(time, 1, 10) >= '2026-05-01'
AND substr(time, 1, 10) <= '2026-05-11';
time のパースで型を揃えたい場合は date_parse や from_iso8601_timestamp も使えるが、小数秒やタイムゾーン表記が環境と完全一致するかは、まず SELECT time FROM alb_access_logs LIMIT 5 で実データを確認するとよい。
列名・パーティション列が上と違う場合は、作ったテーブル定義に合わせて WHERE を付け替える。
参考: ALB アクセスログのクエリ例