カスタム インデックスの構成

このドキュメントでは、Cloud Logging バケットにインデックス付きの LogEntry フィールドを追加して、ログデータのクエリを高速化する方法について説明します。

概要

クエリのパフォーマンスは、すべてのロギング ソリューションで重要です。ワークロードがスケールアップし、対応するログボリュームが増加するに従い、最も頻繁に使用するログデータをインデックスに登録すると、クエリ時間を短縮できます。

クエリのパフォーマンスを向上させるため、Logging は自動的に次の LogEntry フィールドをインデックスに登録します。

Logging によって自動的にインデックスに登録されるフィールドに加えて、バケットのカスタム インデックスを作成して、他の LogEntry フィールドをインデックスに登録するようにログバケットに指示できます。

たとえば、クエリ式に jsonPayload.request.status フィールドが含まれるとします。jsonPayload.request.status を含むバケットのカスタム インデックスを構成できます。そのバケットのデータに対する後続のクエリでは、クエリ式にそのフィールドが含まれている場合、インデックス付き jsonPayload.request.status データが参照されます。

Google Cloud CLI または Logging API を使用して、既存のログバケットや新しいログバケットにカスタム インデックスを追加できます。カスタム インデックスに含めるフィールドを選択する際は、次の制限事項に注意してください。

  • カスタム インデックスごとに最大 20 個のフィールドを追加できます。
  • バケットのカスタム インデックスを構成または更新したら、その変更がクエリに適用されるまで 1 時間待つ必要があります。このレイテンシにより、クエリ結果の正確性が保証され、過去に書き込まれたログを受け入れます。
  • Logging は、インデックスの作成または変更後にログバケットに保存されたデータにカスタム インデックスを適用します。カスタム インデックスへの変更は、過去にさかのぼってログに適用されることはありません。

準備

カスタム インデックスの構成を開始する前に、次の操作を行います。

カスタム インデックスを定義する

バケットのカスタム インデックスに追加するフィールドごとに、フィールドパスとフィールド タイプの 2 つの属性を定義します。

  • fieldPath: ログエントリの LogEntry フィールドへの特定のパスを記述します。例: jsonPayload.req_status
  • type: フィールドが文字列型または整数型のどちらであるかを示します。指定できる値は INDEX_TYPE_STRINGINDEX_TYPE_INTEGER です。

カスタム インデックスを追加するには、新しいバケットを作成するか、既存のバケットを更新します。バケットの構成の詳細については、ログバケットの構成をご覧ください。

バケットを作成するときにカスタム インデックスを構成するには、次の手順を実行します。

gcloud

gcloud logging buckets create コマンドを使用して、--index フラグを設定します。

gcloud logging buckets create BUCKET_NAME\
--location=LOCATION\
--description="DESCRIPTION" \
--index=fieldPath=INDEX_FIELD_NAME,type=INDEX_TYPE

コマンドの例:

gcloud logging buckets create int_index_test_bucket \
--location=global \
--description="Bucket with integer index" \
--index=fieldPath=jsonPayload.req_status,type=INDEX_TYPE_INTEGER

API

バケットを作成するには、Logging API の projects.locations.buckets.create を使用します。次のように、メソッドの引数を準備します。

  1. parent パラメータを、バケットを作成するリソース(projects/PROJECT_ID/locations/LOCATION)に設定します。

    変数 LOCATION は、ログを保存するリージョンを指します。

    たとえば、リージョン asia-east2 にプロジェクト my-project 用のバケットを作成する場合、parent パラメータは次のようになります: projects/my-project/locations/asia-east2

  2. bucketId パラメータを設定します(例: my-bucket)。

  3. LogBucket リクエストの本文で、IndexConfig オブジェクトを構成してカスタム インデックスを作成します。

  4. projects.locations.buckets.create を呼び出してバケットを作成します。

既存のバケットを更新してカスタム インデックスを含めるには、次の操作を行います。

gcloud

gcloud logging buckets update コマンドを使用して、--add-index フラグを設定します。

gcloud logging buckets update BUCKET_NAME\
--location=LOCATION\
--add-index=fieldPath=INDEX_FIELD_NAME,type=INDEX_TYPE

