Azure
ログ
AzureLogAnalytics
LogAnalytics
SIEM

Azure Log Analytics - スカラオペレーターの使い方(クエリ言語)

Azure Log Analytics - 良く使われるオペレーターの使い方(クエリ言語)

https://qiita.com/YoshiakiOi/items/f2cb2b5626c2f7f71dba

に続いて、次はスカラオペレーターの使い方を見ていきます。


Log Analytics とクエリ言語の復習

Azure Log Analytics: Azure上でWindows/Linux, Azureのサービスのログを収集し、分析できる環境を提供するソリューション。

クエリ言語(Kusto Query Language: KQL): AzureのLog AnalyticsやApplication Insightで使われているクエリ言語で、シンプルな構文で検索ができる。以下のリファレンス(公式、英語のみ)に詳細があります。

https://docs.loganalytics.io/index

また、ログデータが溜まっていて、誰でも簡単にクエリを試し書きできるデモ環境:LADemoは以下のリンク先にあります。

https://aka.ms/LADemo

前回と同じく、今回もPluralsightの無料講座をもとに、Log Analyticsのクエリ言語を1つずつ見ていきたいと思います。以下で紹介されているオペレーターは、4. Scalar Operatorsで紹介されているオペレーターです。

Pluralsight "Kusto Query Language (KQL) from Scratch"

https://aka.ms/KQLPluralsight


スカラオペレーター

クエリの結果は、実際に上記のデモ環境で見てみてください。一部のオペレーターは実際にクエリ結果を見てみないと理解しづらいものもあります。


print - 1レコードの挿入

*厳密には、スカラオペレーターではありませんが。。。

文法:1レコード(フィールドと値)を挿入する。

print [<フィールド名> =] <値>

例:フィールド名 Year、値 2018のレコードを挿入する

print Year = 2018


now - 現在時刻(UTC)の取得

文法:現在時刻を取得;引数でずれ(1日前)などを指定して、その時刻を取ることもできる。

now()


ago - 前の時刻を取得

文法:現在時刻から、N(分、時間、日など)だけ前の時刻を取得

ago(N)


sort - 順番にソートするオペレーター

sortはとてもよく使うオペレーターです。

文法:対象を指定して、それに沿ってソートする

sort by <対象> [asc | desc] [nulls first | nulls last] 

例:パフォーマンスカウンターのテーブルを、コンピュータ名(昇順)、ログ生成時刻(降順)の順番でソートする

Perf | sort by Computer asc, TimeGenerated desc


Extract - 特定条件のものだけ抽出するオペレーター

文法:特定のフィールドから正規表現部分を抜き出し、新しいフィールドを作成する。

extract(<正規表現>, <オプション指定用の数字(O or 1 or 2+)>, <フィールド名>, [<型>])

・オプション指定用の数字:0 - 全体がマッチする、 1 - 最初の括弧の中身がマッチする、2+ - 2個以上の括弧の中身がマッチする。

例:パフォーマンスカウンターで論理ディスクのうち、InstanceName (Path) が"ドライブレター:"だけのレコードを抜き出したテーブルから、Computer, CounterName, InstanceNameとInstanceNameから:を抜き出したものをフィールドとして表示する。

Perf 

| where ObjectName == "LogicalDisk"
| where InstanceName matches regex "[A-Z]:"
| project Computer
, CounterName
, InstanceName
, NewInstance=extract ("([A-Z]):", 1, InstanceName )

ここでは、extractのオプションを1に設定しているため、最初の括弧の中身だけ(=ドライブレターだけ)抜き出したものを新しいフィールド(NewInstanceName)として作成しています。


parse - 特定のフィールドから、特定個所を評価・パースし、新しいフィールドを作成するオペレーター

文法:あるフィールドについて、特定の部分を取り出し、新しいフィールドにパースしていく

parse <フィールド名> with <特定の文> <新しいフィールド名> <次の文> <新しいフィールド名2> ... 

これだけ見てもわかりづらいので、具体例を見た方が早いです。

例:イベントログテーブルの中で、RenderedDescription が "Event Code" で始まるレコードについて、RenderedDescriptionを各要素ごとにパースして新しいフィールドを作成していく

Event

| where RenderedDescription startswith "Event code:"
| parse RenderedDescription with "Event code: " myEventCode
"Event message: " myEventMessage
"Event time: " myEventTime
"Event time (UTC): " myEventTimeUTC
"Event ID: " myEventID
"Event sequence: " myEventSequence
"Event occurrence: " *
| project myEventCode, myEventMessage, myEventTime, myEventTimeUTC, myEventID, myEventSequence


datetime と 時間の計算


datetime型

時間と日にちを表現するデータ型(Log Analyticsでは、時刻は全てUTCで扱われます。)


四則演算

以下例のように、時間の四則演算ができます。

例:ログ生成時間から現在時刻までの経過時間

now() - TimeGenerated

例:上記を日数単位にする。

(now() - TimeGenerated) / 1d


startofX / endofX - 基準の最初/最後のdatetimeを返すオペレーター

X = (day | week | month | year)

文法:Xを基準として、その最初/最後のdatetimeを返す。

例:

startofday(datetime(2018-1-2 13:00:00))

--> 2018-01-02T00:00:00:00.000

startofyear(datetime(2018-1-2 13:00:00))

--> 2018-01-01T00:00:00.000


between - 2つの値の間にある対象を返すオペレーター

文法:XとYの間

between (X .. Y)

