配置自定义索引编制

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

概览

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

为了提高查询性能,Logging 会自动将以下 LogEntry 字段编入索引:

除了 Logging 自动编入索引的字段之外,您还可以通过为日志存储桶创建自定义索引来指示该日志存储桶将其他 LogEntry 字段编入索引。

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

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

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

准备工作

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

定义自定义索引

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

  • 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 逻辑)评估此限制条件。行为发生变化:

  • 如果索引是字符串类型,那么所有比较都是字符串比较。
    • “A”条目不匹配,因为“12345”不大于“20”字母数字。“B”条目匹配,因为字符串“3”大于“20”。
  • 如果索引是整数类型,则所有比较都是整数比较。
    • “B”条目不匹配,因为数字上“3”不大于“20”。“A”条目匹配,因为“12345”大于“20”。

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

过滤极端情况

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

jsonPayload.value = "hello"

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

不过,假设您对于字符串类型索引传递了一个整数值:

jsonPayload.value > 50

A 和 B 都不匹配,因为“12345”和“3”在字母数字上均不大于“50”。