こんにちは。アプリケーションサービス部の居石です。
Amazon CloudWatch メトリクスの欠落データ発生時に、Amazon CloudWatch Alarm(以下、CloudWatch Alarmと記載)のアラーム通知が指定の時間より発報が遅れてしまいます。
メトリクス数式を使用してこの問題を対処しました。
背景
S3バケットに継続的にファイルをアップロードするアプリケーションがあり、アップロードが滞っていないことを監視する必要がありました。 S3バケットへのPUTリクエスト(=アップロード)数を監視するために、PutRequestsを利用してCloudWatch Alarmを作成しました。
PutRequestsについて
PutRequestsとは、S3 バケットへのPUTリクエスト(=アップロード)数を取得可能な、リクエストメトリクスのことです。
以下の画像から、S3 バケットへのアップロードが0件のとき、Countが0のプロットがなく、S3のPutRequestsが0の場合はメトリクスを出力しないことがわかります。

CloudWatch Alarmでは、S3バケットへのPUTリクエスト数が0件のとき、PutRequests=0というデータポイントがプロットされるのではなく、データが欠損してしまうようです。 アラーム状態にするには、「欠落データを不正 (しきい値を超えている)として処理」という設定が必要になります。
監視周期を1時間にしているにもかかわらず、アラーム発報はS3へのアップロードが0件であったデータポイントから3時間後でした。
欠落データ発生時のCloudWatch Alarmの挙動
公式ドキュメントによるとデータが欠落した場合のアラーム状態の評価方法は以下のようになります。
アラームが状態を変更するかどうかを評価するたびに、CloudWatch は [Evaluation Periods (評価期間)] に指定されている数よりも多くのデータポイントを取得しようとします。取得を試みるデータポイントの正確な数は、アラーム期間の長さと、基づいているメトリクスが標準解像度か高解像度かによって異なります。取得を試みるデータポイントのタイムフレームは評価範囲です。
欠落データがあった場合、CloudWatch Alarm側ではアラームが状態を変化するか評価するために、指定されている期間よりも多くデータポイント取得しようとします。
監視周期1時間、評価期間1とした場合、1データポイントで判断し1時間後にアラーム発報が行われますが、欠落データが発生したときは1データポイントより多くのデータポイントを取得しアラーム発報するか判断するため、通常よりアラーム発報まで時間を要しているようです。
今回は監視周期1時間、評価期間1で指定しておりましたが、アラーム発報までに3時間を要したことから、CloudWatch Alarmの仕様で、3つのデータポイントを評価してからアラーム状態に遷移しアラームが発報されたと推測されます。
取得を試みるデータポイントの正確な数は、アラーム期間の長さと、基づいているメトリクスが標準解像度か高解像度かによって異なり、算出方法等については公開されていないそうです。
メトリクス数式を使ってみる
上記の欠落データが発生したときにアラーム発報までに時間を要する問題をメトリクス数式を使用して対処しました。
メトリクス数式とはCloudWatch メトリクスに対して使用できる数式です。メトリクスに数式を使用して新しいメトリクスを作成できます。
今回はFILL 関数を使用することで欠落データ部分を明示的に 0 として補完できるため、アラーム発報の遅延を回避できます。
マネジメントコンソールから作成
CloudWatch コンソールを開き「すべてのアラーム」を選択し、「アラームを作成」を押下します。

「メトリクスの選択」を押下し、画面遷移後、該当のメトリクスにチェックをいれます。「メトリクスを選択」→「次へ」を押下します。

アクションの設定では以下のように設定します。

作成したアラームの「表示」→「メトリクス内」を押下します。

「数式を追加」→「すべての関数」→「FILL」を選択します。

ラベルが
式1の方の鉛筆マークを押下し、数式を編集します。
ラベルが
式1の方のベルマークを押下し、アラームを作成します。
設定が期待通りか確認します。

CloudFormationから作成
Resources:
AlarmforS3:
Type: AWS::CloudWatch::Alarm
Properties:
ActionsEnabled: true
AlarmActions:
- arn:aws:sns:${aws:region}:${aws:accountId}:sns-error-topic
AlarmDescription: S3の1時間あたりのアップロード数が1に満たない場合に通知
AlarmName: cloudwatch-alarm-PutRequests
ComparisonOperator: LessThanThreshold
DatapointsToAlarm: 1
EvaluationPeriods: 1
Threshold: 1
TreatMissingData: breaching
Metrics:
- Expression: FILL(m1, 0)
Id: e1
Label: fixed_PutRequests
ReturnData: true
- Id: m1
Label: PutRequests
MetricStat:
Metric:
MetricName: PutRequests
Dimensions:
- Name: BucketName
Value: cloudwatchalarm-s3
- Name: FilterId
Value: logs
Namespace: AWS/S3
Period: 3600
Stat: Sum
ReturnData: false
さいごに
メトリクス数式を使用すると、CloudWatch Alarmの通知をカスタマイズできることを知りました。 何かの役に立てば幸いです。