[アップデート] CloudWatch Logs メトリクスフィルターでディメンションがサポートされました!

メトリクスフィルターでフィールドを指定している場合、フィールド内の値をディメンションとして発行できるようになりました

コンバンハ、千葉(幸)です。

CloudWatch Logs のメトリクスフィルターがディメンションをサポートしました!

メトリクスフィルターで設定しているフィールドの値を、ディメンションとしてメトリクスとともにパブリッシュできるようになりました。(こう書くと何がなんやらですね。)

何ができるようになったのか

イメージとしては以下です。

メトリクスフィルターディメンションを設定できるようになり、メトリクスフィルターからパブリッシュされたメトリクスにディメンションを付与することができるようになりました。

特定の条件にマッチしたログが出力された際に、さらなる詳細情報を付与できるようになった、というイメージです。

これだけだと分かりづらいので各用語の補足をしていきます。

CloudWatch Logs メトリクスフィルターとは

CloudWatch Logs メトリクスフィルターをロググループに関連づけることで、指定したパターンに一致した場合にCloudWatch にメトリクスを発行(パブリッシュ)できます。

平たく言えばログ監視の仕組みに使用できます。「ERRORという文字列が含まれるログがロググループ内に書き込まれたら検知したい」というケースの場合、以下のイメージで実現できます。

  • ERRORという文字列が含まれる」というフィルターパターンを持つメトリクスフィルターを作成し、CloudWatch Logs ロググループに関連づける
  • メトリクスフィルターがパターンマッチした場合にパブリッシュするメトリクス(名前空間、メトリクス名)を設定しておく
  • 当該メトリクスに対してCloudWatch アラームを設定する

単純な例で考えれば、「マッチしたら対象のメトリクスに 1 をパブリッシュする」とメトリクスフィルターを設定しておき、対象のメトリクスに「値が 0 より大きかったらアラート状態に遷移させる」というCloudWatch アラームを設定することになります。

一つのロググループに複数のメトリクスフィルターを設定することもできます。

メトリクスフィルターの詳細は以下を参照してください。

CloudWatch のディメンションとは

CloudWatch のディメンションとは、メトリクスの一意の識別子として機能するものです。

平たく言えば、「名前空間とメトリクス名だけだと区別できないものに追加の観点を加える」ものです。

例えば以下の画像を見てください。EC2 インスタンスを稼働させると自動的に取得されるメトリクスです。

ここではCPUUtilizationというメトリクス名に注目します。このメトリクスは大枠としてEC2という名前空間に属しています。よって、例えば RDS インスタンスで同じメトリクス名のCPUUtilizationが取得されていたとしても、明確に区別できます。

しかし、「どの EC2 インスタンスの CPU 使用率か」を区別するためには名前空間とメトリクス名だけでは不足しています。ここでインスタンスを区別するためにInstanceIdという切り口が加われば充足します。そのように機能するのがディメンションです。

ディメンションは 1 メトリクスあたり最大 10 個まで割り当てることができます。詳細は以下を参照してください。

メトリクスフィルターでディメンションを使用するとは

今回のアップデートの内容に戻ると、「メトリクスフィルターからプッシュするメトリクスにディメンションを付与することができるようになった」というものです。

以下ドキュメントに記載されている例をベースに説明します。

例えば以下のフィルターパターンを持つメトリクスフィルターがあったとします。

フィルターパターン例

[ip, server, username, timestamp, request, status_code, bytes > 1000]

これはスペース区切りのログに対してフィールドを指定する書き方です。以下のようなフォーマットのログが出力されるケースが想定されます。(ここではダブルクォーテーションの前に\が含まれていますが、実際に出力されるログで含まれていると正常に解釈されません。)

ログのフォーマット例

127.0.0.1 Prod frank [10/Oct/2000:13:25:15 -0700] \"GET /index.html HTTP/1.0\" 404 1534

上記のログが出力された場合、各フィールドには以下の値が含まれます。

{
   "$status_code": "404", 
   "$request": "GET /products/index.html HTTP/1.0", 
   "$bytes": "1534", 
   "$timestamp": "10/Oct/2000:13:25:15 -0700", 
   "$username": "frank",
   "$server": "Prod", 
   "$ip": "127.0.0.1"
}

フィルターパターンにマッチするログが出力された場合、指定したメトリクスに値がプッシュされます。ここでは「1000バイトを超える場合」という条件のみでフィルターされ、それ以上の詳細は区別されません。

ここでディメンションとして以下を設定したとします。

メトリクスフィルターにおけるディメンション例

"Server" : $server

これにより、ディメンションServerとしてserverフィールドの値が含まれた状態でメトリクスがパブリッシュされます。(ログフォーマット例におけるProd部が該当します。)

この設定を加えることによって、例えばProdサーバーへのアクセスとDevサーバーへのアクセスは別メトリクスとして解釈されます。Stgという値が途中で増えても、設定を変更することなく自動で収集してくれます。

ディメンションを用いない状態でこれを実現しようとすると、メトリクスフィルターとメトリクス名をパターンごと(Prod,Dev,Stg,,,)に分割して設定する必要がありました。

そう考えるだいぶお手軽になりましたね。

メトリクスフィルターでディメンションを設定する場合の注意点

