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 

国のリストを見たい

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

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

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

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

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

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

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

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

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

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

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

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

再度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)

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

まとめ

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

  • 先週サーバーが返した全ての Http ステータスの値
  • 全てのクライエントのブラウザの種類
  • アクセスがあった全ての国(地域、町)の名前

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