CloudFrontログをCloudWatch Logsに流してターミナルで確認してみる
どうも!大阪オフィスの西村祐二です。
突然ですが、CloudFrontのログをどうやって確認していますか?
CloudFrontのログはS3にgzip形式で出力されるので、 ファイルをローカルに落としてきて、ツールに入れて確認や、 EMRやAthenaを使って確認などいろいろ方法がありますが、 手間がかかったり、すこし大げさな感じがしています。
個人的にはターミナルでパイプでつないでgrep
やawk
とかで確認できたらいいなと思っていました。
そんな中、社内のAWSのプロ達にきいたところ良さそうな方法を教えてもらったのでブログにしてみたいと思います。
簡単に要点をまとめると
Serverless Framework
でS3上のgzipを読み取りCloudWatch Logsに出力するLambda関数を作る- S3(CloudFrontログ出力先)にログファイルがおかれたら、Lambdaを実行されるように設定しておく
Serverless Framework
のログ確認機能を使って、CloudFrontのログが出力されたLambdaの実行ログをターミナルで確認する
ポイントはServerless Framework
のログ確認機能です。
作成したLambda関数のログを簡単に確認できます。
これは一度設定しておくだけ、ターミナルでCloudFrontのログが確認できるようになります。
また、パイプでつないでgrep
やawk
なども使えます。
※ログ量が増えてくると、CloudWatch Logsの料金が膨らんできてしまうので注意
さっそくやっていきましょう!
環境
- node.js : v9.6.1
- Serverless Framework : 1.26.0
Serverless Frameworkをインストール
$ npm install -g serverless
Serverless FrameworkでLambda関数を作成
▼ まず、プロジェクトを作成します。言語は「python3.6」です。
$ sls create --template aws-python3 Serverless: Generating boilerplate... _______ __ | _ .-----.----.--.--.-----.----| .-----.-----.-----. | |___| -__| _| | | -__| _| | -__|__ --|__ --| |____ |_____|__| \___/|_____|__| |__|_____|_____|_____| | | | The Serverless Application Framework | | serverless.com, v1.26.0 -------' Serverless: Successfully generated boilerplate for template: "aws-python3" Serverless: NOTE: Please update the "service" property in serverless.yml with your service name $ ls handler.py serverless.yml
▼ テンプレートファイルを編集していきます。
$ vi serverless.yml
トリガーのS3バケットを指定している
test-cf-accesslog-watch-nishimura
は自分の環境へ置き換えてください。
すでに作成済のバケットだとエラーになるので、ご注意ください。
ここで指定したバケットをCloudFrontログの出力先とする想定です。
service: access-log-watch # NOTE: update this with your service name frameworkVersion: ">=1.26.0 <2.0.0" provider: name: aws runtime: python3.6 region: ap-northeast-1 iamRoleStatements: - Effect: "Allow" Action: - "s3:GetObject" Resource: - "arn:aws:s3:::*" package: exclude: - "**" include: - logwatch.py functions: func: handler: logwatch.lambda_handler events: - s3: bucket: test-cf-accesslog-watch-nishimura event: s3:ObjectCreated:*
▼ Lambda関数のプログラムを作成します。
$ vi logwatch.py
行っている処理としては、S3に保存されたオブジェクト(gzipファイル)を取得して、 printでログ出力しているだけです。
import boto3 import gzip import urllib.parse S3 = boto3.resource('s3') S3CLIENT = boto3.client('s3') def getobject(bucket, key): """ Get S3 object """ S3CLIENT.download_file(bucket, key, '/tmp/access-log.gz') with gzip.open("/tmp/access-log.gz", "rt", "utf_8") as fi: for line in fi: print(line) def lambda_handler(event, context): """ main """ bucket = event['Records'][0]['s3']['bucket']['name'] key = urllib.parse.unquote_plus( event['Records'][0]['s3']['object']['key'], encoding='utf-8') try: getobject(bucket, key) except Exception as e: print(e)
▼ デプロイ
$ sls deploy -v
Lambda関数が作成されていること、権限周りが付与されていることを確認します。
CloudFrontのログ出力先を変更
CloudFrontのマネージメントコンソールから対象のDistributionを選択し、「Edit」ボタンをクリックします。 下部のLoggingあたりの設定を行います。「Bucket for Logs」にはLambdaのトリガーとなるバケットを指定します。
動作確認
▼ S3にCloudFrontのログ(gzipファイル)がPUTされると、Lambdaが実行され、CloudWatch Logsにログ内容が出力されます。
ターミナルでログ確認
Serverless Framework
でLambdaのログを確認することができるので、この機能を利用します。
- Lambdaのログ確認コマンド
このコマンドは、1MBに収まるログイベント数(最大10,000ログイベント)を返します。
funcのところにはテンプレートファイルで設定したファンクション名を指定してください。
$ sls logs -f func
下記画像のようにログが出力されます。
この出力されたログに対してパイプしてgrep
など利用することが可能ですが、
Serverless Framework
のオプションを指定することでも実現可能です。
よく使いそうなオプションをまとめておきます。
-t
オプションでtail -f
のような確認ができます。
$ sls logs -f func -t
--filter
オプションで取得するログの絞込ができます。
ログに「2018-02-26」が含まれているログだけ取得されます。
$ sls logs -f func --filter 2018-02-26
--startTime
オプションでログの取得期間を指定することができます。
過去5時間以内に発生したログが取得されます。
$ sls logs -f func --startTime 5h
詳細は下記をご確認ください。 https://serverless.com/framework/docs/providers/aws/cli-reference/logs/
さいごに
いかがだったでしょうか。
Serverless FrameworkとLambdaを使って CloudFrontログをCloudWatch Logsに流してターミナルで確認できるようにしてみました。
Serverless Frameworkを使ったことがある方ならすぐできると思いますので、 CloudFrontのログ確認を手軽にしたいなと思っている方はためしてみてはいかがでしょうか。
誰かの参考になれば幸いです。