CloudWatch Log Based AlarmのBY句でMulti-contributor Alarmを試してみた

CloudWatch Log Based AlarmのBY句でMulti-contributor Alarmを試してみた

2026.07.02

はじめに

2026年7月1日、CloudWatch Log Based AlarmのAWSブログ(What's New)と公式ドキュメントが公開されました。

https://aws.amazon.com/jp/about-aws/whats-new/2026/07/amazon-cloudwatch-log-alarms/

先行記事では、CLIリファレンスを参考に PutLogAlarm APIの基本機能を検証しました。

https://dev.classmethod.jp/articles/cloudwatch-log-based-alarm-putlogalarm-try/

今回公開されたドキュメントにより、先行記事で未検証だった Multi-contributor Alarm(BY句によるグループ別独立評価)の仕様が明文化されました。本記事ではこの機能を主軸に検証します。

項目 単一値アラーム(先行記事) Multi-contributor Alarm(本記事)
AggregationExpression count(*), avg(duration) など count(*) by svc, avg(duration) by endpoint など
評価単位 クエリ全体で1つの値 BY句のグループ(contributor)ごとに独立評価
閾値判定 全体の集約値 vs 閾値 各 contributor の値 vs 閾値
SNS通知 アラーム全体で1通知 閾値条件を満たした contributor ごとに個別通知
通知に含まれる情報 AlarmName, NewStateReason + AlarmContributorId, AlarmContributorAttributes

Multi-contributor Alarm とは

AggregationExpressionby 句を付けると、クエリ結果がグループ化され、各グループが「contributor」として独立して閾値評価されます。例えば count(*) by serviceName なら、serviceName値ごとにカウントが計算されます。閾値条件を満たしたcontributorがALARM判定となり、通知もcontributor単位で発火します。

公式ドキュメントに記載されている制約は以下のとおりです。

  • BY句に指定できるフィールド数: 最大5
  • 1クエリあたりのcontributor数: 最大500
  • アラームが追跡するcontributor数: 最大100

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/alarm-log.html

検証: Multi-contributor Alarm の作成と動作確認

検証用に以下のようなJSON形式の構造化ログをロググループに投入しました。

{"level":"error","serviceName":"auth-service","environment":"prod","endpoint":"/api/login","duration":1500,"msg":"connection refused"}

このログに対し、3つのパターンの AggregationExpression でMulti-contributor Alarmを作成しました。

サービス別エラーカウント(BY句基本形)

serviceName ごとにエラー件数をカウントし、2件以上でALARMとするアラームを作成しました。

aws cloudwatch put-log-alarm \
  --alarm-name "multi-contributor-case1-error-by-service" \
  --scheduled-query-configuration '{
    "QueryString": "filter level = \"error\" | fields serviceName as svc",
    "LogGroupIdentifiers": ["/test/multi-contributor-alarm"],
    "ScheduledQueryRoleARN": "arn:aws:iam::123456789012:role/log-alarm-scheduled-query-role",
    "ScheduleConfiguration": {
      "ScheduleExpression": "rate(1 minute)",
      "StartTimeOffset": 360,
      "EndTimeOffset": 0
    },
    "AggregationExpression": "count(*) by svc"
  }' \
  --query-results-to-evaluate 1 \
  --query-results-to-alarm 1 \
  --threshold 2 \
  --comparison-operator "GreaterThanOrEqualToThreshold" \
  --alarm-actions "arn:aws:sns:ap-northeast-1:123456789012:my-topic"

describe-alarms の結果です。

{
  "AlarmName": "multi-contributor-case1-error-by-service",
  "StateValue": "ALARM",
  "StateReason": "4 out of 4 contributors evaluated to ALARM",
  "ScheduledQueryConfiguration": {
    "AggregationExpression": "count(*) by svc"
  }
}

StateReasonが「4 out of 4 contributors evaluated to ALARM」という形式になり、ALARM状態のcontributor数が分かります。

各contributorの判定結果は以下のとおりです。

svc count(*) 判定
auth-service 3.0 ALARM
payment-service 3.0 ALARM
notification-service 2.0 ALARM
order-service 2.0 ALARM

全4 contributorが閾値(2件以上)を満たしたためALARMに遷移しました。本検証では4種類の serviceName のログを投入しており、いずれも2件以上のエラーを含んでいます。

SNS通知はcontributorごとに個別に発火しました。SQS経由で受信した通知メッセージの構造を確認します。

