すべてのプロダクト
Search
ドキュメントセンター

Simple Log Service:一般リファレンス

最終更新日:Jul 01, 2025

このトピックでは、さまざまなシナリオにおける Simple Log Service 処理言語 (SPL) の使用法について説明します。

さまざまなシナリオにおける SPL

SPL の機能は、SPL が使用されるシナリオによって異なります。

機能タイプ

ログストアのインデックスベースのフィルタリング結果を入力として使用

フィールド名の大文字と小文字の区別

__line__ の全文フィールド

ベストプラクティス

Logtail コレクション

サポートされていません。アスタリスク (*) を使用すると、Logtail によって収集されたすべての 生データ が入力として使用されます。例:

* | parse-json content

大文字と小文字が区別されます。

サポートされていません。

SPL 文を使用してテキストログを収集する

Ingest プロセッサ

サポートされていません。アスタリスク (*) を使用すると、すべての 生データ が入力として使用されます。

大文字と小文字が区別されます。

サポートされていません。

Ingest プロセッサを使用して Alibaba Cloud サービスログを処理する

リアルタイム消費

サポートされていません。アスタリスク (*) を使用すると、ログストア内のすべての 生データ が入力として使用されます。例:

* | where msg like '%wrong%'

大文字と小文字が区別されます。

サポートされていません。

データ変換の概要 (新バージョン)

サポートされていません。アスタリスク (*) を使用すると、ログストア内のすべての 生データ が入力として使用されます。

大文字と小文字が区別されます。

サポートされていません。

ベストプラクティス

スキャンベースのクエリ

サポートされています。インデックスベースのフィルタリングを実行してから、SPL を使用してフィルタリング結果を処理できます。例:

error and msg:wrong | project level, msg

大文字と小文字は区別されません。

サポートされています。

ログをスキャンする

SPL データセット

SPL データセットは、名前付きデータセットと名前なしデータセットの 2 つのタイプに分類されます。定義は以下のとおりです。

  • 名前付きデータセット: .let ディレクティブを使用して作成され、後続の SPL 式の入力として機能し、$ 記号で参照されます。

  • 名前なしデータセット: .let ディレクティブを使用しない SPL 式の結果は、名前なしデータセットとして分類され、直接出力されます。

次の SPL の例では、次のように結果が出力されます。

  • 名前付きデータセット: valid という名前のデータセット。値が amode フィールドが含まれています。

  • 名前なしデータセット: mode フィールドが含まれていないか、値が bmode フィールドが含まれているデータセット。

-- mode フィールドが含まれていないデータをフィルタリングして名前なしデータセットを生成し、直接出力します。
*
| where mode is null;

-- mode フィールドが含まれているデータをフィルタリングして名前付きデータセット src として定義し、出力しません。
.let src = * 
| where mode is not null;

-- 名前付きデータセット src を入力として使用して、データセット valid を処理結果として定義し、出力しません。
.let valid = $src
| where mode = 'a'
| parse-regexp content, '(\S+)\s+(\S+)\s+(\S+)' as x, y, z
| project x, y, z;

-- 名前付きデータセット valid を出力します。
$valid; 

-- 名前付きデータセット src を入力として使用して名前なしデータセットを生成し、直接出力します。
$src
| where mode = 'b'
| parse-csv content as u, v
| project u, v;

特殊フィールドの処理

時間フィールド

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 の実行中に、大文字と小文字を区別する処理でフィールド名の競合が発生する場合があります。たとえば、 生ログ に Method フィールドと method フィールドの両方が含まれている場合、競合が存在します。SPL は、さまざまなシナリオでさまざまなメソッドを使用してフィールド名の競合を解決します。

以下の競合を防ぐために、 生ログ 内の重複フィールドを削除することをお勧めします。

入力データの競合