例:2018/4/1と2018/4/3の間で生成されたものを選択する

between (startofday(datetime(2018-4-1)) .. endofday(datetime(2018-4-3)))


todynamic - key/value型のデータが入ったフィールドを、dynamics型(JSONのように扱える型)で扱えるようにするオペレーター

文法:

todyanmic (<フィールド名>)

例:SecurityAlertテーブルの中で、key/value型でデータが入っているExtendedPropertiesフィールドをdynamic型で扱い、その中でkeyであるAlert Start Time (UTC)を新しいフィールドして作成する。

SecurityAlert 

| extend ExtProps = todynamic(ExtendedProperties)
| project ExtendedProperties, ExtProps["Alert Start Time (UTC)"]


format_datetime/format_timespan - datetimeを指定のフォーマットで出力するオペレーター

文法:

format_datetime/format_timespan (<datetime型の値>, <指定のフォーマット>)

フォーマットについては以下を参照。

https://docs.loganalytics.io/docs/Language-Reference/Scalar-functions/format_datetime()

例:ログ生成時間を、yyyy/MM/ddのフォーマットで出力する

format_datetime(TimeGenerated, "yyyy/MM/dd")

例:ログ生成時間から現在時刻までの経過時間を計算し、それをhh:mm:ssで出力する

extend TimeGen = now() - TimeGenerated

format_timespan (TimeGen, "hh:mm:ss")


datetime_part - datetimeから特定の項目を取り出すオペレーター

文法:

datetime_part(<取り出す項目>, datetime)

項目は、Hour, Day, WeeekOfYear, Month, Yearなど

詳細はこちらを参照、https://docs.loganalytics.io/docs/Language-Reference/Scalar-functions/datetime_part() 

例:特定のdatetimeから、Dayだけを取り出す

datetime_part("Day",datetime(2015-12-14))

--> 14


iif - 条件分岐を扱うオペレーター

文法:

iif (<条件式>, <条件式=Trueの時の値>, <条件式=Falseの時の値>)

例:% Free Spaceカウンターの値が50以下の時はOK、50以上の時はmight want to look at thisとコメントする新しいフィールドを作成する

Perf 

| where CounterName == "% Free Space"
| extend FreeSpace = iff(CounterValue < 50, "You might want to look at this", "You're OK!")


case - 複数条件の条件分岐を扱うオペレーター

文法:

case(<条件式1>, <条件式1=Trueの時の値>, ... , <条件式N>, <条件式N=Trueの時の値>, <条件式=Falseの時の値>)

例:上記の例で、10以下、30以下、50以下でコメントをつけていく

Perf 

| where CounterName == "% Free Space"
| extend FreeSpace = case(CounterValue < 10, "Critical", CounterValue < 30, "Danger", CounterValue < 50, "You might want to look at this", "You're OK!")


isempty/isnull - Empty値、NULL値かどうかを判定するオペレーター

これらは、上記iffと一緒に使われることが多いです。

文法:

isempty/isnull(<判定したい値>)

例:パフォーマンスカウンターで、InstanceNameがEmpty値のものを、No Instance Nameと表記する新しいフィールドを作成する

Perf | extend InstName = iff(isempty(InstanceName), "No Instance Name", InstanceName)


split - 特定の記号で値を分割する

文法:特定の記号でフィールドを分割し、N番目のものを取り出す(Nは省略可能で、省略された場合は分割したArrayを出力する)。

split(<対象のフィールド>, <分割に使う記号>, [N])

例:パフォーマンスカウンターのCounterPathを'\'で分割し、そのArrayとArray[2]を取り出す。

Perf 

| project CounterPath, CPSplit=split(CounterPath , '\\'), CPSplit2 = split(CounterPath, '\\', 2)


String Operations - 文字列の扱い方

Log Analyticsには、多くの文字列を扱うための判別式があります。ここでは、containsとinを見てみます。


contains - 特定の単語を含んでいるかどうかを判別する

!containsだと否定形、contains_csだとcase sensitive(大文字・小文字を区別)となります。

例:パフォーマンスカウンターのうち、CounterNameが"BYTES"を含んでいるものだけを取り出す。

Perf | where CounterName contains "BYTES"


in - 特定の単語のうちどれかが含まれていればTrue、含まれていなければFalseとなる判別式

例:パフォーマンスカウンターのうち、CounterNameがDisk Transfers/sec, Disk Reads/sec, Avg. Disk/sec Writeであるものを返す

Perf | where CounterName in ("Disk Transfers/sec", "Disk Reads/sec", "Avg. Disk/sec Write")


strcat - 文字列を結合するオペレーター

文法:引数で与えられた文字列を結合する

strcat(<文字列1>, <文字列2> ...)

--> 文字列1文字列2 ...

例:パフォーマンスカウンターで、Computer - ObjectName - CounterNameというフィールドを作成する

Perf 

| extend COC = strcat(Computer, " - ", ObjectName, " - ", CounterName)
| project COC, TimeGenerated, CounterValue


最後に

詳細は以下のリファレンスで各オペレーターの説明をご参照ください。

https://docs.loganalytics.io/docs/Language-Reference/Change-log

前稿

Azure Log Analytics - 良く使われるオペレーターの使い方(クエリ言語)

https://qiita.com/YoshiakiOi/items/f2cb2b5626c2f7f71dba

*本稿は、個人の見解に基づいた内容であり、所属する会社の公式見解ではありません。また、いかなる保証を与えるものでもありません。正式な情報は、各製品の販売元にご確認ください。