Azure Monitor ログのテキスト データの解析

Azure Monitor によって収集された一部のログ データでは、1 つのプロパティに複数に分けられた情報が含まれます。 このデータを複数のプロパティに分けて解析すると、クエリで使用しやすくなります。 一般的な例は、複数の値を持つすべてのログ エントリを 1 つのプロパティに集めるカスタム ログです。 異なる値に個別のプロパティを作成することによって、それぞれで検索したり、集約したりできます。

この記事では、データが取り込まれたとき、またデータがクエリで取得されたときに、Azure Monitor でログ データを解析するためのさまざまなオプションについて説明します。また、それぞれの相対的な利点について比較します。

必要なアクセス許可

解析方法

データを収集する場合は取り込み時に、またはクエリを使用してデータを分析する場合はクエリ時にデータを解析できます。 それぞれの方法には異なる利点があります。

収集時のデータ解析

変換を使用して、収集時にデータを解析し、解析されたデータを送信する列を定義します。

長所:

  • クエリに解析コマンドを含める必要がないため、収集したデータに対してクエリを実行しやすくなります。
  • クエリで解析を実行する必要がないため、クエリのパフォーマンスが向上します。

短所:

  • 前もって定義する必要があります。 既に収集されたデータを含めることはできません。
  • 解析ロジックを変更する場合は、新しいデータにのみ適用されます。
  • データ収集のための待機時間が長くなります。
  • エラー処理が難しくなる場合があります。

クエリ実行時のデータ解析

クエリ実行時にデータを解析する場合、データを複数のフィールドに分けて解析するロジックをクエリに含めます。 実際のテーブル自体は変更されません。

長所:

  • 既に収集されたデータを含め、すべてのデータに適用されます。
  • ロジックに加えた変更はすべてのデータにすぐに適用されます。
  • 特定のデータ構造に対して事前に定義したロジックなど、柔軟な解析オプションがあります。

短所:

  • より複雑なクエリを記述する必要があります。 この欠点は、テーブルをシミュレートする関数を使用することによって軽減できます。
  • 複数のクエリの解析ロジックをレプリケートする必要があります。 関数を使用して一部のロジックを共有できます。
  • 非常に大きなレコード セット (数十億件のレコード) に対して複雑なロジックを実行するときに、オーバーヘッドが発生することがあります。

収集されたとおりにデータを解析する

収集される時のデータの解析の詳細については、「Azure Monitor での変換の構造」を参照してください。 この方法では、他のプロパティと同じようにクエリで使用できるテーブル内のカスタム プロパティが作成されます。

パターンを使用してクエリでデータを解析する

レコード全体で繰り返されるパターンによって解析するデータを識別できる場合、Kusto 照会言語のさまざまな演算子を使用して、1 つまたは複数の新しいプロパティに特定のデータを抽出することができます。

単純なテキスト パターン

クエリで parse 演算子を使用して、文字列式から抽出できる 1 つ以上のカスタム プロパティを作成します。 識別するパターンと作成するプロパティの名前を指定します。 この方法は、key=value のような形式でキー値の文字列を持つデータにおいて特に役立ちます。

次の形式のデータを持つカスタム ログについて考慮します。

Time=2018-03-10 01:34:36 Event Code=207 Status=Success Message=Client 05a26a97-272a-4bc9-8f64-269d154b0e39 connected
Time=2018-03-10 01:33:33 Event Code=208 Status=Warning Message=Client ec53d95c-1c88-41ae-8174-92104212de5d disconnected
Time=2018-03-10 01:35:44 Event Code=209 Status=Success Message=Transaction 10d65890-b003-48f8-9cfc-9c74b51189c8 succeeded
Time=2018-03-10 01:38:22 Event Code=302 Status=Error Message=Application could not connect to database
Time=2018-03-10 01:31:34 Event Code=303 Status=Error Message=Application lost connection to database

次のクエリは、このデータを個別のプロパティに分けて解析します。 project の行は、カスタム ログからのエントリ全体を保持する単一のプロパティである RawData ではなく、計算されたプロパティのみを返すために追加されています。

MyCustomLog_CL
| parse RawData with * "Time=" EventTime " Event Code=" Code " Status=" Status " Message=" Message
| project EventTime, Code, Status, Message

次の例は、AzureActivity テーブル内の UPN のユーザー名を分解します。

AzureActivity
| parse  Caller with UPNUserPart "@" * 
| where UPNUserPart != "" //Remove non UPN callers (apps, SPNs, etc)
| distinct UPNUserPart, Caller

正規表現

データを正規表現で識別できる場合、個々の値を抽出するために、正規表現を使用する関数を使用できます。 次の例では、extract を使用して、AzureActivity レコードから UPN フィールドを呼び出し、個別のユーザーを返します。