{
  "AlarmName": "multi-contributor-case1-error-by-service",
  "NewStateValue": "ALARM",
  "NewStateReason": "Threshold Crossed: 1 out of the last 1 query results [3.0 (02/07/26 00:54:47)] was greater than or equal to the threshold (2.0)",
  "AlarmContributorId": "79e1d0e2f3955827",
  "AlarmContributorAttributes": {
    "svc": "payment-service"
  },
  "LogGroups": ["/test/multi-contributor-alarm"],
  "QueryString": "filter level = \"error\" | fields serviceName as svc",
  "AggregationExpression": "count(*) by svc",
  "QueryExecutionId": "4015767e-3a01-4c88-b245-062cd6ffb129"
}
  • AlarmContributorId: contributorを識別するID(本検証では16桁の16進数文字列が確認できました)
  • AlarmContributorAttributes: BY句で指定したフィールドの値がマップとして格納される
  • NewStateReason: そのcontributorの実測値(3.0)と閾値(2.0)が含まれる

エンドポイント別レイテンシ(avg + sort desc)

avg(duration) by endpoint | sort desc として、エンドポイント別の平均レイテンシを降順で評価するアラームを作成しました。

aws cloudwatch put-log-alarm \
  --alarm-name "multi-contributor-case2-latency-by-endpoint" \
  --scheduled-query-configuration '{
    "QueryString": "fields duration, endpoint",
    "LogGroupIdentifiers": ["/test/multi-contributor-alarm"],
    "ScheduledQueryRoleARN": "arn:aws:iam::123456789012:role/log-alarm-scheduled-query-role",
    "ScheduleConfiguration": {
      "ScheduleExpression": "rate(1 minute)",
      "StartTimeOffset": 360,
      "EndTimeOffset": 0
    },
    "AggregationExpression": "avg(duration) by endpoint | sort desc"
  }' \
  --query-results-to-evaluate 1 \
  --query-results-to-alarm 1 \
  --threshold 1000 \
  --comparison-operator "GreaterThanOrEqualToThreshold" \
  --alarm-actions "arn:aws:sns:ap-northeast-1:123456789012:my-topic"

6つのエンドポイントのうち、平均レイテンシ1000ms以上の5つがALARMに遷移しました。

各contributorの判定結果は以下のとおりです。今回は AlarmActions のみを設定しているため、ALARM判定のcontributorはSNS通知で値を確認し、OK判定の /api/refundはクエリ結果から取得しました。

endpoint avg(duration) 判定
/api/send 4750.0 ALARM
/api/charge 2900.0 ALARM
/api/token 1800.0 ALARM
/api/login 1750.0 ALARM
/api/orders 1150.0 ALARM
/api/refund 500.0 OK

sort desc を指定すると、クエリ結果上では値の大きい順にcontributorが並びました。今回のようにcontributor数が上限内に収まるケースでは、各contributorが独立して閾値評価されており、sort の有無はALARM/OKの判定結果には影響しませんでした。

複数フィールドBY句(serviceName, environment)

BY句に複数フィールドを指定した場合のcontributorキー構成を確認しました。

aws cloudwatch put-log-alarm \
  --alarm-name "multi-contributor-case3-by-service-env" \
  --scheduled-query-configuration '{
    "QueryString": "filter level = \"error\" | fields serviceName, environment",
    "LogGroupIdentifiers": ["/test/multi-contributor-alarm"],
    "ScheduledQueryRoleARN": "arn:aws:iam::123456789012:role/log-alarm-scheduled-query-role",
    "ScheduleConfiguration": {
      "ScheduleExpression": "rate(1 minute)",
      "StartTimeOffset": 360,
      "EndTimeOffset": 0
    },
    "AggregationExpression": "count(*) by serviceName, environment"
  }' \
  --query-results-to-evaluate 1 \
  --query-results-to-alarm 1 \
  --threshold 2 \
  --comparison-operator "GreaterThanOrEqualToThreshold" \
  --alarm-actions "arn:aws:sns:ap-northeast-1:123456789012:my-topic"

結果は「4 out of 5 contributors evaluated to ALARM」でした。serviceNameenvironment の組み合わせが5つ存在し、そのうち4つがエラー2件以上でした。

SNS通知の AlarmContributorAttributes を確認すると、複数フィールドがマップとして格納されています。

{
  "AlarmContributorId": "07416b2411a9b6ab",
  "AlarmContributorAttributes": {
    "serviceName": "auth-service",
    "environment": "prod"
  }
}

BY句に複数フィールドを指定すると、各フィールド値の組み合わせが1つのcontributorになります。これにより「auth-serviceのprod環境」と「auth-serviceのstaging環境」が別のcontributorとして独立評価されます。

検証: CloudFormation での作成

AWS::CloudWatch::LogAlarm リソースタイプでMulti-contributor Alarmを作成しました。

AWSTemplateFormatVersion: '2010-09-09'
Description: Multi-contributor Log Alarm via CloudFormation

