Azure Monitor のログアラートの対象ログを入手する (つまづき編)

# つまづいた... :scream:

[前回の投稿](https://qiita.com/tetsuya-ooooo/items/574526a4e6bda9a9ed2c)では、発報されたログアラートの対象ログを取得する方法について書きました。

今回は、つまづいたポイントを紹介します。


# (1) ログクエリが不正？

## 検証ログアラートルール

[前回の投稿](https://qiita.com/tetsuya-ooooo/items/574526a4e6bda9a9ed2c)の下図のログアラートルールを使います。

[ディメンションで分割する] の [リソース ID 列] で ```_ResourceId``` を指定し、 ```Computer``` と ```RenderedDescription``` で分割します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/a729482e-4885-91a2-7102-ad8e318875ff.png)


## 現象

仮想マシンで以下のようなイベントログを出力しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/122a8755-426c-c40e-9b2b-5527eb2bcf45.png)

そして、発報されたアラートの「アラート詳細」の [Filtered search results] の [View query results] リンクをクリックすると、下図のようにログクエリが失敗してしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/f12a4e5c-3967-15fb-799b-d3c276627a2c.png)

「うまくパースできなかった」と言っているようですね... :cold_sweat:

> Query could not be parsed at 'C' on line [11,114]
> 
> Token: C
> Line: 11
> Position: 114

## 原因

[前回の投稿](https://qiita.com/tetsuya-ooooo/items/574526a4e6bda9a9ed2c#%E3%83%AD%E3%82%B0%E3%82%A2%E3%83%A9%E3%83%BC%E3%83%88%E3%81%AE%E5%AF%BE%E8%B1%A1%E3%83%AD%E3%82%B0%E3%82%92%E5%8F%96%E5%BE%97)では、「[Filtered search results] では、ログクエリにディメンション分割で指定されたカラムの値で絞り込む条件 (赤枠の部分) が追加される」と説明しました。追加される条件は、ディメンション分割で指定されたカラムを文字列に変換し、それらのカラムの値を文字列リテラルで示し、等しいかと問い合わせています。

エラーとなっているのは、**文字列リテラルの「ディメンション分割で指定されたカラムの値」に不正な文字 (エンコードが必要な文字) が含まれている**ためです。よって、この部分について対処する必要があります。

```:エラーが発生している部分 (改修前)
| where
 tostring(Computer) == 'vm-202301' and
 tostring(RenderedDescription) == 'No files exist in '
C : \temp''
```


## 対処

このエラーを対処するのに、アラートルールの「ログクエリ」と「ディメンション分割」を改修します。

文字列リテラルの「ディメンション分割で指定されたカラムの値」は、シングルクォーテーションで囲まれています。以下のドキュメントを参考に対処方法を考えます。

https://learn.microsoft.com/ja-jp/azure/data-explorer/kusto/query/scalar-data-types/string?WT.mc_id=AZ-MVP-5003113#string-literals


### アラートルールのログクエリ

まず、ログクエリを以下のように改修しました。

ディメンション分割で指定されたカラム ```RenderedDescription``` に不正な文字が含まれているので、このカラム値に対して置換を施し、ディメンション分割で指定するためのカラムを別途設けることにしました。

```:改修したログクエリ
Event
| where EventLog == "Application"
| where EventLevel == 1 or EventLevel == 2
| extend dimension_RenderedDescription =
    replace_string(replace_regex(RenderedDescription, '[\'\t\n\r]', ''), '\\', '/')
| project 
    TimeGenerated,
    Computer,
    RenderedDescription,
    dimension_RenderedDescription,
    EventLog,
    EventLevel,
    EventID,
    _ResourceId
```

(繰り返しになりますが)「ディメンション分割で指定されたカラムの値」は文字列リテラルで示されます。そのため、**そのまま文字列リテラルで示されても問題ない値** にしなければなりません。

[前述のドキュメントの「文字列リテラル」](https://learn.microsoft.com/ja-jp/azure/data-explorer/kusto/query/scalar-data-types/string?WT.mc_id=AZ-MVP-5003113#string-literals)を参考に、以下の文字を別の文字に置換することにしました。

| 置換前の文字 | 置換後の文字 |
|:-|:-|
| シングルクォーテーション (```\'```) | 空文字 (```''```) |
| タブ (```\t```) | 空文字 (```''```) |
| 改行 newline (```\n```) | 空文字 (```''```) |
| 戻り return (```\r```) | 空文字 (```''```) |
| バックスラッシュ (```\\```) | スラッシュ (```/```) |

```:ディメンション分割用のカラムを設ける
| extend dimension_RenderedDescription =
    replace_string(replace_regex(RenderedDescription, '[\'\t\n\r]', ''), '\\', '/')
```

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

https://learn.microsoft.com/ja-jp/azure/data-explorer/kusto/query/replace-regex-function?WT.mc_id=AZ-MVP-5003113

https://learn.microsoft.com/ja-jp/azure/data-explorer/kusto/query/replace-string-function?WT.mc_id=AZ-MVP-5003113

そして、クエリの実行結果に別途設けた ```dimension_RenderedDescription``` を追加します。

```:クエリの実行結果に出力するカラム
| project 
    TimeGenerated,
    Computer,
    RenderedDescription,
    dimension_RenderedDescription,
    EventLog,
    EventLevel,
    EventID,
    _ResourceId
```

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


### アラートルールのディメンション分割

次に、ディメンション分割で指定していたカラム ```RenderedDescription``` を先ほどのログクエリで別途設けた ```dimension_RenderedDescription``` に変更しました。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/0f34bf88-c5b5-68ca-1722-ef7688ab898f.png)


## 確認

ログクエリの実行結果を取得することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/aaacfa9e-9e7d-32c7-701e-dc6cb3e8b5f2.png)