生ログ には大文字と小文字が区別されない重複フィールドが含まれている場合があります。たとえば、ログに Status フィールドと status フィールドが含まれている場合、SPL はフィールドのいずれかを入力としてランダムに選択し、もう一方を破棄します。例:

  • SPL 文

    * | extend status_cast = cast(status as bigint)
  • 入力データ

    Status: '200'
    status: '404'
  • 出力結果

    • 可能性 1: Status フィールドの値が保持されます。

      Status: '200' -- 最初のフィールドは保持され、2 番目のフィールドは破棄されます。
      status_cast: '200'
    • 可能性 2: status フィールドの値が保持されます。

      status: '404' -- 2 番目のフィールドは保持され、最初のフィールドは破棄されます。
      Status_cast: '404'

出力結果の競合

シナリオ 1: 既存のデータフィールドの競合。

SPL の実行中に、大文字と小文字が区別されない重複フィールドが生成される場合があります。この場合、SPL は出力としてフィールドのいずれかを入力としてランダムに選択します。たとえば、ログに 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' -- Method フィールドが保持されます。
      status: '200'
    • 可能性 2: method フィールドが保持されます。

      content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}'
      method: 'GetLogs' -- method フィールドが保持されます。
      status: '200'

シナリオ 2: 新しいデータフィールドの競合。

SPL は、SPL の実行後に生成される新しいデータフィールドの名前の大文字と小文字を保持します。extend 命令で指定されたフィールド名と、as の後に 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__ フィールドを使用できます。

  • キーワード error を使用してログを検索します。