AzureActivity
| extend UPNUserPart = extract("([a-z.]*)@", 1, Caller) 
| distinct UPNUserPart, Caller

大規模な解析を効率化するために、Azure Monitor は re2 バージョンの正規表現を使用します。これは、類似しているものの、他の正規表現のバリアントとは異なります。 詳細については、re2 正規表現の構文に関するページを参照してください。

クエリで区切られたデータを解析する

区切られたデータでは、CSV ファイルのコンマのような一般的な文字でフィールドが区切られます。 split 関数を使用して、指定した区切り記号で区切られたデータを解析します。 この方法では、extend 演算子を使用して、データ内のすべてのフィールドを返したり、出力に含める個々のフィールドを指定したりできます。

注意

split は動的オブジェクトを返すため、演算子とフィルターで使用される文字列などのデータ型に、結果を明示的にキャストする必要があります。

次の CSV 形式のデータを持つカスタム ログについて考慮します。

2018-03-10 01:34:36, 207,Success,Client 05a26a97-272a-4bc9-8f64-269d154b0e39 connected
2018-03-10 01:33:33, 208,Warning,Client ec53d95c-1c88-41ae-8174-92104212de5d disconnected
2018-03-10 01:35:44, 209,Success,Transaction 10d65890-b003-48f8-9cfc-9c74b51189c8 succeeded
2018-03-10 01:38:22, 302,Error,Application could not connect to database
2018-03-10 01:31:34, 303,Error,Application lost connection to database

次のクエリは、このデータを解析し、2 つの計算されたプロパティで集計します。 最初の行は、RawData プロパティを文字列配列に分割します。 次の各行は、個々のプロパティに名前を付け、適切なデータ型に変換する関数を使用して出力に追加します。

MyCustomCSVLog_CL
| extend CSVFields  = split(RawData, ',')
| extend EventTime  = todatetime(CSVFields[0])
| extend Code       = toint(CSVFields[1]) 
| extend Status     = tostring(CSVFields[2]) 
| extend Message    = tostring(CSVFields[3]) 
| where getyear(EventTime) == 2018
| summarize count() by Status,Code

クエリの定義済み構造の解析

データの形式が既知の構造に設定されている場合、定義済みの構造を解析するために、Kusto 照会言語のいずれかの関数を使用することができます。

次の例のクエリは、JSON で構造化された AzureActivity テーブルの Properties フィールドを解析します。 JSON で名前が付けられた個々の値が含まれる parsedProp という名前の動的プロパティに結果を保存します。 これらの値は、クエリ結果をフィルターし、集計するために使用されます。

AzureActivity
| extend parsedProp = parse_json(Properties) 
| where parsedProp.isComplianceCheck == "True" 
| summarize count() by ResourceGroup, tostring(parsedProp.tags.businessowner)

これらの解析関数は、プロセッサを大量に消費する場合があります。 クエリが書式設定済みデータからの複数のプロパティを使用する場合にのみこれらを使用してください。 そうでない場合は、単純なパターン マッチングの処理のほうが高速です。

次の例は、ドメイン コントローラー TGT Preauth 型を分解した結果を表示します。 この型は、XML 文字列である EventData フィールドにのみ存在します。 このフィールドの他のデータは必要ありません。 この場合、parse は必要な特定のデータを選択するために使用します。

SecurityEvent
| where EventID == 4768
| parse EventData with * 'PreAuthType">' PreAuthType '</Data>' * 
| summarize count() by PreAuthType

関数を使用してテーブルをシミュレートする

特定のテーブルの同じ解析を実行する複数のクエリが存在することがあります。 この場合、各クエリで解析ロジックをレプリケートせずに、解析されたデータを返す関数を作成します。 その他のクエリでは、元のテーブルの代わりに、関数のエイリアスを使用できます。

前述のコンマ区切りのカスタム ログの例を考慮してください。 複数のクエリで解析されたデータを使用するには、次のクエリを使用して関数を作成し、エイリアス MyCustomCSVLog で保存します。

MyCustomCSVLog_CL
| extend CSVFields = split(RawData, ',')
| extend DateTime  = tostring(CSVFields[0])
| extend Code      = toint(CSVFields[1]) 
| extend Status    = tostring(CSVFields[2]) 
| extend Message   = tostring(CSVFields[3]) 

これで、次のようなクエリで実際のテーブル名の代わりにエイリアス MyCustomCSVLog を使用できるようになりました。

MyCustomCSVLog
| summarize count() by Status,Code

次のステップ

ログ クエリについて学習し、データ ソースとソリューションから収集されたデータを分析します。