CloudWatchの新機能「Log Based Alarm」でLogs Insightsクエリ結果をアラーム化してみた
はじめに
2026年6月29日、CloudWatchに新しいアラームタイプ「Log Based Alarm」が追加されました。AWS CLI v2のChangelogには以下の記載があります。
2.35.12
api-change:
cloudwatch: This release adds the API (PutLogAlarm) to manage a new CloudWatch resource, Log Based Alarms. Log Based Alarms allows customers to alarm directly on CloudWatch Logs query results.https://raw.githubusercontent.com/aws/aws-cli/v2/CHANGELOG.rst
PutLogAlarm のCLIリファレンスは以下で公開されています。
従来、CloudWatch Logsのログ内容に基づくアラームにはメトリクスフィルター経由のカスタムメトリクス作成が必要でした。Log Based Alarmではこれが不要になり、Logs Insightsクエリで抽出・加工した結果を AggregationExpression で集約し、その値を直接アラーム評価に利用できます。従来方式との主な違いは以下の通りです。
| 項目 | 従来(メトリクスフィルター + MetricAlarm) | 新(Log Based Alarm) |
|---|---|---|
| 設定手順 | メトリクスフィルター作成 → メトリクス確認 → アラーム作成 | PutLogAlarm 1 API コールで完結 |
| クエリの柔軟性 | 固定パターンマッチのみ | Logs Insights クエリによるフィルタ・フィールド加工 |
| 通知にログ行を含む | 不可 | ActionLogLineCount で最大50行 |
| Logs Insights リンク | なし | 通知にクエリ結果の直リンクを含む |
| 評価方式 | EvaluationPeriods / DatapointsToAlarm | QueryResultsToEvaluate / QueryResultsToAlarm |
| Chatbot 対応 | ○ | ×(2026-06-30 時点) |
| コスト | メトリクスフィルター: 無料 / カスタムメトリクス: $0.30/月 / アラーム: $0.10/月 | アラーム: $0.10/月 + Logs Insights クエリ: $0.005/GB scanned |
Log Based Alarm の仕組み
Log Based Alarmは「クエリ定期実行 → 結果集約 → 閾値評価」のパイプラインで動作します。
スケジュールドクエリ
PutLogAlarmを実行すると、CloudWatch LogsにScheduled Queryが自動作成されます。指定したスケジュール(例: rate(5 minutes))でLogs Insightsクエリが定期実行され、結果がアラーム評価に使われます。
クエリの対象時間範囲は StartTimeOffset と EndTimeOffset で制御します。
AggregationExpression
クエリ結果を単一の数値に集約する式です。count(*), sum(fieldName), avg(fieldName), min(fieldName), max(fieldName) のいずれかの関数を指定します。この集約結果が閾値と比較されます。
M-of-N 評価
QueryResultsToEvaluate(直近N回のクエリ結果を評価対象とする)と QueryResultsToAlarm(そのうちM回が閾値条件を満たすとALARM)で評価ロジックを制御します。
検証: アラーム作成
実際にPutLogAlarmでアラームを作成します。
IAM ロールの準備
Log Based Alarmにはスケジュールドクエリ実行用のIAMロールが必要です。logs.amazonaws.com と cloudwatch.amazonaws.com の両方を信頼する必要があります。
aws iam create-role \
--role-name "log-alarm-query-role" \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"Service": "logs.amazonaws.com"},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {"Service": "cloudwatch.amazonaws.com"},
"Action": "sts:AssumeRole"
}
]
}'
インラインポリシーで対象ロググループへのクエリ権限を付与します。
aws iam put-role-policy \
--role-name "log-alarm-query-role" \
--policy-name "LogAlarmQueryPermissions" \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:StartQuery",
"logs:GetQueryResults",
"logs:StopQuery",
"logs:FilterLogEvents",
"logs:GetLogEvents"
],
"Resource": "arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws/ecs/your-app:*"
}
]
}'
PutLogAlarm の実行
aws cloudwatch put-log-alarm \
--alarm-name "timeout-log-alarm" \
--alarm-description "ECS timeout errors - 5min aggregation, threshold 20" \
--scheduled-query-configuration '{
"QueryString": "filter @message like /timeout request to/",
"LogGroupIdentifiers": ["/aws/ecs/your-app"],
"ScheduledQueryRoleARN": "arn:aws:iam::123456789012:role/log-alarm-query-role",
"ScheduleConfiguration": {
"ScheduleExpression": "rate(5 minutes)",
"StartTimeOffset": 360,
"EndTimeOffset": 60
},
"AggregationExpression": "count(*)"
}' \
--action-log-line-count 10 \
--action-log-line-role-arn "arn:aws:iam::123456789012:role/log-alarm-query-role" \
--actions-enabled \
--alarm-actions "arn:aws:sns:ap-northeast-1:123456789012:your-alarm-topic" \
--ok-actions "arn:aws:sns:ap-northeast-1:123456789012:your-alarm-topic" \
--query-results-to-evaluate 1 \
--query-results-to-alarm 1 \
--threshold 20.0 \
--comparison-operator "GreaterThanThreshold" \
--treat-missing-data "notBreaching" \
--region ap-northeast-1
主要なパラメータ:
QueryString: Logs Insightsクエリ。ログの絞り込みやフィールド定義を記述します(最終的な数値集約はAggregationExpressionで指定)LogGroupIdentifiers: クエリ対象のロググループScheduleExpression: クエリの実行間隔StartTimeOffset/EndTimeOffset: 実行時刻からの相対秒数でクエリ対象時間範囲を指定。今回は360/60を指定しているため、実行時刻の6分前〜1分前の5分間が評価対象になりますAggregationExpression: クエリ結果の集約関数ActionLogLineCount: アラーム通知に含めるログ行数(最大50)QueryResultsToEvaluate/QueryResultsToAlarm: M-of-N評価のNとM
スケジュールドクエリの自動作成確認
作成後、describe-alarms でScheduled QueryのARNを確認できます。
aws cloudwatch describe-alarms \
--alarm-names "timeout-log-alarm" \
--region ap-northeast-1
:::detailsレスポンス(LogAlarmsセクション)
{
"LogAlarms": [
{
"AlarmName": "timeout-log-alarm",
"AlarmArn": "arn:aws:cloudwatch:ap-northeast-1:123456789012:alarm:timeout-log-alarm",
"AlarmDescription": "ECS timeout errors - 5min aggregation, threshold 20",
"ActionsEnabled": true,
"OKActions": ["arn:aws:sns:ap-northeast-1:123456789012:your-alarm-topic"],
"AlarmActions": ["arn:aws:sns:ap-northeast-1:123456789012:your-alarm-topic"],
"InsufficientDataActions": [],
"StateValue": "INSUFFICIENT_DATA",
"ScheduledQueryConfiguration": {
"QueryString": "filter @message like /timeout request to/",
"LogGroupIdentifiers": ["/aws/ecs/your-app"],
"QueryARN": "arn:aws:logs:ap-northeast-1:123456789012:scheduled-query:e026155f-ae01-4d43-bde5-024d4ea39f45",
"ScheduledQueryRoleARN": "arn:aws:iam::123456789012:role/log-alarm-query-role",
"ScheduleConfiguration": {
"ScheduleExpression": "rate(5 minutes)",
"StartTimeOffset": 360,
"EndTimeOffset": 60
},
"AggregationExpression": "count(*)"
},
"QueryResultsToEvaluate": 1,
"QueryResultsToAlarm": 1,
"Threshold": 20.0,
"ComparisonOperator": "GreaterThanThreshold",
"TreatMissingData": "notBreaching",
"ActionLogLineCount": 10,
"ActionLogLineRoleArn": "arn:aws:iam::123456789012:role/log-alarm-query-role"
}
]
}
:::
describe-alarms のレスポンスは従来の MetricAlarms とは別に、LogAlarms キーで返されます。
検証: アラーム発火と通知確認
スケジュールドクエリが実行されると、対象ロググループに対してLogs Insightsクエリが走ります。今回の検証では、対象ロググループに実際に存在するタイムアウトログが34件マッチしました。閾値20を超えたためALARMに遷移しています。
StateReason: "Threshold Crossed: 1 out of the last 1 query results [34.0 (30/06/26 11:43:54)]
was greater than the threshold (20.0)
(minimum 1 datapoint for OK -> ALARM transition)."
SNS 通知の内容
ALARM発火時のSNSメッセージには、従来のMetricAlarmにはない以下のフィールドが含まれます。
{
"AlarmName": "timeout-log-alarm",
"NewStateValue": "ALARM",
"NewStateReason": "Threshold Crossed: 1 out of the last 1 query results [34.0 (30/06/26 11:43:54)] was greater than the threshold (20.0) ...",
"LogGroups": ["/aws/ecs/your-app"],
"QueryString": "filter @message like /timeout request to/",
"AggregationExpression": "count(*)",
"QueryExecutionId": "627920a2-af1e-4d79-a866-04488dbebd55"
}
従来のMetricAlarmメッセージにある Trigger フィールドは含まれず、代わりにLog Alarm固有のフィールドが追加されています。
ActionLogLineCount によるログ行の同梱
Email通知に含まれたログ行は以下です。
Log Lines:
2026-06-30 11:41:59.111 timeout request to https://example.cloudfront.net/spaces/.../entries?...
2026-06-30 11:38:44.108 timeout request to https://example.io/api/stats/user-30.json.gz
2026-06-30 11:38:44.008 timeout request to https://example.io/api/stats/user-29.json.gz
2026-06-30 11:38:43.908 timeout request to https://example.io/api/stats/user-28.json.gz
2026-06-30 11:38:43.808 timeout request to https://example.io/api/stats/user-27.json.gz
2026-06-30 11:38:43.708 timeout request to https://example.io/api/stats/user-26.json.gz
2026-06-30 11:38:43.608 timeout request to https://example.io/api/stats/user-25.json.gz
2026-06-30 11:38:43.508 timeout request to https://example.io/api/stats/user-24.json.gz
2026-06-30 11:38:43.408 timeout request to https://example.io/api/stats/user-23.json.gz
2026-06-30 11:38:43.308 timeout request to https://example.io/api/stats/user-22.json.gz
Email通知にはLogs Insightsクエリ結果への直リンクも含まれます。
View query results in Logs Insights:
https://ap-northeast-1.console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#logsV2:logs-insights$3FqueryId$3D627920a2-af1e-4d79-a866-04488dbebd55
検証: EventBridge 連携
Log Based Alarmの状態変更もEventBridgeでキャプチャできます。イベントパターンは通常のCloudWatch Alarmと同じ CloudWatch Alarm State Change です。
aws events put-rule \
--name "log-alarm-state-change-capture" \
--event-pattern '{
"source": ["aws.cloudwatch"],
"detail-type": ["CloudWatch Alarm State Change"],
"resources": ["arn:aws:cloudwatch:ap-northeast-1:123456789012:alarm:timeout-log-alarm"]
}' \
--state ENABLED \
--region ap-northeast-1
キャプチャしたイベントの構造は以下の通りです。
EventBridgeイベント(OK → ALARM遷移)
{
"version": "0",
"id": "a644916b-0f3e-7687-4a60-3e0b6b639f81",
"detail-type": "CloudWatch Alarm State Change",
"source": "aws.cloudwatch",
"time": "2026-06-30T12:13:00Z",
"region": "ap-northeast-1",
"resources": [
"arn:aws:cloudwatch:ap-northeast-1:123456789012:alarm:timeout-log-alarm"
],
"detail": {
"alarmName": "timeout-log-alarm",
"state": {
"value": "ALARM",
"reason": "Threshold Crossed: 1 out of the last 1 query results [34.0] was greater than the threshold (20.0)...",
"timestamp": "2026-06-30T12:13:00.795+0000"
},
"previousState": {
"value": "OK",
"reason": "...",
"timestamp": "2026-06-30T12:12:51.478+0000"
},
"configuration": {
"logGroupIdentifiers": ["/aws/ecs/your-app"],
"queryString": "filter @message like /timeout request to/",
"aggregationExpression": "count(*)",
"scheduledQueryRoleARN": "arn:aws:iam::123456789012:role/log-alarm-query-role",
"actionLogLineRoleArn": "arn:aws:iam::123456789012:role/log-alarm-query-role",
"actionLogLineCount": 10,
"schedule": {
"expression": "rate(5 minutes)",
"startTimeOffset": 360,
"endTimeOffset": 60
},
"threshold": 20.0,
"comparisonOperator": "GreaterThanThreshold",
"treatMissingData": "notBreaching",
"queryResultsToEvaluate": 1,
"queryResultsToAlarm": 1
}
}
}
detail.configuration にLog Alarm固有のフィールド(logGroupIdentifiers, queryString, aggregationExpression, schedule 等)が含まれます。
応用: Logs Insights 関数との組み合わせ
Log Based Alarm の AggregationExpression は、QueryString 内で fields や parse を使って定義した数値フィールドを sum(), avg(), min(), max() で参照できます。parse で文字列として抽出した値を数値集約する場合は toNumber() で変換します。2026年5〜6月に追加された Logs Insights の新関数(if, toNumber, isPrivateIP 等)と組み合わせると、単純なカウントだけでなく比率や重み付けスコアでのアラームが実現できます。
比率アラーム: タイムアウト率が閾値を超えたら発火
if 関数でマッチした行を 1、それ以外を 0 としてフラグ化し、AVG で比率を算出します。
aws cloudwatch put-log-alarm \
--alarm-name "timeout-ratio-alarm" \
--alarm-description "Timeout ratio exceeds 50% of all log lines" \
--scheduled-query-configuration '{
"QueryString": "fields if(@message like /timeout request to/, 1, 0) as is_timeout",
"LogGroupIdentifiers": ["/aws/ecs/your-app"],
"ScheduledQueryRoleARN": "arn:aws:iam::123456789012:role/log-alarm-query-role",
"ScheduleConfiguration": {
"ScheduleExpression": "rate(5 minutes)",
"StartTimeOffset": 360,
"EndTimeOffset": 60
},
"AggregationExpression": "avg(is_timeout)"
}' \
--actions-enabled \
--query-results-to-evaluate 1 \
--query-results-to-alarm 1 \
--threshold 0.5 \
--comparison-operator "GreaterThanThreshold" \
--treat-missing-data "notBreaching" \
--region ap-northeast-1
実際に作成したアラームの評価結果は以下でした。
StateReason: "Threshold Crossed: 1 out of the last 1 query results [0.03333333333333333 (30/06/26 12:58:25)]
was not greater than the threshold (0.5)
(minimum 1 datapoint for INSUFFICIENT_DATA -> OK transition)."
評価対象期間のクエリ結果行のうち、タイムアウトの比率が約3.3%と算出され、閾値50%を下回っているためOK状態です。avg(is_timeout) がクエリ結果の各行の is_timeout フィールド(0 or 1)を平均し、比率として評価していることが確認できました。
重み付けスコア: 重大度に応じたアラーム
case 関数(2026年5月追加)で多分岐のスコアリングができます。if のネストより可読性が高くなります。
aws cloudwatch put-log-alarm \
--alarm-name "severity-score-alarm" \
--alarm-description "Weighted severity score exceeds threshold" \
--scheduled-query-configuration '{
"QueryString": "fields case(@message like /timeout/, 2, @message like /error/, 1, 0) as severity_score",
"LogGroupIdentifiers": ["/aws/ecs/your-app"],
"ScheduledQueryRoleARN": "arn:aws:iam::123456789012:role/log-alarm-query-role",
"ScheduleConfiguration": {
"ScheduleExpression": "rate(5 minutes)",
"StartTimeOffset": 360,
"EndTimeOffset": 60
},
"AggregationExpression": "avg(severity_score)"
}' \
--actions-enabled \
--query-results-to-evaluate 1 \
--query-results-to-alarm 1 \
--threshold 1.0 \
--comparison-operator "GreaterThanThreshold" \
--treat-missing-data "notBreaching" \
--region ap-northeast-1
case(条件1, 値1, 条件2, 値2, ..., デフォルト値) の構文で、最大10分岐まで指定できます。
その他の組み合わせパターン
| ユースケース | QueryString | AggregationExpression |
|---|---|---|
| レスポンスタイム平均 | parse @message /took (?<ms>\d+)ms/ | fields toNumber(ms) as rt |
avg(rt) |
| 遅いリクエストの比率 | fields if(toNumber(response_time) > 1000, 1, 0) as is_slow |
avg(is_slow) |
| 外部IPアクセス比率 | fields if(isPrivateIP(src_ip), 0, 1) as is_external |
avg(is_external) |
| 巨大ログ行の検知 | fields if(strlen(@message) > 10000, 1, 0) as is_oversized |
sum(is_oversized) |
ポイントは、QueryString で stats を使わず fields でフィールドを定義することです。stats で集約した結果フィールドは AggregationExpression から参照できません。
注意事項
AggregationExpression の制約
AggregationExpression には集約関数を直接指定します。使用可能な関数は count(*), sum(fieldName), avg(fieldName), min(fieldName), max(fieldName) です。
fields や parse で定義したフィールドは参照可能ですが、QueryString 内で stats を使って集約したフィールドは参照できません。
# NG: QueryString に stats を含め、AggregationExpression でフィールド参照
QueryString: "filter @message like /error/ | stats count(*) as errorCount"
AggregationExpression: "errorCount"
# OK: QueryString はフィルタのみ、集約は AggregationExpression で
QueryString: "filter @message like /error/"
AggregationExpression: "count(*)"
# OK: fields で定義したフィールドを AggregationExpression で集約
QueryString: "fields if(@message like /error/, 1, 0) as is_error"
AggregationExpression: "avg(is_error)"
AWS Chatbot 未対応(2026-06-30 時点)
Log Based AlarmのSNSメッセージは従来のMetricAlarmと形式が異なるため(前述の通り Trigger フィールドがなく、Log Alarm固有のフィールドで構成)、AWS Chatbotが対応していない可能性があります。検証ではSNS Publishは成功しましたがSlackへの通知は表示されませんでした。
Chatbot経由でSlackに通知したい場合は、EventBridge → Lambdaでメッセージをカスタム通知フォーマットに加工してSNSにPublishする構成をお試しください。
EventBridge ターゲットのリソースベースポリシー
EventBridgeのターゲットにCloudWatch Logsを指定する場合は、ロググループにリソースベースポリシーが必要です。events.amazonaws.com に対して logs:CreateLogStream と logs:PutLogEvents を許可してください。
まとめ
Log Based Alarmにより、CloudWatch Logsの監視設定を大幅にシンプルにできるようになりました。メトリクスフィルターを作成せずに、Logs Insightsクエリによるフィルタやフィールド加工と AggregationExpression による集約を組み合わせて、ログ検索結果を直接アラーム条件として扱えます。
今回の検証では、単純なカウント閾値だけでなく、if / case / toNumber / isPrivateIP などの関数を使うことで、タイムアウト率、重大度スコア、レスポンスタイム平均といった比率や加重値ベースのアラームも表現できることを確認しました。従来はメトリクスフィルター、カスタムメトリクス、MetricAlarmを組み合わせたり、Lambdaで条件判定していた構成を、より少ない設定で実現できます。
通知面では、ActionLogLineCount によってマッチしたログ行を含められる点と、Logs Insightsクエリ結果への直リンクが含まれる点が便利です。EventBridge連携も従来のアラームと同じイベントパターンで利用できました。
現時点ではAWS Chatbotへの直接通知には制約があり、AggregationExpression の使い方にも注意点はありますが、ログ内容に基づくアラームをシンプルに作成したい場面では有力な選択肢になりそうです。








