この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、菊池です。
これまでのエントリで、ELBのログをAmazon Athenaで分析する方法を紹介しました。
- Amazon Athena RegexSerDe を利用して CLB ログ / Apache Web のアクセスログを探索する
- Amazon Athena RegexSerDe を利用して ALB ログを探索する
今回は、CloudFrontのアクセスログをAmazon Athenaで分析してみます。
CloudFront とは
Amazon CloudFrontは、AWSが提供するコンテンツ配信サービス(CDN)です。ユーザからのアクセスを、世界中にあるエッジサーバを経由するよう誘導することで、高速なアクセスを提供します。また、エッジサーバにコンテンツをキャッシュすることで、オリジンサーバの負荷を低減することもできます。
CloudFrontのアクセスログ
CloudFrontのアクセスログは、ディストリビューションごとに指定したS3のバケットに保存されます。
ウェブディストリビューションとRTMPディストリビューションでログファイルの形式は異なりますので、今回はウェブシストリビューションを対象にします。
テーブル定義
ログファイルのフィールドを、ドキュメントを参考に以下の様にテーブルのカラムにマッピングします。
フィールド | 説明 |
---|---|
request_date | イベントが発生した日付。yyyy-mm-dd形式。UTC。 |
request_time | CloudFrontがリクエストへの対応を完了した時刻(UTC)。 |
x_edge_location | リクエストを処理したエッジロケーション。3文字コードと割り当てられた数字で識別される。 |
sc_bytes | CloudFront がリクエストに応答してビューワーに渡したデータの総バイト数 |
client_ip | リクエストを送信したクライアントの IP アドレス。 |
cs_method | リクエスト時のHTTPメソッド。 |
cs_host | CloudFront ディストリビューションのドメイン名。 |
cs_uri_stem | パスおよびオブジェクトを識別する URI 。 |
sc_status | CloudFrontが応答したHTTP ステータスコード。応答前にクライアントが切断した場合は"000"を記録。 |
cs_referer | リクエスト元のドメインの名前。 |
user_agent | リクエスト内の User-Agent ヘッダーの値。 |
uri_query | URI のクエリ文字列の部分 (ある場合)。ない場合には"-"を記録。 |
cookie | リクエスト内の Cookie ヘッダー。ない場合には"-"を記録。 |
x_edge_result_type | エッジロケーションへのCloudFrontのレスポンスの分類。例えば以下のようなものがある。
|
x_edge_request_id | 要求を一意に識別する文字列。 |
x_host_header | ビューワーによってこのリクエストの Host ヘッダーに追加された値。 |
cs_protocol | リクエストのプロトコル。httpまたはhttps |
cs_bytes | リクエストに組み込まれたデータのバイト数 |
time_taken | CloudFrontエッジサーバがリクエストを受け取ってから、レスポンスの最終バイトをエッジサーバーの出力キューに書き込むまでの秒数。 |
x_forwarded_for | ビューワーがリクエストを送るのに HTTPプロキシやロードバランサーを使った場合、client_ipの値は、プロキシあるいはロードバランサーの IP アドレスとなる。その場合のリクエスト元のビューワーの IP アドレス。 |
ssl_protocol | cs_protocolがhttpsの場合のSSLプロトコル。 |
ssl_cipher | cs_protocolがhttpsの場合のSSL 暗号。 |
x_edge_response_result_type | CloudFront がレスポンスをビューワーに返す直前に行った分類。x_edge_result_typeも参照。 |
cs_protocol_version | リクエストで指定した HTTP バージョン。 |
これらを順にカラムとして定義します。Amazon Athena は、ログが複数のファイルの場合でも、同じフォルダに配置することで同じテーブル内のデータとしてクエリーを実行できます。
CREATE EXTERNAL TABLE IF NOT EXISTS cf_log (
request_date STRING,
request_time STRING,
x_edge_location STRING,
sc_bytes INT,
client_ip STRING,
cs_method STRING,
cs_host STRING,
cs_uri_stem STRING,
sc_status STRING,
cs_referer STRING,
user_agent STRING,
uri_query STRING,
cookie STRING,
x_edge_result_type STRING,
x_edge_request_id STRING,
x_host_header STRING,
cs_protocol STRING,
cs_bytes INT,
time_taken DECIMAL(8,3),
x_forwarded_for STRING,
ssl_protocol STRING,
ssl_cipher STRING,
x_edge_response_result_type STRING,
cs_protocol_version STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
'serialization.format' = '\t',
'input.regex' = '\t'
)
LOCATION 's3://LOG_BUCKET_NAME/cf/'
TBLPROPERTIES ('has_encrypted_data'='false');
上記のDDLをテンプレートとして利用する場合、LOCATION
に指定するクエリ対象のロフファイルを保存している S3バケット/フォルダ名を変更するだけで、再利用できます。
全てのレコードの全てのカラムデータが参照できることが確認できます。
SELECT * FROM sampledb."cf_log" limit 10;
CloudFront アクセスログの集計
実際にCloudFrontのアクセスログを集計する例を、いくつか紹介します。
エッジロケーションごとのアクセス数を集計
どの地域からのアクセス数が多いか、調べてみるのに使えるかと思います。
SELECT x_edge_location, count(*) AS num
FROM cf_log
WHERE request_date = '2017-08-15'
GROUP BY 1
ORDER BY 1;
クライアントIPごとにアクセス数を集計
クライアントのIPアドレスごとのアクセス数を集計します。BotやF5アタックなど、不適切なアクセスを仕掛けてくるIPを特定し、AWS WAFで遮断するなどの対応を想定しています。
SELECT client_ip, x_edge_location, count(*) AS num
FROM cf_log
WHERE request_date = '2017-08-15'
GROUP BY 1,2
ORDER BY 1;
パスごとにキャッシュ有無によるレスポンス時間を集計
アクセス先のパスごとに、平均のレスポンス時間を集計しています。キャッシュの状態により、ユーザへどの程度のレスポンス時間でサービスできているか確認できます。
SELECT cs_uri_stem, x_edge_result_type, avg(time_taken) AS num
FROM cf_log
WHERE request_date = '2017-08-15'
GROUP BY 1,2
ORDER BY 1;
最後に
以上です。
ELB(CLB/ALB)に続き、CloudFrontのアクセスログをAthenaで集計する手順を紹介しました。AWSでは、S3にログを出力するサービスが多いですが、Athenaを使うことでカジュアルに分析することができます。