エラーが発生していた部分は、以下のように改善されていました。

```:エラーが発生していた部分 (改修後)
| where
 tostring(Computer) == 'vm-202301' and
 tostring(dimension_RenderedDescription) == 'No files exist in C:/temp'
```


# (2) テーブルがない？

## 検証ログアラートルール

下図のログアラートルールを使います。

ターゲットリソースは、Log Analytics ワークスペースを指定しています。

[AppTraces](https://learn.microsoft.com/ja-jp/azure/azure-monitor/reference/tables/apptraces?WT.mc_id=AZ-MVP-5003113) テーブルに対するログクエリを用意し、[ディメンションで分割する] の [リソース ID 列] で ```_ResourceId``` を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/0b179f4d-2cfc-d7e6-ca92-b5afdd32a66c.png)


## 現象

発報されたアラートの「アラート詳細」の [Filtered search results] の [View query results] リンクをクリックすると、下図のようにログクエリが失敗してしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/c68379a4-8f7b-997b-5d2b-45d3b0cc9c33.png)

「AppTraces という名前のテーブルが見当たらない」と言っているようですね... :cold_sweat:

> 'where' operator: Failed to resolve table or column expression named 'AppTraces'


## 原因

[前回の投稿](https://qiita.com/tetsuya-ooooo/items/574526a4e6bda9a9ed2c#rest-api-%E3%81%8B%E3%82%89%E5%8F%96%E5%BE%97)で、「[ディメンションで分割する] の [リソース ID 列] で ```_ResourceId``` を指定すると、Azure リソースのログに対して直接クエリを実行することができる」と説明しました。

https://learn.microsoft.com/ja-jp/azure/azure-monitor/logs/api/azure-resource-queries?WT.mc_id=AZ-MVP-5003113

```_ResourceId``` が Application Insights リソースだと、アラート時の「影響を受けるリソース」もその Application Insights リソースとなり、その Application Insights リソースからクエリを実行することとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/4aa50c8b-29ad-b3e2-6f13-562d59df2a18.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/b97b7910-a8b3-f44b-ee8c-e69b3c6256c5.png)

ログは Log Analytics ワークスペースへ保存されているものの、Log Analytics ワークスペースでも、Application Insights リソースでも同じログを確認することができますが、それぞれのテーブル名やカラム名が異なるため、Log Analytics ワークスペースで成功しているクエリでも Application Insights リソースではそのクエリは失敗してしまいます。

https://learn.microsoft.com/ja-jp/azure/azure-monitor/app/convert-classic-resource?WT.mc_id=AZ-MVP-5003113#table-structure

- テーブル構造
Application Insights と Log Analytics ワークスペースでは、以下のようにテーブルが異なっています。
※各テーブルの説明は、上記のドキュメントをご参照ください。

| Application Insights<br/>のテーブル | Log Analytics ワークスペース<br/>のテーブル |
|:-|:-|
| availabilityResults | AppAvailabilityResults |
| browserTimings | AppBrowserTimings |
| dependencies | AppDependencies |
| customEvents | AppEvents |
| customMetrics | AppMetrics |
| pageViews | AppPageViews |
| performanceCounters | AppPerformanceCounters |
| requests | AppRequests |
| exceptions | AppExceptions |
| traces | AppTraces |


## 対処

このエラーを対処するのに、アラートルールを改修します。対処方法は以下のいずれかで行います。

1. [ターゲットスコープ] を「Application Insights」リソースを指定し、[ログクエリ] を Application Insights リソースから実行するのに適したものに変更する。 (テーブルを「AppTraces」→「traces」に変更するなど) 
1. [ディメンションで分割する] の [リソース ID 列] で「分割しない」を選択する。

ふたつ目のほうが影響が小さい (変更も少ない) ようなので、そちらの方法で対処しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/8d4b66f9-c8a3-c27f-d779-d25a454f2453.png)


## 確認

ログクエリの実行結果を取得することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/ffbc7dd3-eabc-ea8c-6b6c-6263832da836.png)


# まとめ

REST API で不具合が発生したら Azure ポータルで確認する術があるので、このようにトラブルシューティングすると良いですね。
早く改善してくれるとなお良いですけどね。