FluentdのログフォーマットでS3に保存されたApacheのアクセスログをAmazon Athenaで集計する
突然の Amazon Web Services Advent Calendar 2016 の 15日の記事です
基盤ユニットの小山 ( @k1LoW )です。
AWS re:Invent 2016すごかったですね。
数多くのサービスが使える形でリリースされてきました。
ただ、個人的にはその後の aws-sdk-ruby が v3に上がる というエントリーを見て、awspecをどうしようか戦々恐々としています。
awspecを aws-sdk-ruby v3.0.0.rc2 で動かしてみようと思ったら、依存している https://t.co/TIuG9dGHfH のテストが v3.0.0.rc2 失敗したので、1回休み
— k1LoW (@k1LoW) 2016年12月14日
突然のアクセスログ集計
あるAWS上に構築しているシステムプロジェクトで、突然「月単位でのアクセス集計1年間分」という要望がどこからともなく降ってきました。
そのプロジェクトでは、アクセスログを含む様々なメトリクスをFluentd ( td-agent ) で収集して、S3のバケットに保存しています。
ただ、保存の目的がいざという時のためで、稼働している分析基盤はありませんでした。
そこで、まずはローカルのMacBook ProでDigdag+MySQLによる集計を試みました。
が、
1日立ってもログ取得が終わらず。。。
(そういえば今まではdstatのような定期的に取得するメトリクス情報のログ集計で、アクセスログのようなさらに大量のデータの取得はしていなかった。。。)
さてどうしようかとなった時に、ふと思い出したのが、そう、Amazon Athenaでした。
そうだ、Amazon Athena を使ってみよう
Amazon Athena、ざっくり紹介するとマネージドなPrestoです(ざっくりすぎる)。
AWS提供で、S3との相性がとてもよさそうなので、もしかしていけるのでは?と思って試してみたらできました。
前提
アクセスログは s3://[bucket-name]/access_logs/[ec2-hostname]/[year]/[month]/[day]/access_log.xxxxx.xxx.xxx.gz
みたいに保存されています。
S3のバケット自体はap-northeast-1 (Tokyoリージョン)にあります(Amazon Athena自体はTokyoリージョンではまだ提供されていませんが、S3バケットの指定はできますよ!)。
実際のアクセスログはFluentdの一般的な(?)ログフォーマットで、
2016-12-19T04:35:27Z ip-10-xx-xxx-xxx {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/path/to/?q=query","code":"200","size":"1234","referer":"-","agent":"Some User-Agent"}
というような、タイムスタンプとhostnameとJSONの複合形式です。
テーブルの作成
本来ならば「Add Table」 リンクを押してデータベースの作成からするほうがいいのですが、今回は
Query Editorで、おもむろに以下のクエリを実行して集計用テーブルを作成しました。
CREATE EXTERNAL TABLE IF NOT EXISTS default.access_logs ( date date, hour int, min int, second int, z string, host string , ip string, user string, method string, path string, code int, size int, referer string, agent string ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' WITH SERDEPROPERTIES ( 'serialization.format' = '1', 'input.regex' = '^(.+)T(\\d+):(\\d+):(\\d+)(.+)\\t([^\\s]+)\\t\\{"host":"([^"]+)","user":"([^"]+)","method":"([^"]+)","path":"([^"]+)","code":"([^"]+)","size":"([^"]+)","referer":"([^"]+)","agent":"([^"]+)"\\}' ) LOCATION 's3://[bucket-name]/access_logs/'
ポイントは 'input.regex' = '^(.+)T(\\d+):(\\d+):(\\d+)(.+)\\t([^\\s]+)\\t\\{"host":"([^"]+)","user":"([^"]+)","method":"([^"]+)","path":"([^"]+)","code":"([^"]+)","size":"([^"]+)","referer":"([^"]+)","agent":"([^"]+)"\\}'
でFluentdのログフォーマットに合わせた正規表現を設定しているところです。
集計SQLの実行
ここからは簡単です。
1クエリごとに小さくない金額がかかりますが、突然の依頼なので悠長なことは言っていられません。
そこは札束で殴るように
SELECT MONTH(date) AS month, count(*), SUM(size) AS total_size FROM rkb_web_public_access_logs WHERE host IS NOT NULL AND date >= CAST('2016-01-01' AS DATE) GROUP BY MONTH(date) ORDER BY total_size DESC
などと、フルスキャンでがっつり集計などしました。
まとめ
Amazon Athenaは思った以上に気軽に使えました。
ただ、クエリごとに課金されるので、ご利用は計画的に。
突然のアクセスログ集計などには良いと思います。
よい突然ライフを。
おまけ
Amazon Athenaで課題解決できた話をきばんブログで書いていたのに、レビュー中に、本家に同じようなのを出されて二番煎じみたいになってしまっている(レビュー待ち)
— k1LoW (@k1LoW) 2016年12月14日