コマンドの例:

gcloud logging buckets update \
int_index_test_bucket \
--location=global \ --add-index=fieldPath=jsonPayload.req_status,type=INDEX_TYPE_INTEGER

API

Logging API の projects.locations.buckets.patch を使用します。LogBucket リクエストの本文で IndexConfig オブジェクトを構成し、インデックスを作成する LogEntry フィールドを含めます。

カスタム インデックス フィールドを削除する

バケットのカスタム インデックスからフィールドを削除するには、次のようにします。

gcloud

gcloud logging buckets update コマンドを使用して、--remove-indexes フラグを設定します。

gcloud logging buckets update BUCKET_NAME\
--location=LOCATION\
--remove-indexes=INDEX_FIELD_NAME

コマンドの例:

gcloud logging buckets update int_index_test_bucket \
--location=global \
--remove-indexes=jsonPayload.req_status

API

Logging API の projects.locations.buckets.patch を使用します。LogBucket リクエストの本文で、IndexConfig オブジェクトから LogEntry フィールドを削除します。

カスタム インデックス フィールドのデータ型を更新する

カスタム インデックス フィールドのデータ型を修正する必要がある場合は、次の操作を行います。

gcloud

gcloud logging buckets update コマンドを使用して、--update-index フラグを設定します。

gcloud logging buckets update BUCKET_NAME\
--location=LOCATION\
--update-index=fieldPath=INDEX_FIELD_NAME,type=INDEX_TYPE

コマンドの例:

gcloud logging buckets update \
int_index_test_bucket \
--location=global \
--update-index=fieldPath=jsonPayload.req_status,type=INDEX_TYPE_INTEGER

API

Logging API で projects.locations.buckets.patch を使用します。LogBucket リクエストの本文で IndexConfig オブジェクトを更新して、LogEntry フィールドに正しいデータ型を指定します。

カスタム インデックス フィールドのパスを更新する

カスタム インデックス フィールドのフィールドパスを修正する必要がある場合は、次の操作を行います。

gcloud

gcloud logging buckets update コマンドを使用して、--remove-indexes フラグと --update-index フラグを設定します。

gcloud logging buckets update BUCKET_NAME\
--location=LOCATION\
--remove-indexes=OLD_INDEX_FIELD_NAME \
--update-index=fieldPath=NEW_INDEX_FIELD_NAME,type=INDEX_TYPE

コマンドの例:

gcloud logging buckets update \
int_index_test_bucket \
--location=global \
--remove-indexes=jsonPayload.req_status_old_path \
--add-index=fieldPath=jsonPayload.req_status_new_path,type=INDEX_TYPE_INTEGER

API

Logging API の projects.locations.buckets.patch を使用します。LogBucket リクエストの本文で IndexConfig オブジェクトを更新して、LogEntry フィールドに正しいフィールドパスを指定します。

バケットのインデックス化されたすべてのフィールドを一覧表示する

カスタム インデックス フィールドを含むバケットの詳細を一覧表示するには、次のようにします。

gcloud

gcloud logging buckets describe コマンドを実行します。

gcloud logging buckets describe BUCKET_NAME\
--location=LOCATION

コマンドの例:

gcloud logging buckets describe indexed-bucket \
--location global

API

Logging API で projects.locations.buckets.get を使用します。

カスタム インデックス フィールドをクリアする

バケットからすべてのカスタム インデックス フィールドを消去するには、次のようにします。

gcloud

gcloud logging buckets update コマンドを使用して、--clear-indexes フラグを指定します。

gcloud logging buckets update BUCKET_NAME\
--location=LOCATION\
--clear-indexes

コマンドの例:

gcloud logging buckets update \
int_index_test_bucket \
--location=global \
--clear-indexes

API

Logging API の projects.locations.buckets.patch を使用します。LogBucket リクエストの本文で IndexConfig オブジェクトを削除します。

インデックス付きデータのクエリ実行と表示

カスタム インデックス フィールドに含まれるデータのクエリを実行するには、クエリのスコープをカスタム インデックス フィールドを含むバケットに制限し、適切なログビューを指定します。

