CloudWatch Log Based AlarmのBY句でMulti-contributor Alarmを試してみた
はじめに
2026年7月1日、CloudWatch Log Based AlarmのAWSブログ(What's New)と公式ドキュメントが公開されました。
先行記事では、CLIリファレンスを参考に PutLogAlarm APIの基本機能を検証しました。
今回公開されたドキュメントにより、先行記事で未検証だった 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 とは
AggregationExpression に by 句を付けると、クエリ結果がグループ化され、各グループが「contributor」として独立して閾値評価されます。例えば count(*) by serviceName なら、serviceName値ごとにカウントが計算されます。閾値条件を満たしたcontributorがALARM判定となり、通知もcontributor単位で発火します。
公式ドキュメントに記載されている制約は以下のとおりです。
- BY句に指定できるフィールド数: 最大5
- 1クエリあたりのcontributor数: 最大500
- アラームが追跡するcontributor数: 最大100
検証: 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」でした。serviceName と environment の組み合わせが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:StartQuery、logs:StopQuery、logs: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 ofQueryResultsToEvaluate(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 serviceName や avg(duration) by endpoint のように指定すると、サービス名やエンドポイントごとに独立して閾値評価されます。閾値条件を満たしたcontributor単位で通知されることを確認しました。
これにより、複数サービスや複数エンドポイントを1つのLog Based Alarmで横断的に監視できます。通知に含まれる AlarmContributorAttributes から対象グループを確認でき、本検証の範囲ではCloudFormationでも同様に作成できました。
Multi-contributor Alarmでは、同じBY句アラーム内のcontributorに共通の閾値が適用されます。そのため、同じ閾値で評価できるグループはBY句アラームに集約し、閾値を分けたい対象は別アラームとして定義する、という使い分けが考えられます。







