Azure Monitor でのステートフルなログアラート


# はじめに

ステートフルなログアラートについて、検証してみました。

ステートフルなログアラートは、1 年くらい前 (2021 年 4 月 28 日) に Public Preview されました。どのような機能なのかについては、まずは以下のアップデート情報をご覧ください。

https://azure.microsoft.com/ja-jp/updates/public-preview-stateful-and-1minute-frequency-log-alerts-in-azure-monitor/?WT.mc_id=AZ-MVP-5003113

> **ステートフル ログ アラート** - この機能が有効になっている場合、発行されたアラートは、条件が満たされなくなった時点で自動的に解決されます。これは、メトリック アラートの既定の動作に似ています。

この機能を使う機会があり、つまづいた (勘違いした？) こともあったため、どのように設定すれば「ステートフル」なログアラートを実現できるか、ここで共有できればと思います。

なお、こちらの機能はこの投稿を執筆している時点でも Public Preview です。よって、この投稿の内容は今後変更される可能性があります。


# ログアラートの状態と解決

ログアラートには、アラート ルールの条件を満すたびに発生する「ステートレス アラート」と、ある条件を満たすと自動で解決する「ステートフル アラート (今回検証するもの)」の 2 種類あります。

なお、「ステートフル アラート」は、**30 分間アラート ルールの条件を満たさず**、かつ **3 回連続してアラート ルールの条件を満たさない**場合、自動的に解決します。「ステートフル アラート」を設定するためには、「アラートを自動的に解決する」オプションを有効にします。

https://docs.microsoft.com/ja-jp/azure/azure-monitor/alerts/alerts-unified-log?WT.mc_id=AZ-MVP-5003113

このように読み解くと、何も考えずにログアラートが簡単にステートフルなものになると思えますが、ステートフルにするためにはひと工夫が必要です。


# 検証してみる

では、さっそく試してみます。

今回は 2 つのアラート ルールを比較します。どちらも検索クエリで抽出されたレコードが 1 件以上存在したらアラートを発報するものです。また、評価の頻度はどちらも「5 分置き」に設定します。

なお、ログのアラート ルールの作成、管理については、以下のドキュメントをご参照ください。

https://docs.microsoft.com/ja-jp/azure/azure-monitor/alerts/alerts-log?WT.mc_id=AZ-MVP-5003113

https://docs.microsoft.com/ja-jp/azure/azure-monitor/logs/get-started-queries?WT.mc_id=AZ-MVP-5003113


## アラート ルール (1) 測定でログ検索結果の件数を集計する

ひとつ目は、検索クエリ結果のレコードを「測定 (Measure)」で集計する方法です。
メジャーで「テーブルの行」、集計の種類で「カウント」を選択することによって、ログの検索結果の件数を集計します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/75bf42e9-339a-0430-1328-6c3a427a8075.png)

「ステートフル アラート」を使うためには、「アラートを自動的に解決する」オプションを有効にする必要があるので、アラート ルールの詳細セクションの「アラートを自動的に解決する」にチェックを付けます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/47a6c808-9876-911e-5f8c-6ec336ac37ce.png)


## アラート ルール (2) 検索クエリでログ検索結果の件数を集計する

ふたつ目は、検索クエリでログ検索結果の件数を集計する方法です。
検索クエリ内で集計関数 (ここでは Count) を使って、ログの検索結果の件数を集計します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/d1625c62-d577-5fe7-8756-f9e56bff3011.png)

前述と同様に、「アラートを自動的に解決する」にチェックを付けます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/e3d4b149-0b94-8b50-e8f8-52b056586b1c.png)

これでアラートを発報する準備が整いました。


## イベント ログを登録する

監視対象の Windows 仮想マシンで、以下のコマンドを実行してイベント ログを登録します。

```powershell
EVENTCREATE /ID 999 /L application /SO systeminfo /T ERROR /D "This is Test：テストです"
```

イベント ビューアーでも登録したイベント ログを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/3a5a3d63-f266-8c04-946c-8fb9ef782d14.png)

それでは、アラートが発報されるまで、しばらく待ちます。


## アラート受信 (1) Fired (発報)

アラート ルールの条件を満たした場合の通知 (Fired) が届きました。どちらも想定どおりですね。
以下に実際に届いた通知メール (一部) を貼っておきます。

