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
ところで、値は空のものがあります。データとしては無意味なので、それをwhere
にand
オペレーターを使って条件をもうひとつ付け足して、とりのぞきます。
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 ステータスの値
- 全てのクライエントのブラウザの種類
- アクセスがあった全ての国(地域、町)の名前
それらをキーとして、別のクエリに利用する場合などがよくあります。