NTTドコモR&Dの技術ブログです。

Cloudwatch Logs Insightsでログを集計する話

目次

はじめに

NTTドコモ サービスイノベーション部の外山です。
普段の業務では、お客様の行動データを特定の形式でタイムライン化したデータマート「CX分析基盤」の普及活動を行っています。CX分析基盤を活用すると、サービス改善やお客様への最適な訴求を比較的手軽に実現することができます。

CX分析基盤では簡単に分析するためのツール(カスタマージャーニー可視化ツールやデータ抽出支援ツールなど)を提供しており、いくつかのアプリケーションはAWSのコンテナ(ECS)にデプロイされています。アプリケーションのログはコンテナ上で保管しておくことはできないため、すべてCloudWatchに送信することで対応しています。 ここで、雑多なログから欲しい情報を効率よく取得できるのが、CloudWatch Logs Insightsです。 本記事では、CloudWatch Logs Insightsの初学者向けに、サンプルクエリを用いて使い方を説明いたします。

CloudWatch Logs Insightsとは

AWSドキュメントでは以下のように説明されています。

CloudWatch Logs Insights には、シンプルで強力なコマンドがいくつか用意された専用のクエリ言語が含まれています。 CloudWatch Logs Insights は、サンプルクエリ、コマンドの説明、クエリの自動完了、ログフィールド検出を提供し、開始に役立ちます。サンプルクエリは、 AWS のサービスの複数のログタイプ向けに用意されています。CloudWatch Logs Insights は、Amazon Route 53、AWS Lambda などの AWSサービスからのログのフィールド AWS CloudTrail、VPC のログイベントを出力するアプリケーションまたはカスタムログを自動的に検出します。CloudWatch Logs Insights を使用して、2018年11月5日以降に Logs に送信された CloudWatch ログデータを検索できます。

昨今、サーバレスな構成も増えているため、CloudWatchにすべてログを送っておくことは後々の解析等のためにも非常に有効です。AWS公式のチュートリアルにサンプルクエリも提供されているため、すぐに試してみることができます。 「専用のクエリ」というのがやや独特なので、今回はアプリケーションの効果測定に有用なクエリを紹介したいと思います。

主なクエリコマンド

今回登場するクエリコマンドは以下になります。

クエリコマンド 動作
stats ログフィールドの値を使って集計した統計を算出
filter クエリをフィルタリングし、1 つ以上の条件に一致するログイベントのみを返却


これだけです。 他のクエリコマンドもありますので、詳細はAWSドキュメントを参考にしてください。

AWS構成

今回の検証で使用している構成は以下になります。(図は簡単化しています)

AWS構成


事前準備

ログの形式はJSONで

CloudWatchに保存するログはJSON形式にすることをお勧めします。 CloudWatch Logs Insightsでは、ログをJSONで保持することで、そのままクエリのフィールドとして使用することができるからです。 例えば、

{
    "thread_name": "http-nio-8080-exec-5",
}

のように記載されているデータへのアクセスは thread_name で実現できてしまいます。(注意:"@"は付けません。)
詳細は次項のサンプルクエリを用いて説明します。

ロググループ

単一のAWS環境で複数のアプリケーションを運用していることがほとんどだと思いますので、絞り込みを容易にするために事前にロググループを構成しておくのがおすすめです。 ロググループの構成方法については、AWSドキュメントを参考にしてください。

ロググループで絞り込み

CloudWatchのTOPから【ログのインサイト】を押下し、【ロググループを参照】からロググループを選択することで、単一のアプリケーションログに絞り込むことができます。



サンプルクエリ

以下にアプリケーションの効果測定に有用な2つのクエリを紹介いたします。 なお、カウント方法はログの仕様に応じて工夫する必要があります。

①特定ユーザーを除いた特定期間のアクセス回数を知りたい

関係者によるテスト利用を除きたいシーンなど、実質のアクセス回数を知りたい場合は以下になります。

クエリ

stats count(oidc_user_id)
| filter oidc_user_id not like "user_id1" 
     and oidc_user_id not like "user_id2"
 …

oidc_user_idはユーザーIDを指しており、not likeを使って特定ユーザーを除いています。

結果

ここで注意ポイントがいくつかあります。 * アクセス回数=ユーザーIDの出現回数 で良いかは対向システムの数やログの仕様によります。可能であれば、アクセス毎に1回出現するフィールドを指定するのが良いでしょう。 * timestampなどを使ってクエリ上で期間指定をしない場合は、UI上からも期間指定できます。



②特定ユーザーを除いたユニークユーザ数を知りたい

①のクエリうち"count"を"count_distinct"に変更するだけで実現できます。

クエリ

stats count_distinct(oidc_user_id)
| filter oidc_user_id not like "user_id1" 
     and oidc_user_id not like "user_id2"
 …

結果



クエリを作成するのが面倒な時は

AWS re:Invent 2023 (2023/11/29)にて発表された機能"natural language query generation"を利用することができます。東京リージョンでは2024/9/26にGeneral Availabilityとなりました。 【Query Generator】を押下すると利用を開始できます。なお、本投稿時点では日本語入力には対応しておらず英語で入力する必要があります。

せっかくなので試してみましょう。 プロンプトに英語で「2024年10月のユニークユーザー数を算出せよ」と入力します。


【新しいクエリを生成】を押下すると下記のクエリが得られました。

stats count_distinct(oidc_user_id) as uniqueUsers by bin(1mo)


上記のクエリを実行した結果が以下です。

正しい出力を得ることができました。 複雑な分析の場合はそのまま使えないことがあるかもしれませんが、クエリ記法の参考にはなりそうです。

料金

これまで紹介したクエリは実行時のスキャン量に対して課金されますが、非常に安価です。 東京リージョンでは、CloudWatch Logs Insightsのクエリ実行に対し、1GBスキャンあたりUSD 0.0076(2024/11/26現在)になります。 https://aws.amazon.com/jp/cloudwatch/pricing/

おわりに

本記事では、CloudWatch Logs Insightsの簡単な使い方、アプリケーションログの効果測定に有用なクエリおよび新機能Query Generatorを紹介させて頂きました。
JSONログから効率的にインサイトを抽出する方法として、本記事が参考になれば幸いです。