配置自定义索引

本文档介绍了如何向 Cloud Logging 存储分区添加编入索引的 LogEntry 字段,以加快查询日志数据的速度。

概览

查询性能对任何日志记录解决方案都至关重要。随着工作负载扩容和相应日志量增加,对最常用的日志数据编入索引可以缩短查询时间。

为了提高查询性能,日志记录会自动为以下 LogEntry 字段编制索引:

除了 Logging 自动编制索引的字段之外,您还可以为存储桶创建自定义索引,以指示存储桶为其他 LogEntry 字段编制索引。

例如,假设您的查询表达式通常包含字段 jsonPayload.request.status。您可以为包含 jsonPayload.request.status 的存储桶配置自定义索引;如果查询表达式包含该字段,则对该存储桶数据的任何后续查询都会引用已编入索引的 jsonPayload.request.status 数据。

您可以使用 Google Cloud CLI 或 Logging API 将自定义索引添加到现有或新建的日志分桶。选择要添加到自定义索引中的其他字段时,请注意以下限制:

  • 每个自定义索引最多可以添加 20 个字段。
  • 配置或更新存储桶的自定义索引后,您必须等待一小时,以便更改应用于查询。此延迟时间可确保查询结果的正确性,并接受过去写入的日志。
  • 日志记录会在索引创建或更改后,将自定义索引应用于存储在日志存储分区中的数据;对自定义索引所做的更改不会向日志应用回溯。

准备工作

在开始配置自定义索引之前,请执行以下操作:

定义自定义索引

对于添加到存储桶的自定义索引中的每个字段,您都需要定义两个属性:字段路径和字段类型:

  • 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 会根据要评估的每个日志条目中数据的类型,将过滤条件应用于字段。启用索引后,系统会根据索引的类型应用对字段的过滤约束条件。为字段添加索引会对该字段强制执行架构。

为存储桶配置自定义索引后,如果同时满足以下两个条件,架构匹配行为会有所不同:

  • 字段的来源数据类型与该字段的索引类型不匹配。
  • 用户对该字段应用约束条件。

考虑以下 JSON 载荷:

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

现在,将此过滤条件应用于每个维度:

jsonPayload.value > 20

如果 jsonPayoad.value 字段缺少自定义索引,则日志记录会应用灵活类型匹配:

  • 对于“A”,Logging 会观察到“value”键的值实际上是整数,并且约束条件“20”可以转换为整数。然后,日志记录会评估 12345 > 20 并返回“true”,因为从数字上看,情况确实如此。

  • 对于“B”,Logging 会发现“value”键的值实际上是字符串。然后,它会评估 "3" > "20" 并返回“true”,因为从字母数字的角度来看,情况确实如此。

如果自定义索引中包含字段 jsonPayload.value,则 Logging 会使用该索引(而非常规 Logging 逻辑)来评估此约束条件。行为变更:

  • 如果索引是字符串类型,则所有比较都是字符串比较。
    • “A”条目不匹配,因为“12345”在字母数字顺序中不大于“20”。由于字符串“3”大于“20”,因此“B”条目匹配。
  • 如果编号是整数类型,则所有比较都是整数比较。
    • “B”条目不匹配,因为“3”在数字上不大于“20”。由于“12345”大于“20”,因此“A”条目匹配。

这种行为差异很细微,在定义和使用自定义索引时应予以考虑。

过滤边缘情况

对于 jsonPayload.value 整数类型的索引,假设要过滤字符串值:

jsonPayload.value = "hello"

如果无法将查询值强制转换为索引类型,则系统会忽略该索引。

不过,假设您为字符串类型的索引传递整数值:

jsonPayload.value > 50

由于“12345”和“3”的字母数字值均不大于“50”,因此 A 和 B 均不匹配。