このトピックでは、さまざまなシナリオでのSimple Log Service Processing Language (SPL) の使用方法について説明します。
さまざまなシナリオでのSPL
SPLの能力は、SPLが使用されるシナリオに基づいて変化する。
SPLエントリポイント | Logstoreインデックスベースのフィルタリング結果の入力としての使用 | フィールド名の大文字と小文字の区別 | __line__のフルテキストフィールド | |
リアルタイム消費 |
| サポートされていません。 アスタリスク (
| 大文字と小文字を区別します。 | サポートされていません。 |
スキャンベースのクエリ |
| サポートされています。 インデックスベースのフィルタリングを実行してから、SPLを使用してフィルタリング結果を処理できます。 例:
| 大文字と小文字を区別しません。 | サポートされています。 |
Logtailコレクション | Logtail設定を作成します。 | サポートされていません。 アスタリスク (
| 大文字と小文字を区別します。 | サポートされていません。 |
プロセス特殊フィールド
時間フィールド
SPLの実行中、Simple Log Serviceの時間フィールドのデータ型は常にINTEGER
またはBIGINT
です。 Simple Log Serviceの時間フィールドは、__time__
および __time_ns_part__
です。 __time__フィールドはタイムスタンプを指定し、__time_ns_part__フィールドは時間値のナノ秒を指定する。
データの時刻を更新する場合は、extend命令を使用し、新しい時刻値のデータ型がINTEGER
またはBIGINT
であることを確認する必要があります。 他の手順を使用して時間フィールドを管理することはできません。
project、project-away、およびproject-rename: デフォルトでは、時間フィールドは保持されます。 フィールドの名前変更や上書きはできません。
parse-regexpおよびparse-json: 時間フィールドが抽出された場合、フィールドは無視されます。
例
既存の時間文字列から時間フィールドを抽出します。
SPLステートメント
* | parse-regexp time, '([\d\-\s:]+)\.(\d+)' as ts, ms | extend ts=date_parse(ts, '%Y-%m-%d %H:%i:%S') | extend __time__=cast(to_unixtime(time_s) as INTEGER) | extend __time_ns_part__=cast(ms as INTEGER) * 1000000 | project-away ts, ms
入力データ
time: '2023-11-11 01:23:45.678'
出力結果
__time__: 1699637025 __time_ns_part__: 678000000 time: '2023-11-11 01:23:45.678'
名前に特殊文字が含まれるフィールド
ログにスペースまたは特殊文字で名前が付けられたフィールドが含まれている場合、フィールド名を二重引用符 (") で囲み、フィールドを引用できます。 たとえば、ログには、名前がa B
のフィールドが含まれています。フィールド名にはスペースが含まれます。
SPLステートメントで "A B"
を指定して、フィールドを引用できます。 例:
* | where "A B" like '%error%'
名前が大文字と小文字を区別しないフィールド
SPLを使用してスキャンベースのクエリ操作を実行する場合、SPL命令で引用したフィールド名は大文字と小文字が区別されません。 たとえば、ログにMethod
という名前のフィールドが含まれている場合、SPL命令でmethod
またはMETHOD
を指定してフィールドを引用できます。
Simple Log Serviceのスキャンベースのクエリ機能が含まれます。 詳細については、「スキャンベースのクエリの概要」をご参照ください。
例
where命令でフィールド名を指定します。 フィールド名は大文字と小文字を区別しません。
SPLステートメント
* | where METHOD like 'Post%'
入力データ
Method: 'PostLogstoreLogs'
出力結果
Method: 'PostLogstoreLogs'
フィールド名の競合の処理
ログのアップロードまたはSPLの実行中に、大文字と小文字が区別される処理でフィールド名の競合が発生する可能性があります。 たとえば、生のログにメソッドフィールドとメソッドフィールドの両方が含まれている場合、競合が存在します。 SPLは、さまざまなシナリオでさまざまなメソッドを使用してフィールド名の競合を解決します。
次の競合を防ぐために、生ログの重複フィールドを削除することをお勧めします。
入力データの競合
生のログには、名前が大文字と小文字を区別しないフィールドが重複することがあります。 たとえば、ログに [ステータス]
フィールドと [ステータス]
フィールドが含まれている場合、SPLはフィールドの一方を入力としてランダムに選択し、もう一方を破棄します。 例:
SPLステートメント
* | extend status_cast = cast(status as bigint)
入力データ
Status: '200' status: '404'
出力結果
可能性1: Statusフィールドの値は保持されます。
Status: '200' -- The first field is retained, and the second field is discarded. status_cast: '200'
可能性2: statusフィールドの値は保持されます。
status: '404' -- The second field is retained, and the first field is discarded. Status_cast: '404'
出力結果の競合
シナリオ1: 既存のデータフィールドが競合する。
SPL実行中に、大文字と小文字を区別しない重複フィールドが生成され得る。 この場合、SPLはフィールドの1つを出力としてランダムに選択します。 たとえば、ログには、値がJSON文字列型のフィールドが含まれています。 parse − json
命令の実行中に、重複フィールドが抽出され得る。 例:
SPLステートメント
* | parse-json content
入力データ
content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}'
出力結果
可能性1: Methodフィールドは保持される。
content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}' Method: 'PostLogs' -- The Method field is retained. status: '200'
可能性2: 方法フィールドは保持される。
content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}' method: 'GetLogs' -- The method field is retained. status: '200'
シナリオ2: 新しいデータフィールドが競合します。
SPLは、SPLの実行後に生成される新しいデータフィールドの名前の大文字化を保持します。これには、extend
命令で指定されたフィールド名と、parse-regexp
およびparse-csv
命令のよう
に指定されたフィールド名が含まれます。 これは競合を防ぐのに役立ちます。
たとえば、extend
命令で [Method]
フィールド名を指定した場合、フィールド名は [Method]
のままになります。
SPLステートメント
* | extend Method = 'Post'
入力データ
Status: '200'
出力結果
Status: '200' Method: 'Post'
予約済みフィールドの競合の処理
Simple Log Serviceのリアルタイム消費とスキャンベースのクエリ機能が含まれています。
Simple Log Serviceの予約フィールドの詳細については、「予約フィールド」をご参照ください。 SPLは、Simple Log ServiceのLogGroupからデータを入力として読み取ります。 LogGroupの定義の詳細については、「データエンコーディング」をご参照ください。 Simple Log Serviceに書き込まれた生データがLogGroupのエンコード仕様に準拠していない場合、またはLogGroupではなくLogContentに予約フィールドが含まれている場合、SPLは次のポリシーに基づいて予約フィールドを読み取ります。
__source__
、__topic__
、__time__
、および__time_ns_part__
フィールドの場合、SPLはLogGroupからフィールド値を読み取り、LogContentの重複フィールドの値を無視します。名前の先頭に
__tag __:
が付いているタグフィールドの場合、SPLはLogGroupからフィールド値を優先的に読み取ります。 フィールド値が見つからない場合、SPLはLogContentからフィールド値を読み取ります。 たとえば、__tag __: ip
フィールドの場合、SPLはLogTagのリストからキーがip
であるフィールドを優先的に読み取ります。 値が見つからない場合、SPLはLogContentのカスタムフィールドのリストからキーが__tag __: ip
であるフィールドを読み取ります。
__line__のフルテキストフィールド
スキャンベースのクエリ機能が含まれます。
Simple Log Serviceコンソールで、またはGetLogstoreLogs操作を呼び出して生ログをフィルタリングする場合は、__line__フィールドを使用できます。
例
キーワードエラーを使用してログを検索します。
* | where __line__ like '%error%'
ログに__line ___という名前のフィールドが含まれている場合は、フィールドを引用するには、フィールド名を
'__line__'
などの記号で囲む必要があります。
* | where `__line__` ='20'
古い値と新しい値の保持と上書き
SPL命令が実行された後に出力フィールドが入力データ内の既存のフィールドと同じ名前になっている場合、出力フィールドは次のポリシーに基づいて名前が変更されます。
次のポリシーは、extend命令には適用されません。 extend命令を使用し、出力フィールドの名前が入力フィールドと同じである場合、新しいフィールド値が使用されます。
古い値と新しい値の不一致
入力フィールドの値は保持されます。
例
例1: プロジェクト命令が実行されると、出力フィールドは入力フィールドと同じ名前になります。
SPLステートメント
* | extend status=cast(status as BIGINT) -- Convert the data type of the status field into BIGINT. | project code=status -- The old data type of the code field is VARCHAR, and the new data type of the field is BIGINT. Retain the old value of the field.
入力データ
status: '200' code: 'Success'
出力結果
code: 'Success'
例2: parse-json命令が実行された後、抽出されたフィールドは入力フィールドと同じ名前が付けられます。
SPLステートメント
* | extend status=cast(status as BIGINT) -- Convert the data type of the status field into BIGINT. | parse-json content -- The old data type of the status field is BIGINT, and the new data type of the field is VARCHAR. Retain the old value of the field.
入力データ
status: '200' content: '{"status": "Success", "body": "this is test"}'
出力結果
content: '{"status": "Success", "body": "this is test"}' status: 200 body: 'this is test'
古い値と新しい値の一貫性のあるデータ型
出力フィールドの名前が値がnullの入力フィールドと同じである場合、新しいフィールド値が使用されます。 入力フィールド値がヌルでない場合、出力フィールドの値は、実行される命令内のmode
パラメータに基づいて決定される。
mode
パラメーターが命令に含まれていない場合は、パラメーターのデフォルト値が使用されます。 デフォルト値はoverwrite
です。
Value of mode | 説明 |
overwrite | 古い値を新しい値で上書きします。 |
preserve | 古い値を保持し、新しい値を無視します。 |
例
例1: プロジェクト命令が実行されると、出力フィールドは入力フィールドと同じ名前になります。 2つのフィールドは同じデータ型で、modeパラメーターのデフォルト値が使用されます。 デフォルト値はoverwriteです。
SPLステートメント
* | project code=status -- The old and new data types of the code field are VARCHAR. In overwrite mode, the new value is used.
入力データ
status: '200' code: 'Success'
出力結果
code: '200'
例2: parse-json命令が実行された後、抽出された出力フィールドは入力フィールドと同じ名前が付けられます。 2つのフィールドは同じデータ型で、modeパラメーターのデフォルト値が使用されます。 デフォルト値はoverwriteです。
SPLステートメント
* | parse-json content -- The old and new data types of the status field are VARCHAR. In overwrite mode, the new value is used.
入力データ
status: '200' content: '{"status": "Success", "body": "this is test"}'
出力結果
content: '{"status": "Success", "body": "this is test"}' status: 'Success' body: 'this is test'
例3: parse-json命令が実行された後、抽出された出力フィールドは入力フィールドと同じ名前が付けられます。 2つのフィールドは同じデータ型で、modeパラメーターは保持するように設定されています。
SPLステートメント
* | parse-json -mode='preserve' content -- The old and new data types of the status field are VARCHAR. In preserve mode, the old value is used.
入力データ
status: '200' content: '{"status": "Success", "body": "this is test"}'
出力結果
content: '{"status": "Success", "body": "this is test"}' status: '200' body: 'this is test'
データ型の変換
初期タイプ
SPLを使用する場合、ログの時間フィールドを除き、すべての入力フィールドの初期タイプはVARCHARです。 厳密に型指定されたデータが後続の処理に含まれる場合、データ型変換が必要です。
例
ステータスコード5xxを使用してアクセスログをフィルタリングする場合は、ステータスフィールドのデータ型をBIGINTに変換してからデータを比較する必要があります。
* -- The initial type of the status field is VARCHAR.
| where cast(status as BIGINT) >= 500 -- Convert the data type of the status field into BIGINT and then compare data.
タイプ保持
SPLの実行中にextend命令を使用してフィールドのデータ型を変換する場合、新しいデータ型は後続の処理で使用されます。
例
* -- A Logstore is used as the input data. The initial type of all input fields is VARCHAR, except for the time fields.
| where __source__='127.0.0.1' -- Use the __source__ field for filtering.
| extent status=cast(status as BIGINT) -- Convert the data type of the status field into BIGINT.
| project status, content
| where status>=500 -- The data type of the status field is retained as BIGINT. The field value can be directly compared with the number 500.
SPL式のnull値の処理
null値の生成
次のシナリオでは、SPLの実行中にnull値が生成されます。
SPL式で指定されたフィールドが入力データに存在しない場合、システムはフィールドの値を計算のnullと見なします。
SPL式の計算処理中にエラーが発生した場合、システムは計算結果としてnullを返します。 このエラーには、キャスト関数によるデータ型変換の失敗と、Array Index Out Of Boundsエラーが含まれます。
例
フィールドが存在しない場合、値nullが計算に使用されます。
SPLステートメント
* | extend withoutStatus=(status is null)
入力データ
# Entry 1
status: '200'
code: 'Success'
# Entry 2
code: 'Success'
出力結果
# Entry 1
status: '200'
code: 'Success'
withoutStatus: false
# Entry 2
code: 'Success'
withoutStatus: true
計算プロセス中にエラーが発生した場合、計算結果はnullになります。
SPLステートメント
* | extend code=cast(code as BIGINT) -- The data type of the code field failed to be converted into BIGINT. | extend values=json_parse(values) | extend values=cast(values as ARRAY(BIGINT)) | extend last=arr[10] -- An Array Index Out Of Bounds error occurred.
入力データ
status: '200' code: 'Success' values: '[1,2,3]'
出力結果
status: '200' code: null values: [1, 2, 3] last: null
null値の削除
計算中にnull値を削除するには、COALESCE式を使用して複数の値を優先的に関連付け、最初のnull以外の値を最終的な計算結果として使用する必要があります。 すべての式がnullを返す場合、最終的な計算結果としてデフォルト値を指定できます。
例
配列の最後の要素を読み取ります。 配列が空の場合、デフォルト値0が返されます。
SPLステートメント
* | extend values=json_parse(values) | extend values=cast(values as ARRAY(BIGINT)) | extend last=COALESCE(values[3], values[2], values[1], 0)
入力データ
# Entry 1 values: '[1, 2, 3]' # Entry 2 values: '[]'
出力結果
# Entry 1 values: [1, 2, 3] last: 3 # Entry 2 values: [] last: 0
ハンドルエラー
構文エラー
SPL構文エラーとは、SPLステートメントを記述するときに構文に準拠しないエラーを指します。 エラーには、無効な命令名、キーワード引用エラー、および無効なタイプが含まれます。 SPL構文エラーが発生した場合、SPLはデータを処理しません。 報告されたエラー情報に基づいてエラーを処理する必要があります。
データエラー
SPLの実行中に関数または変換でエラーが発生した場合、SPLは関連する結果フィールドをnull
に設定します。 この場合、データエラーが報告される。 データエラーはデータの各行で発生する可能性があり、SPLはランダムにサンプリングして特定のエラーを返します。 データエラーを無視したり、実際の状況に基づいてSPLステートメントを変更したりできます。
データエラーは、SPLステートメントの実行全体には影響しません。 SPLステートメントは引き続き処理結果を返し、エラーのあるフィールドの値はnull
です。 実際の状況に基づいてデータエラーを無視できます。
タイムアウトエラー
SPLステートメントには、特定のデータシナリオで異なる時間を消費する異なる命令が含まれています。 SPLステートメントの実行時間全体がデフォルトのタイムアウト時間を超えた場合、システムはSPLステートメントの実行を停止し、タイムアウトエラーを返します。 この場合, SPL文の実行結果は空になります。 デフォルトのタイムアウト期間は、スキャンベースのクエリ、リアルタイム消費、およびLogtail収集のシナリオで異なる場合があります。
タイムアウトエラーが発生した場合は、SPLステートメントを変更して、ステートメントの複雑さとパイプラインの数を減らすことをお勧めします。 たとえば、SPLステートメントで正規表現を使用して、ステートメントの複雑さを軽減できます。
メモリ不足エラー
SPLステートメントには、特定のデータシナリオで異なるメモリリソースを消費するさまざまな命令が含まれています。 SPLステートメントによって消費されるメモリリソースの量が既定のメモリクォータを超えると、システムはSPLステートメントの実行を停止し、メモリ不足エラーを返します。 この場合, SPL文の実行結果は空になります。 デフォルトのメモリクォータは、スキャンベースのクエリ、リアルタイム消費、およびLogtail収集のシナリオによって異なる場合があります。
メモリ不足エラーが発生した場合は、SPLステートメントを変更して、ステートメントの複雑さとパイプラインの数を減らし、生データの量が過度に大きいかどうかを確認することをお勧めします。