- 【通知メール】アラート ルール (1) 測定でログ検索結果の件数を集計する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/fa3d5e40-acdc-7d4a-379a-9a0bd14cab70.png)

- 【通知メール】アラート ルール (2) 検索クエリでログ検索結果の件数を集計する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/a0d2dff2-6f20-a57e-d685-9961562ec290.png)


## アラート受信 (2) Resolved (解決済み)

しばらく経つと、解決済み (Resolved) の通知が届きました。ただ届いたのは「検索クエリでログ検索結果の件数を集計する」アラート ルールのほうのみでした。

- 【通知メール】アラート ルール (2) 検索クエリでログ検索結果の件数を集計する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/29f79342-28c4-159a-6fbd-c467e6456b04.png)

また、[ドキュメント](https://docs.microsoft.com/ja-jp/azure/azure-monitor/alerts/alerts-unified-log?WT.mc_id=AZ-MVP-5003113#state-and-resolving-alerts)に記載されている例のとおり、(評価の頻度が 5 分の場合) 40 分後に解決されました。

ちなみに、「測定でログ検索結果の件数を集計する」アラート ルールのほうは全然届きません。


## 2 つのアラートの状態を確認する

Azure ポータルで、それぞれのアラートの状態を確認すると、以下のように解決済みの通知を受け取った (2) のほうが「解決済み」となっていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/4fc3c94b-db7b-d6a7-71cf-57bfcd27349a.png)


# ステートフルなログアラートにするためのひと工夫

前述の 2 つのアラート ルール「測定でログ検索結果の件数を集計する」と「検索クエリでログ検索結果の件数を集計する」の違いは何でしょう。

アラートを解決するには、**「条件が満たされていないこと」** を明確に示す必要があります。
それではそれぞれのアラート ルールで用いた検索クエリに注目してみます。

- アラート ルール (1) 測定でログ検索結果の件数を集計するの「検索クエリ」

```
Event
| where EventID == 999
```

(1) のほうは、条件に該当するレコードが存在する場合は 1 件以上のレコードが検索結果として返ってきますが、存在しない場合は検索結果としては何も返ってきません (検索結果として「null」が返ってくる)。

- アラート ルール (2) 検索クエリでログ検索結果の件数を集計するの「検索クエリ」

```
Event
| where EventID == 999
| count
```

(2) のほうは、条件に該当するレコードの存在する場合は検索結果として「1」以上の値が返ってきます。また、存在しない場合は検索結果として「0」が返ってきます。要するに、こちらはどのような結果となっても検索結果として必ず値が返ってきます。

このように比較した結果、(2)のように「条件が満たされていないこと」を明示する必要があるということがわかります。


# まとめ

- ログアラートには「ステートレス アラート」と「ステートフル アラート」の 2 種類ある。
- 「ステートレス アラート」は、アラート ルールの条件を満すたびに発報する (Fired)。
- 「ステートフル アラート」は、アラート ルールの条件を満すと発報 (Fired) し、30 分間アラート ルールの条件を満たさず、かつ 3 回連続してアラート ルールの条件を満たさない場合、自動的に解決する (Resolved)。
- 「ステートフル アラート」を設定するためには、「アラートを自動的に解決する」オプションを有効にする。
- 「ステートフル アラート」を自動的に解決させるためには、「アラート ルールの条件が満たされていないこと」を明確に示す必要がある。


# その他の参考文献

以下のドキュメントもご参考ください。

https://docs.microsoft.com/ja-jp/azure/azure-monitor/alerts/alerts-log-query?WT.mc_id=AZ-MVP-5003113

https://docs.microsoft.com/ja-jp/azure/data-explorer/kusto/query/best-practices?WT.mc_id=AZ-MVP-5003113

https://docs.microsoft.com/ja-jp/azure/azure-monitor/best-practices?WT.mc_id=AZ-MVP-5003113

https://docs.microsoft.com/ja-jp/azure/azure-monitor/alerts/alerts-troubleshoot?WT.mc_id=AZ-MVP-5003113

https://docs.microsoft.com/ja-jp/azure/azure-monitor/alerts/alerts-troubleshoot-log?WT.mc_id=AZ-MVP-5003113

https://jpazmon-integ.github.io/blog/AzureMonitorEssential/HowMetricAlertisFired/