Resources:
  MultiContributorLogAlarm:
    Type: AWS::CloudWatch::LogAlarm
    Properties:
      AlarmName: multi-contributor-cfn-case4
      AlarmDescription: "CloudFormation で作成した Multi-contributor Alarm"
      ScheduledQueryConfiguration:
        QueryString: 'filter level = "error" | fields serviceName as svc'
        LogGroupIdentifiers:
          - /test/multi-contributor-alarm
        ScheduledQueryRoleARN: arn:aws:iam::123456789012:role/log-alarm-scheduled-query-role
        ScheduleConfiguration:
          ScheduleExpression: rate(1 minute)
          StartTimeOffset: 360
          EndTimeOffset: 0
        AggregationExpression: "count(*) by svc"
      QueryResultsToEvaluate: 1
      QueryResultsToAlarm: 1
      Threshold: 2
      ComparisonOperator: GreaterThanOrEqualToThreshold
      AlarmActions:
        - arn:aws:sns:ap-northeast-1:123456789012:my-topic
      ActionsEnabled: true

Outputs:
  AlarmArn:
    Value: !GetAtt MultiContributorLogAlarm.Arn

デプロイ後、describe-alarms で確認するとCLIで作成した場合と同様に動作し、「3 out of 3 contributors evaluated to ALARM」に遷移しました。

補足: 公式ドキュメントで明文化された情報

IAMロール分離の推奨構成

Log Based Alarmでは、用途に応じて以下のIAMロールを指定します。

  • ScheduledQueryRoleARN: スケジュールクエリの実行に使用。logs:StartQuerylogs:StopQuerylogs:GetQueryResults の権限が必要
  • ActionLogLineRoleArn: ActionLogLineCount を設定した場合に、通知に含めるログ行の取得に使用。logs:GetLogEvents の権限が必要

権限は最小限に絞り、対象ロググループのARNのみに制限することが推奨されています。

TreatMissingData の挙動

クエリ結果が空(contributorが1つも返されない)場合の動作を TreatMissingData で制御します。空のロググループ(/test/multi-contributor-alarm-empty)を対象にして4つのオプションを検証した結果は以下のとおりです。

オプション アラーム状態 用途
missing(デフォルト) INSUFFICIENT_DATA データ不足を明示的に検知したい場合
notBreaching OK ログが無い=正常と見なす場合
breaching ALARM ログが出ない事自体が異常な場合(例: ヘルスチェックログの欠如)
ignore 前の状態を維持 一時的なデータ欠損でアラート状態を変えたくない場合

StateReasonには設定値が含まれるため、なぜその状態になったかが分かります。

なお本検証では、空のロググループを使って「クエリ結果全体が空の場合」の挙動を確認しました。BY句利用時に「特定のcontributorのログのみが欠如した」ケースの扱いは、今回の検証対象外です。

EvaluationState

スケジュールクエリの実行自体が失敗した場合、通常の状態遷移ではなく EvaluationState フィールドが EVALUATION_ERROR に設定されます。検証では、logs:StartQuery 権限を持たないIAMロールを ScheduledQueryRoleARN に指定して確認しました。

{
  "StateValue": "INSUFFICIENT_DATA",
  "EvaluationState": "EVALUATION_ERROR",
  "StateReason": "User with accountId: 123456789012 is not authorized to perform StartQuery on resources /test/multi-contributor-alarm."
}

describe-alarms のレスポンスに EvaluationState が出現していれば、ScheduledQueryRoleARN に設定したIAMロールの権限を確認してください。

その他の制約

  • Scheduled Queryの同時実行上限: アカウントあたり100
  • EndTimeOffset: ログの取り込み遅延を考慮する場合に設定。0(デフォルト)だと、取り込みが完了していないログが評価対象外になる可能性がある
  • M-out-of-N評価: QueryResultsToAlarm(M)out of QueryResultsToEvaluate(N)で、直近N回の評価中M回が閾値条件を満たすとALARMへ遷移。例えばM=2, N=3に設定すると、直近3回中2回以上がbreachingと判定された場合にALARMとなるため、一時的なスパイクによる誤報を抑制できます

まとめ

先行記事では、Log Based AlarmによりCloudWatch Logsの検索結果を単一の集約値として評価し、メトリクスフィルターなしでログベースのアラームを作成できることを確認しました。

今回検証したMulti-contributor Alarmでは、AggregationExpression にBY句を追加することで、評価単位をクエリ全体からcontributor単位へ拡張できます。count(*) by serviceNameavg(duration) by endpoint のように指定すると、サービス名やエンドポイントごとに独立して閾値評価されます。閾値条件を満たしたcontributor単位で通知されることを確認しました。

これにより、複数サービスや複数エンドポイントを1つのLog Based Alarmで横断的に監視できます。通知に含まれる AlarmContributorAttributes から対象グループを確認でき、本検証の範囲ではCloudFormationでも同様に作成できました。

Multi-contributor Alarmでは、同じBY句アラーム内のcontributorに共通の閾値が適用されます。そのため、同じ閾値で評価できるグループはBY句アラームに集約し、閾値を分けたい対象は別アラームとして定義する、という使い分けが考えられます。

参考リンク

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事