[アップデート] CloudWatch Logs Insights のクエリ言語に JOIN とサブクエリが追加され、異なるロググループのログを関連付けて分析できるようになりました
いわさです。
CloudWatch Logs Insights はロググループに対してインタラクティブにクエリを実行し、ログデータを検索・分析できる機能です。
Logs Insights QL、OpenSearch PPL、OpenSearch SQL の 3 つのクエリ言語をサポートしています。
Logs Insights では従来から複数のロググループを選択して単一クエリを実行することは可能でした。
ただし、これは複数ロググループのログをまとめて検索・集計するもので、異なるロググループのログイベント同士をリクエスト ID などの共通キーで関連付けて分析することはできませんでした。
例えばアプリケーションサービスのエラーログと認証サービスのログを突き合わせたい場合、それぞれのロググループに対して個別にクエリを実行し、結果を手動で照合する必要がありました。
今回のアップデートで、Logs Insights QL に join コマンドとサブクエリ構文が追加されました。
これにより、異なるロググループのログイベントを共通キーで結合したり、サブクエリで中間結果を抽出してから外側のクエリで絞り込んだりといった相関分析が、Logs Insights QL の単一クエリで完結するようになりました。
全商用リージョンで利用可能とのことです。
今回こちらを確認してみたので紹介します。
実際に確認してみる
では早速 CloudWatch Logs Insights のコンソールから新しいコマンドを確認してみましょう。
検証用のログデータを準備する
今回は 2 つのロググループを用意して検証してみました。
/hoge0424/app-service にアプリケーションサービスのログ、/hoge0424/auth-service に認証サービスのログをそれぞれ投入しています。
各ログには共通の requestId フィールドを持たせています。

まずは従来の方法で、両方のロググループを選択してクエリを実行してみます。

2 つのロググループのログが混在して 10 件返ってきました。
app-service のレコードには authResult / authMethod がなく、auth-service のレコードには endpoint / status がありません。
このように、従来はログをまとめて取得することはできても、共通キーで関連付けることはできませんでした。
join コマンドを使ってみる
まずは join コマンドから試してみます。
構文は以下のとおりです。
join type=<join_type> left=<left_alias> right=<right_alias>
where <left_alias>.<field>=<right_alias>.<field>
(SOURCE <right_log_group>)
type パラメータで結合タイプを指定でき、inner(デフォルト)と left の 2 種類がサポートされているようですね。
なお、公式ドキュメントによると結合条件は等価条件(=)のみで、1 クエリにつき join コマンドは 1 つまでとのこと。
Only equality (=) conditions are supported.
Only one join command is supported per query.
/hoge0424/app-service をクエリ対象のロググループとして選択し、/hoge0424/auth-service のログと requestId で結合するクエリを実行してみます。

left と right でエイリアスを指定し、app.requestId や auth.authResult のようにドット記法で各ロググループのフィールドにアクセスできます。
先ほどの従来のクエリとは異なり、各レコードに app-service と auth-service 両方のフィールドが横に結合されて表示されていることがわかりますね。
これまでだと /hoge0424/app-service でエラーの requestId を特定してから、/hoge0424/auth-service でその requestId を検索する、という 2 段階の操作が必要でしたが、join を使えば 1 回のクエリで完結します。
なお、join を使う場合はコンソールのロググループ選択欄にはプライマリ(左側)のロググループだけを指定します。
右側のロググループは SOURCE 句で指定するため、両方を選択欄に含めると ServiceUnavailableException が発生しました。

公式ドキュメントには特に記載がなかったのですが、join や subqueries で SOURCE を使う場合はプライマリ側のロググループのみを選択する必要があるようです。
サブクエリを使ってみる
続いてサブクエリを試してみます。
サブクエリは filter コマンドの in 句の中にネストしたクエリを記述する形式みたいです。
認証サービスで認証失敗(authResult = "FAILED")となったリクエスト ID を抽出し、そのリクエスト ID に対応するアプリケーションサービスのログを取得するクエリを実行してみます。

サブクエリ部分で /hoge0424/auth-service から認証失敗のリクエスト ID を抽出し、外側のクエリでそのリクエスト ID に一致するアプリケーションログを取得しています。
join とは異なり、サブクエリは中間結果をフィルタ条件として使う形なので、結合ではなく「条件の動的な生成」に近い使い方ですね。
なお、公式ドキュメントによるとサブクエリにはいくつかの制限があるみたいです。
Nested subqueries are not supported.
Correlated subqueries are not supported.
Inner query execution is limited to 30 seconds.
ネストしたサブクエリや相関サブクエリはサポートされておらず、内部クエリの実行時間は 30 秒までとのことです。
サブクエリで集計を使ってみる
サブクエリの中で stats コマンドによる集計も使えます。
例えば、エラーが発生したリクエスト ID を集計で抽出してから、そのリクエストの詳細を取得するクエリを書いてみます。

サブクエリ内で集計した結果をフィルタ条件に使えるので、「エラーが N 回以上発生したリクエストだけを抽出する」といった分析が 1 クエリで実現できます。
さいごに
本日は CloudWatch Logs Insights の Logs Insights QL に join コマンドとサブクエリ構文が追加されたので確認してみました。
これまで複数のロググループを選択してクエリを実行すること自体は可能でしたが、異なるロググループのログイベント同士を共通キーで関連付けて分析するには、個別にクエリを実行して手動で突き合わせるか、OpenSearch SQL に切り替えて JOIN を使う必要がありました。
今回のアップデートで Logs Insights QL のパイプベースの構文のまま、ロググループ間の結合やサブクエリによるフィルタリングが出来るようになったのは良いですね。
複数のロググループにまたがるログを関連付けて分析したいケースは多いと思うので、活用の幅は広そうです。
1 クエリにつき join は 1 つまで、サブクエリのネストは不可、といった制限はありますが、基本的なユースケースには十分対応できるかなと思います。










