跳转至

全行索引


什么是全行索引

全行索引是一种日志全文检索方式。开启后,系统会将日志中的所有业务字段纳入全文索引。查询时,无需预先指定字段名称,输入任意业务字段的值,即可检索包含该值的日志。

例如,一条日志包含以下字段:

{
  "service": "order-api",
  "trace_id": "8d4f2a",
  "order_id": "O-1001",
  "amount": 128.5
}

开启全行索引后,直接搜索 8d4f2aO-1001128.5,均可检索到该日志。

全行索引适用于以下场景:

  • 日志已经提取为多个结构化字段,不再依赖一整段 message
  • 需要从 trace_id、订单号、用户 ID 等不同业务字段中快速搜索;
  • 同一个日志索引包含多种日志结构,无法为所有日志预先确定统一的搜索字段;
  • 希望保留字段化查询能力,同时支持跨业务字段的全文搜索。

与仅 message 索引的区别

对比项 message 索引 全行索引
全文搜索范围 message 字段 所有业务字段,包括存在的 message
是否需要保留原始日志 需要保留 message 不强制,可保留,也可在字段提取后删除
适合的数据 纯文本日志、未结构化日志 JSON 日志、经过 Pipeline 提取的结构化日志
全文索引字段 message variant

全行索引只改变全文搜索范围,不会代替字段筛选。对于已提取的字段,仍可继续使用 service:order-api 等字段条件进行精确筛选、聚合或分析。

工作逻辑

系统通过 variant 统一承载全行索引中的业务字段,并仅为 variant 建立全文索引。

不存在 message:
业务字段 → variant → 全文索引

存在 message:
message + 其他业务字段 → variant → 全文索引

具体规则如下:

  • 全行索引包含日志的业务字段,不包含系统字段;
  • 日志不存在 message 时,其他业务字段仍然可以参与全文搜索;
  • 日志存在 message 时,系统不会删除该字段,而是将其作为普通业务字段写入 variant
  • 系统不会同时为 messagevariant 建立两份全文索引;
  • 同一个日志索引可以同时存储带 message 和不带 message 的日志。

message 是否存在,由日志原始内容以及 DataKit、Pipeline 的实际处理结果决定。开启全行索引并不要求必须删除 message

开启全行索引

  1. 进入日志 > 索引
  2. 新建日志索引,或编辑目标日志索引;
  3. 展开高级选项
  4. 全文索引字段中选择全行索引
  5. 保存配置。
前提条件

当前工作空间需要支持全行索引。如页面未显示该选项,请确认工作空间版本及相关功能权限。

使用全行索引查询

完成配置并写入日志后,进入日志 > 查看器,选择对应的日志索引。

查看器支持文本搜索、字段筛选、组合搜索、JSON 搜索和 DQL 查询等方式。完整的搜索语法和使用说明,参见查看器搜索

全文搜索

在搜索框中输入业务字段的值,即可在所有业务字段中搜索,无需指定字段名称。

以上述订单日志为例:

  • 输入 O-1001,可匹配 order_id
  • 输入 8d4f2a,可匹配 trace_id
  • 输入 order-api,可匹配 service
  • 日志保留 message 时,也可以搜索 message 中的内容。

文本搜索会对输入内容进行分词。如果需要匹配完整、连续的内容,可以使用英文半角双引号包裹搜索内容。更多说明参见文本搜索

字段筛选

如果已经知道字段名称,仍可使用字段条件缩小查询范围。例如:

service:order-api

全文搜索适合“不确定内容位于哪个字段”的场景;字段筛选适合已知字段名称、需要精确过滤或聚合分析的场景。两者可以结合使用。字段筛选的完整语法参见筛选

查询注意事项

  • 全行全文搜索只匹配业务字段,不匹配系统字段;
  • 日志没有 message 时,查看器会组合当前日志的业务字段展示日志内容;
  • 系统字段不会作为全行索引日志内容的一部分;
  • 如果业务字段尚未从原始日志中提取,全行索引只能搜索当前实际存在的字段。因此,对于 JSON 或纯文本日志,可按下文方法先提取所需字段。

提取日志字段

全行索引会索引日志中已经存在的业务字段,但不会自动理解并拆分 message 中的内容。如果原始日志仍是一整段 JSON 或纯文本,可以通过 DataKit 或 Pipeline 将内容提取为结构化字段。

字段提取完成后,是否保留原始 message 由实际需求决定:

  • 需要查看完整原文或兼容原有使用习惯时,可以保留 message
  • 已有足够的结构化字段,不再需要保存原文时,可以删除 message
  • 无论是否保留 message,已提取的业务字段都可以参与全行全文索引。

使用 DataKit 提取 JSON 字段

适用于每行均为标准 JSON 对象、希望直接提取所有顶层字段的日志。DataKit 2.9.0 及以上版本可以开启 json_as_fields

开启后,DataKit 会在字符解码、ANSI 清理和多行合并后,将 JSON 根对象的顶层属性转换为日志字段,再执行 Pipeline。

主机日志采集

编辑 logging.conf

[[inputs.logging]]
  logfiles = ["/var/log/order/*.json"]
  source = "order"
  service = "order-api"
  json_as_fields = true

保存配置后,重启 DataKit

Kubernetes 容器日志采集

可通过 Pod Annotation 为指定容器开启 JSON 字段模式:

metadata:
  annotations:
    datakit/order-api.logs: >-
      [{"source":"order","service":"order-api","json_as_fields":true}]

其中,order-api 为容器名称。也可以在容器环境变量 DATAKIT_LOGS_CONFIG 中使用相同的 JSON 配置。