以下の注意点があります。

  • メトリクスフィルターに設定できるディメンションは最大で3つ
  • メトリクスフィルターの「デフォルト値」と併用はできない
  • JSON ログイベントもしくはスペース区切りのログイベントでしか使えない
  • カスタムメトリクスの料金の高騰に注意

三つ目と四つ目について補足します。

JSON ログイベントもしくはスペース区切りのログイベントでしか使えない

例えば以下のようなフィルターパターンを持つメトリクスフィルターではディメンションを指定できません。

「ERROR を含む場合」というフィルターパターン

”ERROR"

「ERROR もしくは WARN を含む場合」というフィルターパターン

?"ERROR" ?"WARN"

「Exiting を含まず ERROR を含む場合」というフィルターパターン

"ERROR" -"Exiting"

ディメンションとして出力するのはフィールドの値であるため、それを指定していないフィルターパターンの場合は対応していない、ということです。

カスタムメトリクスの料金の高騰に注意

メトリクスフィルターによりパブリッシュされた値は、カスタムメトリクスとして扱われます。そしてカスタムメトリクスはその数により課金されます。

例えば東京リージョンであれば、最初の 10,000個のメトリクスは 1個あたり0.3 USD /月かかります。

冒頭で挙げた例のようにProd,Dev,Stgとディメンションの値がパブリッシュされる場合、それらは 3 つの別物のカスタムメトリクスとして扱われます。

タイムスタンプやクライアントのIPアドレスなどカーディナリティが高い(種類の絶対数が多い)フィールドをディメンションにした場合、メトリクス数が膨れ上がることになるので注意が必要です。

偶発的な高額請求を避けるため、特定の時間内で特定のディメンションに 1000 の異なる値が発行された場合、Amazon によりメトリクスフィルターが無効化されることがあるとのことです。

やってみた

ドキュメントに記載の例を実装した上でサンプルでログレコードを出力し、メトリクスにどのように値が出力されているかを確認します。

メトリクスフィルターの作成

Testという名称のロググループにメトリクスフィルターを設定していきます。全部で3ステップあります。

フィルターパターンとして以下を設定し、次に進みます。

[ip, server, username, timestamp, request, status_code, bytes > 1000]

以下を指定し、画面を下にスクロールします。

  • フィルター名:test-filter
  • メトリクス名前空間:test-log
  • メトリクス名:Over1000byte
  • メトリクス値:1

続いて以下の値を設定していきます。

  • デフォルト値
  • Unit(単位)
  • ディメンション

デフォルト値」は、「ログが出力されているがパターンにマッチしない」場合にメトリクスにパブリッシュされる値です。今回のようなケースであれば0を指定するのがセオリーでしょう。

しかし、ディメンションと併用はできず、「デフォルト値」に値を入れるとディメンション部がグレーアウトされます。よって今回は空欄にします。

以下を指定し、次に進みます。

  • Unit:なし
  • ディメンション
    • ディメンション名:Server
    • ディメンション値:$server

ディメンション値はフィルターパターンの内訳からプルダウンが用意されているため、選択するだけです。

CloudWatch_Management_Console-2366222

最後のステップで設定内容を確認し、作成を実行します。

CloudWatch_Management_Console-2366254

以下の通り正常に作成されました。

CloudWatch_Management_Console-2366281

ログの出力とメトリクスの確認

ロググループTest内にログストリームTest-Streamを作成し、サンプルのログを出力します。

ログストリームの詳細画面から「アクション」→「ログイベントの作成」を実行することでログ出力ができます。

CloudWatch_Management_Console-2366567

CloudWatch_Management_Console-2366584

今回は以下のログイベントを1行ずつ順に作成します。

127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534
127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534
127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534
127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999
127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999
127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999
127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534
127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534
127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534
127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999
127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999
127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999
hogehoge
hogehoge
hogehoge

以下を3回ずつ実施するということです。

  • ServerProdでフィルターパターンにマッチ(1000バイトより大きい)するもの
  • ServerProdでフィルターパターンにマッチしないもの
  • ServerDevでフィルターパターンにマッチするもの
  • ServerDevでフィルターパターンにマッチしないもの
  • ログフォーマットに則っていないもの

結果から言うと、パターンにマッチするもののみメトリクスに値が出力されました。フォーマットに則っているがマッチしないもの、そもそもフォーマットに則っていないものの場合、「0が出力されるでもなく値そのものが出力されない」という状態でした。

パブリッシュされたメトリクスはこのように確認できます。指定した通りの名前空間、ディメンション、メトリクス名となっています。

CloudWatch_Management_Console-2368652

実行するタイミングをちょっと失敗したためProdの方は時間が空いていますが、それぞれ合計 3 のメトリクスが出力されています。

CloudWatch_Management_Console-2368800

メトリクスフィルターが一つであっても出力先のメトリクスを分割できたため、それぞれの環境ごとの傾向を確認したり、 Prod の方だけはCloudWatchアラームを設定しておく、といった柔軟な使い方ができそうです。

終わりに

CloudWatch Logs メトリクスフィルターがディメンションの発行に対応した、というアップデートでした。

今回の例ではディメンションは一つだけでしたが、最大三つまで設定できるため、より細かな集計も実現できます。カスタムメトリクスの料金には気をつけつつ、要件に応じて活用してみてください。

ディメンションを設定するとデフォルト値が設定できないため、「ログは出力されているがマッチしていない」場合はメトリクスの値が null になることも覚えておくといいでしょう。

以上、千葉(幸)がお送りしました。