📈

ログをS3に出力してAthenaでクエリする方法

4 min read

はじめに

APIのログを管理する仕組みを、AWSをフル活用して作りたかったので、以下のような流れでログを出力〜確認する環境を構築してみました。(node.jsの部分はLambdaを想定)

[node.jsアプリ]->[Kinesis Firehose]->[S3]->[Glue]->[Athena]

うまく行ったので作成する方法をまとめてみました。

方法

S3バケットの作成

  • 任意のバケット名を入力します。私は katoaki-dev-log-stream というバケットを作成しました。
    • バケット名を入力し、他はデフォルトのままとします

配信ストリームの作成

node.jsアプリの作成

S3バケットへログを出すだけのシンプルなものを作ります。

  • Kinesisのダッシュボードに移動します

  • Name and source
    ストリーム名を入力し、他はデフォルトのまま次へ進みます。
    私は katoaki-dev-log-stream という名称を設定しました。

  • Process records
    デフォルトのまま次へ進みます

  • Choose a destination
    前のセクションで作成したS3バケットを指定して、他はデフォルトのまま次へ進みます

  • Configure settings
    デフォルトのまま次へ進みます

  • Review
    設定内容を確認して、次へ進みます

  • 確認
    Data Firehoseに項目が作成され、Activeになっていれば作成成功です

クローラの作成

データの内容からAthenaのテーブルを構築するために、クローラを作成します。
最低限の設定でクローラを作ります

  • Glueダッシュボードからクローラの追加

  • クローラの情報
    クローラの名前を指定します。私は katoaki-dev-log-stream-crawler を指定しました。

  • Crawler source type
    デフォルトのまま次へ進みます。

  • データストア
    インクルードパスに前セクションで作成したS3バケットを指定します。他はデフォルトのまま次へ進みます。

「別のデータストアの追加」ダイアログ画面になりますが、いいえのまま次へ進みます。

  • IAMロール
    デフォルトで選択されている「IAMロールを作成する」のオプションを選択した状態で、IAMロール名の末尾を設定します。私は最初のステップで入力したクローラ名を指定しました。

  • スケジュール
    頻度はデフォルト(オンデマンド)のまま次へ進みます。

  • 出力
    「データベースの追加」を選択して、モーダルダイアログ内でデータベース名を入力して確定します。私はストリーム名と同じ名称にしました。
    その他の設定はデフォルトのまま次へ進みます。

  • すべてのステップの確認
    設定内容を確認して次へ進みます。

node.jsでログ出力をするアプリを作成

  • 必要なライブラリをインストールします
$ npm init
$ npm install aws-sdk --save
  • FirehoseにPUTするだけの最低限のコードを書きます
$ vim app.js

サンプルコードは以下です。

const AWS = require("aws-sdk");
const region = process.env.AWS_REGION || 'ap-northeast-1';

AWS.config.update({ region: region });

const DELIVERY_STREAM_NAME = "katoaki-dev-log-stream";

const main = async () => {
  const log = {
    "key": "fuga",
    "value": 'hoge',
    "created_at": Date.now(),
  }

  // See: https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/writing-with-sdk.html
  const params = {
    DeliveryStreamName: DELIVERY_STREAM_NAME,
    Record: {
      Data: JSON.stringify(log)
    }
  }

  const firehose = new AWS.Firehose({apiVersion: '2015-08-04'});

  try {
    await firehose.putRecord(params).promise();
  } catch(e) {
    console.log(e);
  }
}

main();
  • AWS SDKの実行に必要な環境変数をセットします
$ aws configure

とか。

  • 実行します
$ node app.js

5分程待って、前セクションで作成したS3バケットにオブジェクトが作成されていることを確認します。

Glueでテーブルを作成

  • クローラ作成確認と実行
    クローラが作成されていることを確認します。
    その上で、クローラを実行します。

ステータスが Startingに切り替わり、最終的にReadyになることを確認します。

Athenaのテーブルを確認

  • データベースの選択
    Glueで指定したデータベースを選択します。
    その上で、クローラで作成されたテーブルのメニューから「テーブルのプレビュー」を選択します。

自動的にクエリが実行されて、アプリが出力したログが見れることを確認します。

まとめ

  • 以下の構成で、AWSをフル活用してAWS LambdaのログをAthenaでクエリできるシステムを作成できる
[node.jsアプリ]->[Kinesis Firehose]->[S3]->[Glue]->[Athena]

おわりに

node.jsアプリからログを出力し、出力内容をAthenaでクエリできる最小限の設定が確認できました。これをベースに必要なものを追加していけば、便利なログ基盤が用意できそうです。

当時、FirehoseもGlueもAthenaも経験がほぼなかったので、自分と同じような状況の人向けになるべく画像多めにしてみました。

参考になれば幸いです。