CloudWatch Alarm に曜日・時間帯によって変わる閾値を設定する

こんにちは、masm11 です。

AWS の CloudWatch には、CloudWatch Alarm という機能がありますよね。 弊社でも使っています。私も設定しました。

ただ、監視したい値は、曜日や時間帯によって異なる設定にしてあります。 そして、ご存知かと思いますが、CloudWatch Alarm では時刻は UTC のみなのです。

設定を任されましたが、大変でした。

今回の記事では、以下の仕様をどう解りやすく設定するかを説明します。

曜日 8:10〜20:00 20:00〜翌8:10
月〜金 3以上 2以上
土日 2以上 2以上

なお、今回掲載したグラフはすべて、横軸は JST となっています。

CloudWatch Alarm を設定する

とりあえず、曜日や時間帯は無視して、設定の仕方を説明します。

設定は CloudWatch の「すべてのメトリクス」で行います。

監視したいメトリクスを検索して、チェックボックスにチェックを入れると、 グラフが表示されます。

「グラフ化したメトリクス」タブに移動します。

式を追加してみます。「数式を追加」から「空の式ではじまる」を選択すると、 式を入力できます。ここに IF(m1 < 3, 1, 0) と入力します。

すると ID が e1 で、詳細が今入力した式になりました。 最初に選択したメトリクスは m1 になっています。 e1 は、m1 < 3 の場合は 1、そうでなければ 0、という意味になります。

あとは、ID が e1 の行の右の方にあるベルのアイコンをクリックすれば、 Alarm を作成できます。e1 >= 1 の場合は通知する、と設定するわけです。

ここからの話としては、この m1 < 33 の部分を曜日や時間帯によって 変えたい、という話になります。

e1: 時刻を扱いやすくする

みなさんは、1日が 24x60=1440分 であることはご存知ですよね。

では、現在の時(HH)と分(MM)が与えられた時に、 その時刻が 8:10〜20:00 の間かどうかを どのように式で表現しますか?

  • HH が 8 未満の場合は false
  • HH が 8 の場合は、MM が 10 までは false、10 を超えたら true
  • HH が 9〜19 の場合は true
  • HH が 20 以上の場合は false

式でもっと簡潔に表現したいですね。

HH * 60 + MM >= 8 * 60 + 10 && HH * 60 + MM < 20 * 60

こんな感じでしょうか? いえ、真面目すぎます。もっと簡単にしましょう。

HH * 100 + MM >= 0810 && HH * 100 + MM < 2000

いかがでしょうか? 60倍でなく 100倍にすることで、 8:10 や 20:00 を直感的に 0810 や 2000 と書けました。

さて、 CloudWatch Metrics では HOUR(m1)MINUTE(m1) と書くことで、 m1 の各データの時や分を取り出すことができます。 なので、

HOUR(m1) * 100 + MINUTE(m1)

この式を e1 として登録しておけば、時刻が扱いやすくなります。

e2: 曜日も入れてしまう

e1 の考え方は解りました。 今回は曜日によっても変えたいので、 更に進めて曜日も入れてしまいます。

DAY(m1) と書くことで、m1 の各データの曜日を 1〜7 で取り出すことができます。 1は月曜、7は日曜です。

なので、e2 として、

DAY(m1) * 10000 + HOUR(m1) * 100 + MINUTE(m1)

を登録します。月曜 23:45 は 12345 という数値になります。

e3: 日中の期待値

次は、日中の期待値を式で表現します。これは曜日によって異なります。

e2 を使えばできそう、というのはお分かりかと思いますが、 e1 や e2 が UTC であることに注意が必要です。

  • 土曜 0時 JST = 金曜 15時 UTC = 51500
  • 月曜 0時 JST = 日曜 15時 UTC = 71500

なので、

IF(51500 <= e2 AND e2 < 71500, 2, 3)

と書けば、土曜と日曜は日中の期待値が 2、それ以外の曜日は日中の期待値が 3 となります。

e4: 現在の期待値

e3 は日中の期待値です。一方、夜間は 2 固定の仕様です。

現在の期待値としては、日中(8:10〜20:00)は e3、夜間(20:00〜8:10)は 2 です。 これを式にします。

曜日なしの時刻は e1 を見ればいいのですが、ここでも UTC であることに注意が必要です。

  • 8:10 JST = 23:10 UTC
  • 20:00 JST = 11:00 UTC

ですので、

IF(2310 <= e1 OR e1 < 1100, e3, 2)

となります。AND ではありません、OR です。 JST で「8:10〜20:00」は、 UTC では「23:10 以降 (24時まで)、または、(0時以降) 11時まで」です。

これで、日中は e3、夜間は 2 の式ができあがりました。

e5: アラームステータス

やっと期待値が出ましたので、実際の値がこれを下回っていたら 1、 大丈夫なら 0 の式を作ります。ここまで来たら簡単ですね。e5 は

IF(m1 < e4, 1, 0)

となります。

この e5 を使ってアラームを設定して完了となります。

まとめ

e1 と e2 の考え方さえできれば、あとは自由自在かと思います。JST→UTC が面倒ですが。

それぞれの式に対応するグラフを貼り付けてありますので、参考にしていただけたら、と思います。

うまくやれば JST で表現できるのでは、と思いましたが、そこまではできませんでした。

また、m1 や e1〜e5 はこの場限りの変数ですので、いくらでも作り直しが効きます。 Alarm として設定しても、Alarm に情報として残ってはいますが、 複数の Alarm に重複して存在して大丈夫なはずです。 どんどん試してみましょう。

インゲージでは、こんなこともサクサクこなせるエンジニアも募集しています。 詳細は以下のページからお願いします。

https://ingage.co.jp/recruit/