* | where __line__ like '%error%'
  • ログに __line__ という名前のフィールドが含まれている場合は、`__line__` など、フィールド名をグレイブアクセント (`) で囲んでフィールドを引用符で囲む必要があります。

* | where `__line__` ='20'

古い値と新しい値の保持と上書き

SPL 命令の実行後に出力フィールドの名前が入力データの既存のフィールドと同じ名前になった場合、出力フィールドの名前は次のポリシーに基づいて変更されます。

重要

次のポリシーは extend 命令には適用されません。extend 命令を使用し、出力フィールドの名前が入力フィールドと同じ名前になった場合、新しいフィールド値が使用されます。

古い値と新しい値のデータ型が一致しない

入力フィールドの値が保持されます。

  • 例 1: project 命令の実行後、出力フィールドの名前が入力フィールドと同じ名前になります。

    • SPL 文

      * 
      | extend status=cast(status as BIGINT) -- status フィールドのデータ型を BIGINT に変換します。
      | project code=status -- code フィールドの古いデータ型は VARCHAR で、フィールドの新しいデータ型は BIGINT です。フィールドの古い値を保持します。
    • 入力データ

      status: '200'
      code: 'Success'
    • 出力結果

      code: 'Success'
  • 例 2: parse-json 命令の実行後、抽出されたフィールドの名前が入力フィールドと同じ名前になります。

    • SPL 文

      * 
      | extend status=cast(status as BIGINT) -- status フィールドのデータ型を BIGINT に変換します。
      | parse-json content -- status フィールドの古いデータ型は BIGINT で、フィールドの新しいデータ型は VARCHAR です。フィールドの古い値を保持します。
    • 入力データ

      status: '200'
      content: '{"status": "Success", "body": "this is test"}'
    • 出力結果

      content: '{"status": "Success", "body": "this is test"}'
      status: 200
      body: 'this is test'

古い値と新しい値のデータ型が一致する

出力フィールドの名前が入力フィールドと同じ名前で、入力フィールドの値が null の場合、新しいフィールド値が使用されます。入力フィールド値が null でない場合、出力フィールドの値は、実行される命令の mode パラメーターに基づいて決定されます。

重要

命令に mode パラメーターが含まれていない場合は、パラメーターの デフォルト 値が使用されます。デフォルト 値は overwrite です。

mode の値

説明

overwrite

古い値を新しい値で上書きします。

preserve

古い値を保持し、新しい値を無視します。

  • 例 1: project 命令の実行後、出力フィールドの名前が入力フィールドと同じ名前になります。2 つのフィールドのデータ型は同じで、mode パラメーターの デフォルト 値が使用されます。デフォルト 値は overwrite です。

    • SPL 文

    * | project code=status -- code フィールドの古いデータ型と新しいデータ型は VARCHAR です。上書きモードでは、新しい値が使用されます。
    • 入力データ

      status: '200'
      code: 'Success'
    • 出力結果

      code: '200'
  • 例 2: parse-json 命令の実行後、抽出された出力フィールドの名前が入力フィールドと同じ名前になります。2 つのフィールドのデータ型は同じで、mode パラメーターの デフォルト 値が使用されます。デフォルト 値は overwrite です。

    • SPL 文

      * | parse-json content -- status フィールドの古いデータ型と新しいデータ型は VARCHAR です。上書きモードでは、新しい値が使用されます。
    • 入力データ

      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 パラメーターは preserve に設定されています。

    • SPL 文

      * | parse-json -mode='preserve' content -- status フィールドの古いデータ型と新しいデータ型は VARCHAR です。保存モードでは、古い値が使用されます。
    • 入力データ

      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 を使用してアクセスログをフィルタリングする場合、status フィールドのデータ型を BIGINT に変換してからデータを比較する必要があります。

* -- status フィールドの初期型は VARCHAR です。
| where cast(status as BIGINT) >= 500 -- status フィールドのデータ型を BIGINT に変換してからデータを比較します。

型の保持

SPL の実行中に extend 命令を使用してフィールドのデータ型を変換する場合、後続の処理では新しいデータ型が使用されます。

* -- ログストアが入力データとして使用されます。時間フィールドを除き、すべての入力フィールドの初期型は VARCHAR です。
| where __source__='127.0.0.1' -- フィルタリングに __source__ フィールドを使用します。
| extent status=cast(status as BIGINT) -- status フィールドのデータ型を BIGINT に変換します。
| project status, content
| where status>=500 -- status フィールドのデータ型は BIGINT として保持されます。フィールド値は数値 500 と直接比較できます。

SPL 式の null 値の処理

null 値の生成

SPL の実行中に、次のシナリオで null 値が生成されます。

  1. SPL 式で指定されたフィールドが入力データに存在しない場合、システムは計算のためにフィールドの値を null と見なします。

  2. SPL 式の計算プロセス中にエラーが発生した場合、システムは計算結果として null を返します。エラーには、cast 関数によって実装されたデータ型変換の失敗と、Array Index Out Of Bounds エラーが含まれます。

  1. フィールドが存在しない場合、計算には値 null が使用されます。

  • SPL 文

  • * | extend withoutStatus=(status is null)
  • 入力データ

  • # エントリ 1
    status: '200'
    code: 'Success'
    
    # エントリ 2
    code: 'Success'
  • 出力結果

  • # エントリ 1
    status: '200'
    code: 'Success'
    withoutStatus: false
    
    # エントリ 2
    code: 'Success'
    withoutStatus: true
  1. 計算プロセス中にエラーが発生した場合、計算結果は null になります。

  • SPL 文

    *
    | extend code=cast(code as BIGINT) -- code フィールドのデータ型を BIGINT に変換できませんでした。
    | extend values=json_parse(values)
    | extend values=cast(values as ARRAY(BIGINT))
    | extend last=arr[10] -- Array Index Out Of Bounds エラーが発生しました。
  • 入力データ

    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)
  • 入力データ

    # エントリ 1
    values: '[1, 2, 3]'
    
    # エントリ 2
    values: '[]'
  • 出力結果

    # エントリ 1
    values: [1, 2, 3]
    last: 3
    
    # エントリ 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 文を変更して文の複雑さと パイプライン の数を減らし、 生データ の量が過剰に大きいかどうかを確認することをお勧めします。