tukaのブログ

気が向いた時に何か書きます

CloudWatch Logsのフィルター構文が正規表現に対応したのでcheck-aws-cloudwatch-logsプラグインで試してみた

2023年9月6日の What's New with AWS で、CloudWatch Logsのフィルターパターンの正規表現への対応が発表されました。

aws.amazon.com

MackerelでもCloudWatch Logsの監視はcheck-aws-cloudwatch-logsプラグインを用いてできるのですが、正規表現の対応はCloudWatch LogsのAPI側のアップデートになるので、check-aws-cloudwatch-logsはそのままに条件指定だけ正規表現に変更して動作するか試してみました。

TL;DR

  • CloudWatch Logsのフィルターパターンが正規表現による指定に対応したようです。
    • ただしサポートしている正規表現には制限があります。*1
  • check-aws-cloudwatch-logsでもフィルターパターン構文の正規表現が指定できます。

フィルターパターン構文とは?

詳しくはAWSのユーザーガイドを見てくれ!なのですが、ざっくり言うとログイベントを照会するためのCloudWatch Logs独自のクエリです。

フィルターとパターンの構文 - Amazon CloudWatch Logs

Mackerelのチェック監視プラグインには、check-logやcheck-windows-eventlogなど正規表現によるマッチングに対応したものがいくつかありますが、CloudWatch Logs APIのFilterLogEventsでチェックする仕組みを持つcheck-aws-cloudwatch-logsは正規表現の指定にはこれまで非対応でした。*2

検証してみる

次のようなログを1行1イベントとして出力して、ERROR もしくは CRITICALを含むログの監視をフィルターパターン構文と正規表現構文のそれぞれの条件で監視してみます。

[WARNING] This is WARNING message.
[ERROR] This is ERROR message.
[ERROR] This is ERROR message, but ignore it.
[CRITICAL] This is CRITICAL message.

検証用のロググループ・ログストリームを作成してログをPUTする

検証用にロググループ・ログストリームを作成して、単純な非構造化ログを出力して試してみます。

aws logs create-log-group --log-group-name regex-test
aws logs create-log-stream --log-group-name regex-test --log-stream-name regex-test-stream-1

ログイベントは次のようにPUTします。

aws logs put-log-events --log-group-name regex-test --log-stream-name regex-test-stream-1 \
--log-events \
"timestamp=$(date +%s)100,message=\"[WARNING] This is WARNING message.\"" \
"timestamp=$(date +%s)200,message=\"[ERROR] This is ERROR message.\"" \
"timestamp=$(date +%s)300,message=\"[ERROR] This is ERROR message, but ignore it.\"" \
"timestamp=$(date +%s)400,message=\"[CRITICAL] This is CRITICAL message.\""

検証する際は次のような点を気をつけました。

  • すでにチェック済みのログイベントは監視の対象とならないため、必要に応じて同じ内容でログイベントをPUTします。
  • 同じログストリームにPUTを続けるには put-log-events に nextSequenceToken の指定が必要になります。詳しくはput-log-eventsに関するリファレンスを確認してください。

フィルターパターン構文で試してみる

フィルターパターン構文で ERROR もしくは CRITICAL を含むイベントを条件に指定してみます。 フィルターパターン構文では、?を用いて次のような指定になります。

?ERROR ?CRITICAL

これをcheck-aws-cloudwatch-logsプラグインの条件に指定してみます。 check-aws-cloudwatch-logsがインストールされているホストで、次のようなコマンドで直接実行して確認します。

## 監視ルールの設定
[plugin.checks.hoge]
command = ["check-aws-cloudwatch-logs", "--log-group-name", "regex-test", "--pattern", "?ERROR ?CRITICAL", "--return"]
env = { AWS_REGION = "ap-northeast-1" }

## 上記を直接実行するコマンド
$ AWS_REGION=ap-northeast-1 check-aws-cloudwatch-logs --log-group-name regex-test --pattern "?ERROR ?CRITICAL" --return

実行した結果が以下の通りで、ERRORCRITICALの3つのログイベントが検知されました。

CloudWatch Logs CRITICAL: 3 > 0 messages for pattern /?ERROR ?CRITICAL/
[ERROR] This is ERROR message.[ERROR] This is ERROR message, but ignore it.[CRITICAL] This is CRITICAL message.

正規表現構文に置き換えて試してみる

これを正規表現構文に置き換えてみます。 フィルターパターンの正規表現構文は%〜%で囲む形式で定義するそうなので、次のように指定できます。

%ERROR|CRITICAL%

ログイベントを再度PUTした後に、同じように直接実行してみます。

$ AWS_REGION=ap-northeast-1 check-aws-cloudwatch-logs --log-group-name regex-test --pattern "%ERROR|CRITICAL%" --return

CloudWatch Logs CRITICAL: 3 > 0 messages for pattern /%ERROR|CRITICAL%/
[ERROR] This is ERROR message.[ERROR] This is ERROR message, but ignore it.[CRITICAL] This is CRITICAL message.

先程と同じ3件のログイベントにマッチしていますね。 比較的単純な条件による監視であれば、フィルターパターン構文より正規表現構文の方が直感的に定義できそうです。

フィルターパターン構文の正規表現は万能ではない

正規表現に対応されたばんざーいと思っていたのですが、今回サポートされた正規表現構文では一部の演算子やシンボルがサポートされておらず、()!がサポート外となるため、否定的先読みによる除外*3などには対応していないようでした。

フィルターパターンでは-演算子で除外できるのですが?を含む場合だと?の効力が無効となってしまうなどの制約もあり、除外条件の指定は引き続き難しいなという印象を受けました。

まとめ

CloudWatch Logsのフィルターパターンに追加された正規表現構文を、check-aws-cloudwatch-logsプラグインで試してみました。

CloudWatch Logsの監視にはCloudWatch Logs Insightsを使用するcheck-aws-cloudwatch-logs-insightsもあるので、それぞれのプラグインの違いを比較の上でどちらを使用するか選択するとよさそうです。

*1:2023年9月10日時点では日本語翻訳されたページは提供されてないですが、Supported regular expressions (regex) syntaxで定義されています

*2:CloudWatch Logs Insightsを使用するcheck-aws-cloudwatch-logs-insightsプラグインは、クエリ構文が正規表現に対応しています。

*3:否定的先読みについては「正規表現で文字列を含まない、否定の記述 | UX MILK」が参考になります。