gcloud

ログバケットからログを読み取るには、gcloud logging read コマンドに LOG_FILTER を追加してインデックス付きのデータを含めます。

gcloud logging read LOG_FILTER --bucket=BUCKET_ID --location=LOCATION --view=VIEW_ID

API

ログバケットからログを読み取るには、entries.list メソッドを使用します。resourceNames を設定して適切なバケットとログビューを指定し、filter を設定してインデックス付きデータを選択します。

フィルタリング構文の詳細については、Logging のクエリ言語をご覧ください。

インデックス タイプとフィールド タイプ

カスタム フィールド インデックスの構成方法は、ログのログバケットへの保存方法やクエリの処理の方法に影響します。

書き込み時

Logging は、インデックスが作成された後にログバケットに保存されているデータに対してカスタム インデックスの使用を試みます。

インデックス付きフィールドが入力されますが、これはログエントリのタイムスタンプに影響します。ログエントリがログバケットに保存されるとき、次のルールを使用してログフィールドがインデックス タイプに対して評価されます。

  • フィールド タイプがインデックス タイプと同じ場合、データはインデックスとしてすぐに追加されます。
  • フィールド タイプがインデックス タイプと異なる場合、Logging はフィールド タイプをインデックス タイプ(整数から文字列など)に強制変換しようとします。
    • タイプの強制変換が失敗した場合、データはインデックスに登録されません。タイプの強制変換が成功すると、データはインデックスに登録されます。

クエリ時

フィールドでインデックスを有効にすると、そのフィールドに対するクエリ方法が変更されます。デフォルトでは、Logging は評価対象の各ログエントリのデータ型に基づいてフィルタ制約をフィールドに適用します。インデックスが有効な場合、フィールドのフィルタ制約がインデックスのタイプに基づいて適用されます。フィールドにインデックスを追加すると、そのフィールドにスキーマが設定されます。

バケット用にカスタム インデックスが構成されている場合、次の条件の両方が満たされると、スキーマを一致させる動作が変わります。

  • フィールドのソースデータ型がそのフィールドのインデックス型と一致しない。
  • ユーザーが、このフィールドに制約を適用している。

次の JSON ペイロードについて考えてみましょう。

{"jsonPayload": {"name": "A", "value": 12345}}
{"jsonPayload": {"name": "B", "value": "3"}}

次は、このフィルタをそれぞれに適用します。

jsonPayload.value > 20

jsonPayoad.value フィールドにカスタム インデックスがない場合、Logging では柔軟なタイプのマッチングが適用されます。

  • 「A」の場合、Logging は「value」キーの値が実際には整数であり、制約「20」が整数に変換できることを監視します。次に、Logging は 12345 > 20 を評価し、数値の場合に true を返します。

  • 「B」の場合、Logging は「value」キーの値が実際には文字列であることを確認します。次に、"3" > "20" を評価し、この場合は英数字に該当するため「true」を返します。

jsonPayload.value フィールドがカスタム インデックスに含まれている場合、Logging では通常の Logging ロジックではなくインデックスを使用してこの制約が評価されます。動作が次のように変わります。

  • インデックスが文字列型の場合、すべての比較は文字列比較です。
    • 「12345」は英数字の「20」以下のため、「A」のエントリは一致しません。文字列「3」が「20」より大きいため、「B」のエントリが一致します。
  • インデックスが整数型の場合、すべての比較は整数の比較になります。
    • 「3」が数値的に「20」よりも大きくないため、「B」エントリは一致しません。「12345」は「20」より大きいため、「A」エントリは一致します。

この動作の違いは微妙で、カスタム インデックスを定義して使用する場合は考慮する必要があります。

エッジケースのフィルタリング

jsonPayload.value 整数型インデックスについて、文字列値がフィルタリングされたとします。

jsonPayload.value = "hello"

クエリ値をインデックス型に強制変換できない場合、インデックスは無視されます。

ただし、文字列型のインデックスについて、整数値を渡すとします。

jsonPayload.value > 50

「12345」も「3」も英数字の「50」より大きくないため、A も B も一致しません。