このドキュメントでは、インデックス付きの LogEntry フィールドを Cloud Logging バケットに追加して、ログデータのクエリを高速化する方法について説明します。
概要
クエリのパフォーマンスは、どのロギング ソリューションにとっても重要です。ワークロードのスケールアップに伴い、対応するログボリュームも増加していきますが、最も頻繁に使用するログデータをインデックスに登録することで、クエリ時間を短縮できます。
クエリのパフォーマンスを向上させるため、Logging は次の LogEntry フィールドを自動的にインデックスに登録します。
- resource.type
- resource.labels.*
- logName
- severity
- timestamp
- insertId
- operation.id
- trace
- httpRequest.status
- labels.*
- split.uid
Logging が自動的にインデックスに登録するフィールド以外にも、バケットのカスタム インデックスを作成して、他の LogEntry フィールドをインデックスに登録するようログバケットに指示することもできます。
たとえば、クエリ式に jsonPayload.request.status フィールドが頻繁に含まれているとします。jsonPayload.request.status を含むバケットにカスタム インデックスを構成すると、クエリ式にそのフィールドが含まれている場合、そのバケットのデータに対する後続のクエリは、インデックスに登録された jsonPayload.request.status データを参照します。
Google Cloud CLI または Logging API を使用して、既存または新しいログバケットにカスタム インデックスを追加できます。カスタム インデックスに含める追加のフィールドを選択する際は、次の制限事項に注意してください。
- 1 つのカスタム インデックスに追加できるフィールドは 20 個までです。
- バケットのカスタム インデックスを構成または更新した後、変更がクエリに適用されるまで 1 時間ほど待つ必要があります。このレイテンシにより、クエリ結果の正確性が確保され、過去に書き込まれたログが受け入れられます。
- Logging は、インデックスの作成または変更後にログバケットに保存されたデータにカスタム インデックスを適用します。カスタム インデックスへの変更は、過去に遡ってログに適用されることはありません。
始める前に
カスタム インデックスの構成を開始する前に、次の操作を行います。
gcloud CLI の最新バージョンを使用していることを確認します。詳細については、Google Cloud CLI コンポーネントの管理をご覧ください。
次の権限を持つ Identity and Access Management ロールが付与されていることを確認します。
これらのロールの詳細については、IAM によるアクセス制御をご覧ください。
カスタム インデックスを定義する
バケットのカスタム インデックスに追加するフィールドごとに、フィールドパスとフィールド タイプの 2 つの属性を定義します。
fieldPath: ログエントリのLogEntryフィールドの特定のパスを指定します。例:jsonPayload.req_status。type: フィールドが文字列型か整数型かを指定します。指定できる値はINDEX_TYPE_STRINGまたはINDEX_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 を使用します。次のように、メソッドの引数を準備します。
バケットを作成するリソース(
projects/PROJECT_ID/locations/LOCATION)をparentパラメータに設定します。変数 LOCATION には、ログを保存するリージョンを指定します。
たとえば、リージョン
asia-east2にプロジェクトmy-projectのバケットを作成する場合、parentパラメータはprojects/my-project/locations/asia-east2のようになります。bucketIdパラメータを設定します。例:my-bucketLogBucketリクエスト本文で、IndexConfigオブジェクトを構成してカスタム インデックスを作成します。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 リクエスト本文で、インデックスに登録する LogEntry フィールドを含むように IndexConfig オブジェクトを構成します。
カスタム インデックス フィールドを削除する
バケットのカスタム インデックスからフィールドを削除するには、次の操作を行います。
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=LOG_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 も一致しません。