🐧

CloudWatch Logs Insightsを使ってユーザのアクセスログを分析する

2023/08/07に公開

やりたいこと

企業ごとのDAU(Daily Active User)の取得

  • DAU=1日で何人のユーザがサービスを利用したかを表す指標(詳細については以下の記事など参照ください)

https://repro.io/contents/dau-for-beginner/

設計

上記を実現するにあたり、ざっと思いついた方法は以下の3つです。

  1. APIへのアクセスがあるたびに、アクセスしたユーザがその日初めてアクセスしたかをDBの情報をもとにチェックして、必要に応じて都度DBに書き込む
    → APIアクセスのたびに毎回計算するのはなんかスマートじゃない。
  2. Google Analytics使う
    → あまり詳しくない。ページごとのアクセス回数などは簡単に取得できるイメージはあるが、企業ごとのアクティブユーザを取得するには一手間かかりそう。
  3. 日次でCloudWatch Logsにあるログを分析して結果をDBに書き込む
    → CloudWatch Logs Insightsで何ができるのか試してみたい。

ということで3の方法を選択しました。

ちなみに、CloudWatch Logs Insightsが何かというと、CloudWatch Logs のログデータに対して、クエリを実行できるサービスです。以下、マネジメントコンソールから操作した時の実際の画面を見ていただくと、イメージしやすいかと思います。

公式ドキュメントは以下です。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/AnalyzingLogData.html

ロジックの設計

アクセスログに、以下の情報を出力しているとします。

  • アクセス日時
  • アクセスされているエンドポイント
  • アクセスしているユーザのID
  • アクセスしているユーザが所属している企業のID

このうち、日次で、重複しない企業ID・ユーザIDの組み合わせを持つログを抽出し、その数をカウントできれば、企業ごとのDAUを計算できそうです。

インフラの設計

かなりざっくりですが以下がインフラの構成です。

やったこと

アクセスログの出力

CloudWatch Logs Insightsでは、ログ出力をJSON文字列化することでクエリのフィールドとして使用することができます。
JavaScriptやTypeScriptを例にとると、JSON.stringifyを使ってログを出力することで、JSON文字列としてログを出力できます。

const jsonObject = {
  endpoint: "エンドポイント",
  CompanyID: "企業ID",
  UserID: "ユーザID"
};
console.log(`accessInfo: ${JSON.stringify(jsonObject)}`);

CloudWatch Logs Insightsのクエリの作成

ここから、実際にCloudWatch Logs Insightsでクエリを発行してみます。

まずは、コンソールから基本的なクエリを発行してみます。

以下のようなクエリを打つことで、直近20件のログのタイムスタンプおよびログを取得できます。

fields @timestamp, @message
| sort @timestamp desc
| limit 20

以下、結果の一部です。JSON文字列として出力した内容が以下の赤枠部分のように表示されていれば、クエリのフィールドとして使用することができるようになります。

では、実際にやりたかった、重複しない企業ID・ユーザIDの組み合わせをログから抽出します。

結論としては、以下のクエリで実現できます。

fields CompanyID, UserID
| filter ispresent(UserID) and ispresent(CompanyID)
| sort CompanyID asc
| dedup CompanyID, UserID

結果は以下の通りです。

クエリについて簡単に解説しておきます。
といいつつ、fields、filter、sortの部分はなんとなくわかると思います(笑)。
dedupは以下のクラスメソッドさんの記事にある通り、割と最近サポートされたクエリのようで、重複排除をしたい時に使用します。

https://dev.classmethod.jp/articles/logs-insights-dedup/

あとは、sdkでこのクエリを叩くLambdaを作成するだけですのでこの記事はここまででおしまいです。

NCDCエンジニアブログ

Discussion