容器配置限制

json_as_fields 当前仅支持容器环境变量及 Pod Annotation/Label 中的 JSON 日志配置,暂不支持 ClusterLoggingConfig CRD。

Log Streaming

logstreaming.conf 中开启:

[inputs.logstreaming]
  json_as_fields = true

json_as_fields 是采集器配置,不是 HTTP URL 参数;该配置不作用于 influxdbfirelensfirehose 类型。

提取结果

原始日志:

{"timestamp":"2026-08-18T10:00:00+08:00","level":"INFO","service":"order-api","trace_id":"8d4f2a","order_id":"O-1001","amount":128.5,"labels":{"channel":"web"}}

转换成功后:

  • timestamplevelservicetrace_idorder_idamount 成为独立字段;
  • labels 对象保存为紧凑 JSON 字符串;
  • DataKit 不再额外生成保存整段原始 JSON 的 message
  • 如果原始 JSON 本身包含 message,该字段会正常保留。

主要字段转换规则如下:

  • 顶层字符串、布尔值、整数和小数保持类型;对象和数组保存为紧凑 JSON 字符串;null 被忽略;
  • 非法 JSON、根节点不是对象或没有有效字段时,回退为原始 message
  • 字段名中的 . 会转换为 _,换行符会转换为空格,字段名最长为 256 字节;
  • 每条日志最多保留 1024 个 field,不包含 tag;
  • JSON 字段会覆盖采集器中的同名 tag 或 field;
  • JSON 中的 timesourcedatestorage_index 会分别改名为 json_timejson_sourcejson_datejson_storage_index

完整规则参见 JSON 字段模式

使用 Pipeline 提取字段

适用于以下情况:

  • 只需要提取部分字段;
  • 需要重命名或转换字段;
  • 日志不是标准 JSON;
  • 已有 Pipeline 清洗流程,需要继续沿用。

提取所有顶层标量字段

DataKit 2.2.0 及以上版本可使用 json_all()

# 原始数据:
# {"service":"order-api","status":"info","trace_id":"8d4f2a","order_id":"O-1001","amount":128.5}

json_all(_, key_patterns=["*"])

处理后会得到 servicestatustrace_idorder_idamount 等独立字段。

json_all() 只提取顶层字符串、数字和布尔值,不递归展开对象或数组,也不会保存 nullinclude_keyskey_patterns 均未配置时不会提取任何字段;需要提取所有顶层标量字段时,必须显式设置 key_patterns=["*"]

只提取指定字段

json(_, service)
json(_, level, status)
json(_, trace_id)
json(_, order_id)
json(_, amount)

这种方式可以控制进入全行索引的字段范围,也可以将不同日志中的字段统一为相同名称。

对象或数组不会被 json_all() 提取。需要保留此类内容时,可使用 json() 指定字段提取;提取结果会保存为 JSON 字符串。

提取字段后删除 message

通过 Pipeline 提取字段时,原始日志默认仍会保存在 message 中。如果结构化字段已经能够满足展示和查询需求,可以在完成字段提取后调用 drop_origin_data(),不再保存原始内容。

json_all(_, key_patterns=["*"])
drop_origin_data()

也可以在提取指定字段后删除:

json(_, service)
json(_, level, status)
json(_, trace_id)
json(_, order_id)
json(_, amount)
drop_origin_data()

如果 JSON 中本身包含 message,并且该字段也被提取出来,可以根据需要保留或删除。明确不需要时,使用:

json_all(_, key_patterns=["*"])
drop_origin_data()
drop_key(message)

三个函数的作用不同:

  • drop_origin_data():不再输出初始化时保存的原始文本,整条日志仍会上传;
  • drop_key(message):删除已经提取出的 message 字段;
  • drop():丢弃整条日志,日志不会上传,不能用于删除 message
不要使用 drop() 删除 message

drop() 会把当前日志标记为待丢弃。Pipeline 执行结束后,整条日志都不会上传。

更多语法参见 json()json_all()drop_origin_data()drop_key()

本地验证 Pipeline

保存 Pipeline 脚本后,可在 DataKit 所在主机执行:

datakit pipeline -P full_line_json.p \
  -T '{"service":"order-api","status":"info","trace_id":"8d4f2a","order_id":"O-1001","amount":128.5}'

检查输出是否符合以下预期:

  • 需要检索的字段均已提取;
  • 如果配置了 drop_origin_data(),原始 message 已删除;
  • 日志未被标记为 drop: true
  • status 和日志时间等字段符合业务预期。

常见问题

全行索引必须删除 message 吗?

不需要。存在 message 时,系统会将其作为普通业务字段写入 variant,不会再为 message 单独建立一份全文索引。是否删除 message 应根据原始内容保留和展示需求决定。

开启全行索引后,为什么仍然搜不到 message 中的 JSON 字段?

如果整段 JSON 仍然只是 message 的字符串内容,其中的属性并不是独立业务字段。虽然可以搜索 message 中的文本,但无法直接使用这些属性进行字段筛选或聚合。建议使用 DataKit 或 Pipeline 先提取所需字段。

没有 message 时,日志查看器如何展示内容?

日志不存在 message 时,日志查看器会组合当前日志的业务字段展示日志内容;系统字段不会作为日志内容的一部分。

同一个索引能否同时存在带 message 和不带 message 的日志?

可以。两类日志都会按统一规则将业务字段写入 variant,由 variant 参与全文索引。

全行索引能否搜索系统字段?

不能。全行索引只包含业务字段,不包含系统字段。系统字段仍可通过字段筛选等方式查询。

文档评价

文档内容是否对您有帮助? ×