Posted at

DevOps のための Azure Application Insights クエリ(Kustoクエリ言語 - KQL) その2

DevOps のための Azure Application Insights クエリ(Kustoクエリ言語 - KQL) の続編です。

今回もrequestsテーブルからデータを抽出していきます。今回想定しているDevOpsシーンは、ログの特定のコラムの値を、重複なく羅列する場合です。例えば「いったいどの国からサービスへアクセスがあったのか?」といった疑問に答えたいような場合です。


リクエスト元のクライエントのジオ情報をざっくりみたい

リクエストがどの国の、どの地域の、どの町から来ているかを知りたいとします。まずはprojectで要らない情報を切り捨てましょう。

requests

| where timestamp > ago(24h)
| project client_CountryOrRegion, client_StateOrProvince, client_City

image.png


国のリストを見たい

重複を排除して24時間でどの国からリクエストがあったかを調べます。

requests

| where timestamp > ago(24h)
| summarize count() by client_CountryOrRegion
| project client_CountryOrRegion, count_

image.png

11か国ということでした。

国のリストだけでいいので、projectからcount_を取り除きます

requests

| where timestamp > ago(24h)
| summarize count() by client_CountryOrRegion
| project client_CountryOrRegion

image.png

ところで、値は空のものがあります。データとしては無意味なので、それをwhereandオペレーターを使って条件をもうひとつ付け足して、とりのぞきます。

requests

| where timestamp > ago(24h) and not(isempty(client_CountryOrRegion))
| summarize count() by client_CountryOrRegion
| project client_CountryOrRegion

image.png

isempt()関数で空かどうかをしらべ、not()関数で否定して値を逆にします。

これで、求めていた結果が出ました。


国のリストをJSON配列に変換したい

テーブルの状態ではなく、JSON配列の方が都合が良かったとします。

requests

| where timestamp > ago(24h) and not(isempty(client_CountryOrRegion))
| summarize count() by client_CountryOrRegion
| summarize makelist(client_CountryOrRegion)

image.png

再度summarizeしますが、今回はmakelist()関数を使ってJSON配列にしています。


count()関数を使わずに国のリストを得る

count()関数を使うとパフォーマンスが遅い可能性が高いです。数を数えるということは、O(n)の時間計算量(time complexity)になります。データが多いほど遅くなってしまいます。そこでおそらくはO(1)時間計算量(コンスタントでデータの量に影響されない)になるany()関数を使って以下のように最適化してみます。(実測はしていませんが、論理的には早くなるはずです)

requests

| where timestamp > ago(24h) and not(isempty(client_CountryOrRegion))
| summarize any(client_CountryOrRegion) by client_CountryOrRegion
| summarize makelist(client_CountryOrRegion)

image.png

any() 関数はグループ毎にレコードをひとつランダムに選んで、指定されたカラム、この場合はclient_CountryOrRegionを返します。any()関数のドキュメンテーションに記述されているとおり、どのレコードを選ぶかはランダムで、そのアルゴリズムも公開されていないので、結果は安定していません。


まとめ

ログ解析では時々、特定のカラムの別個の値をすべて知りたい状況が出来きます。例えば:


  • 先週サーバーが返した全ての Http ステータスの値

  • 全てのクライエントのブラウザの種類

  • アクセスがあった全ての国(地域、町)の名前

それらをキーとして、別のクエリに利用する場合などがよくあります。