wan0ri Lab

CloudWatchのメトリクスフィルターを論理演算で組み立てるまでの記録

· wan0ri

前置き

参画案件の情報を伏せる意味合いもあり、アプリケーション名や文字列については実際のものとは違うものになります。

背景とやらかし

現在参画している「AIX から AWS への全面リプレイス案件」で、CloudWatch Logs のメトリクスフィルターを設定する作業がありました。
現行 AIX 環境では、オンラインアプリケーション ABC 系のエラー検知に以下の 2 つのルールが設定されています。

  • ABC[0-9]{4}E
  • CV[0-9]{4}E

さらに例外として CV9006E と CV9007E が出力された場合は検知から除外する必要があります。
この条件をそのまま CloudWatch に写経しようとして、フィルターは「正規表現を連結するもの」だと勘違いしたまま構築を進めたのが今回のやらかしの発端でした。

CloudWatch フィルターパターンの素朴なルール整理

CloudWatch Logs のフィルターパターンは、まず「文字列の出現有無を論理演算で組み合わせる」仕組みになっています。スペースで区切った語句は AND、語句の前に - を置くと NOT、語句の前に ? を置くと OR(いずれかが含まれていればマッチ)という扱いになります。
これらはプレーンテキストにも JSON ログにも共通で、JSON の場合は { $.field = “value” } のようにフィールドを指定できるのが追加要素です。
正規表現はあくまで補助的に %…% で囲んだ部分として書けますが、1 パターンにつき最大 2 つまでという制限がありますし、使わなくても目的を満たせるなら論理演算だけで完結させた方が運用は楽です。

今回のケースでは「ABC または CV で始まり、4 桁の数字と E が続く」という条件をどうしても 1 つの正規表現で書きたいので %((ABC|CV)[0-9]{4}E)% までは許容するとしても、除外条件にまで正規表現を使ってしまうとクォータを超えてしまいます。
このルールを理解しないまま以下のように 4 本の正規表現を含んだパターンを書いた結果、テスト画面で
Your input has exceeded the maximum of 2 regular expressions per filter pattern.
と表示されて撃沈しました。

[(a=%ABC[0-9]{4}E%||a=%CV[0-9]{4}E%)&&(a!=%CV9006E%&&a!=%CV9007E%)]

改めて組み直したフィルターパターン

論理演算のルールを踏まえ、最終的には以下のように整理しました。

%((ABC|CV)[0-9]{4}E)% -CV9006E -CV9007E
  • %((ABC|CV)[0-9]{4}E)% が唯一の正規表現で、ABC####E または CV####E(# は数字)の文字列を拾います。
  • -CV9006E と -CV9007E は除外キーワードです。正規表現ではなく単純な文字列条件なのでクォータを消費しません。
  • 全てスペース区切りなので AND 結合として評価され、正規表現に一致し、かつ 2 つの除外語を含まないログだけがヒットします。

テスト用に使用したログは以下の通りです。

Aug 21 10:05:42 abc ip-10-24- ABC1234E 2025/08/22 HOST接続エラーが発生しました。
Aug 21 10:05:42 abc ip-10-24- CV1234E 2025/08/22 HOST接続エラーが発生しました。
Aug 21 10:05:42 abc ip-10-24- CV9006E 2025/08/22 HOST接続エラーが発生しました。
Aug 21 10:05:42 abc ip-10-24- CV9007E 2025/08/22 HOST接続エラーが発生しました。

CloudWatch コンソールの「パターンをテスト」機能に上記パターンとログを入力すると、ABC1234E と CV1234E の 2 行だけがマッチし、除外したい 2 行はヒットしないことを確認できました。

JSON ログの場合の考慮点

今回はテキストログでしたが、JSON 形式のログに対しては { $.appCode = “ABC” } のようなフィールド指定で論理演算が書けます。
比較演算子には =, !=, <, >, <=, >= が利用可能で、値にワイルドカード * を含めることもできます。
この場合でも組み立ての基礎は同じで、まずはフィールドごとに条件を列挙し、足りない部分を %regex% で補うという順序を意識するのが吉です。

正規表現との付き合い方のポイント

  • まずは論理演算で条件を絞り込めないかを考える。除外条件は - 付きの語句、JSON なら != で表現できる。
  • 正規表現を使う場合は必ず % で囲み、1 パターンあたり 2 つまでという制限と、ロググループごとに正規表現を含むフィルターが最大 5 つというクォータを把握しておく。
  • コンソールや CLI の test-metric-filter を使い、正規表現の文字クラスが CloudWatch 側でサポートされているかを逐次確認する。

まとめ

  • CloudWatch のフィルターパターンは論理演算が主役で、正規表現は %…% の形で補助的に書くもの。
  • 1 パターンに書ける正規表現は 2 つまで。除外条件などは極力プレーンな語句で書く。
  • テスト機能を必ず使い、ヒットさせたいログ・除外したいログの双方で挙動を確認する。

同じようにフィルターパターンで詰まっている方の参考になれば幸いです。