プレスリリースやお知らせ、開発ブログ、会社の活動状況、Mattermost・aws・AI等の技術情報などを発信しています。

AWS CloudWatch Logs のparseの使い方がわからなかったので調べてみた

こんばんわhorikiです。

業務上AWSのCloudWatch Logsのログのインサイトを使って、ログの検索、集計を行なっているのですが、ずっと気になっていることがありました。

それがこちら。

そう、parseですね。

クエリによって処理される 1 つまたは複数のエフェメラルフィールドを作成します。

うーん、何言ってるかわからないですね。

とはいえ、使ってみると便利な機能でしたので、使い方をまとめておきたいと思います。

parse部分の説明

まずはエフェメラルフィールドってなに?ということで調べました。

エフェメラル:つかの間の、一時的な、刹那の、はかない

from 英辞郎

とのこと。つまり、一時的なフィールドのようです。

肝心のクエリ部分ですが

parse '* - * [*] "* * *" * *' as host, identity, dateTimeString, httpVerb, url, protocol, statusCode, bytes

となっています。

これだけだとわかりづらいですね・・・、なので元のログを一時フィールドから再現してみます。

アスタリスクをas以降のフィールドに置き換えるので、

'host - identity [dateTimeString] "httpVerb url protocol" statusCode bytes'

になります。つまり、Parseの対象となるログは以下のような形であると推測できます。

'128.xxx.xxx.xxx - - [14/Dec/2023:10:40:57 +9000] "GET http:// www.hogehoge HTTP" 200 45'

ですので、ログを一定のフォーマットに従って分解し、要素をフィールドとして切り出せるクエリのようです。

実際の利用例

私が実際に利用した例としては以下のものがあります。

parse endpoint '*?' as endpointbase

例えば、/my/hogehogeというendpointがあるとして、このendpointが何回呼ばれたのか集計しようとしています。

ログのフィールドとしてはそのままendpointというフィールドとして出力しています。

このendpointがidというクエリパラメータを受け付ける場合、

/my/hogehoge?id={ids}

となり、単純にendpointだけで集計してしまうと、idごとに集計することになってしまいます。

このとき

parse endpoint '*?' as endpointbase

を使うと、?より前の値をendpointbaseというフィールドとして抜き出すことができ、/my/hogehoge毎に集計ができるようになります。

名前付きキャプチャグループの利用

parseには名前付きキャプチャグループを利用するという方法があります。

例えば、

/my/hogehoge/{id}

/my/hogehoge/fugafuga

というエンドポイントが二つあるとします。

この時{id}ごとに集計しようとして

parse endpoint "/my/hogehoge/*"

と指定してしまうと、fugafugaも集計されてしまいます。

ここで名前付きキャプチャグループを利用します。

名前付きキャプチャグループは(?<Name>pattern)で構成されており、<Name>には一時フィールド名、patternには正規表現が入ります。

名前付きキャプチャグループを利用すると、

parse endpoint /my\/hogehoge/(?<id>[0-9]+)/

というように書けます。

(?<id>[0-9]+)の部分が名前付きキャプチャグループとなり、正規表現(ここでは数値)に一致する{id}部分をidという一時フィールドとして抜き出しています。

正規表現に一致しないendpointは一時フィールドから省かれるためidのもののみ集計できるわけですね。

多少トリッキーになりますが、以下のようにすればidごとではない/my/hogehoge/{id}の集計も可能です。

fields @timestamp, endpoint

| parse endpoint /my\/(?<path_hogehoge>hogehoge)\/(?<id>[0-9]+)/

| filter ispresent(id) and ispresent(path_hogehoge)

| stats count(*) as total_requests by bin(1d), path_hogehoge

※filterのispresentにて値のあるもののみ集計対象としています。

※引用符を使うと正規表現が利用できないため注意が必要です。

まとめ

使いこなせれば非常に強力なクエリになりますね。

また、複雑なparseを書かなくてもいいようにログのフォーマットは整えておいた方がいいですね。

  • B!

おすすめ記事リンク