全行索引¶
什么是全行索引¶
全行索引是一种日志全文检索方式。开启后,系统会将日志中的所有业务字段纳入全文索引。查询时,无需预先指定字段名称,输入任意业务字段的值,即可检索包含该值的日志。
例如,一条日志包含以下字段:
开启全行索引后,直接搜索 8d4f2a、O-1001 或 128.5,均可检索到该日志。
全行索引适用于以下场景:
- 日志已经提取为多个结构化字段,不再依赖一整段
message; - 需要从
trace_id、订单号、用户 ID 等不同业务字段中快速搜索; - 同一个日志索引包含多种日志结构,无法为所有日志预先确定统一的搜索字段;
- 希望保留字段化查询能力,同时支持跨业务字段的全文搜索。
与仅 message 索引的区别¶
| 对比项 | 仅 message 索引 |
全行索引 |
|---|---|---|
| 全文搜索范围 | 仅 message 字段 |
所有业务字段,包括存在的 message |
| 是否需要保留原始日志 | 需要保留 message |
不强制,可保留,也可在字段提取后删除 |
| 适合的数据 | 纯文本日志、未结构化日志 | JSON 日志、经过 Pipeline 提取的结构化日志 |
| 全文索引字段 | message |
variant |
全行索引只改变全文搜索范围,不会代替字段筛选。对于已提取的字段,仍可继续使用 service:order-api 等字段条件进行精确筛选、聚合或分析。
工作逻辑¶
系统通过 variant 统一承载全行索引中的业务字段,并仅为 variant 建立全文索引。
具体规则如下:
- 全行索引包含日志的业务字段,不包含系统字段;
- 日志不存在
message时,其他业务字段仍然可以参与全文搜索; - 日志存在
message时,系统不会删除该字段,而是将其作为普通业务字段写入variant; - 系统不会同时为
message和variant建立两份全文索引; - 同一个日志索引可以同时存储带
message和不带message的日志。
message 是否存在,由日志原始内容以及 DataKit、Pipeline 的实际处理结果决定。开启全行索引并不要求必须删除 message。
开启全行索引¶
- 进入日志 > 索引;
- 新建日志索引,或编辑目标日志索引;
- 展开高级选项;
- 在全文索引字段中选择全行索引;
- 保存配置。
前提条件
当前工作空间需要支持全行索引。如页面未显示该选项,请确认工作空间版本及相关功能权限。
使用全行索引查询¶
完成配置并写入日志后,进入日志 > 查看器,选择对应的日志索引。
查看器支持文本搜索、字段筛选、组合搜索、JSON 搜索和 DQL 查询等方式。完整的搜索语法和使用说明,参见查看器搜索。
全文搜索¶
在搜索框中输入业务字段的值,即可在所有业务字段中搜索,无需指定字段名称。
以上述订单日志为例:
- 输入
O-1001,可匹配order_id; - 输入
8d4f2a,可匹配trace_id; - 输入
order-api,可匹配service; - 日志保留
message时,也可以搜索message中的内容。
文本搜索会对输入内容进行分词。如果需要匹配完整、连续的内容,可以使用英文半角双引号包裹搜索内容。更多说明参见文本搜索。
字段筛选¶
如果已经知道字段名称,仍可使用字段条件缩小查询范围。例如:
全文搜索适合“不确定内容位于哪个字段”的场景;字段筛选适合已知字段名称、需要精确过滤或聚合分析的场景。两者可以结合使用。字段筛选的完整语法参见筛选。
查询注意事项¶
- 全行全文搜索只匹配业务字段,不匹配系统字段;
- 日志没有
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 中开启:
json_as_fields 是采集器配置,不是 HTTP URL 参数;该配置不作用于 influxdb、firelens 和 firehose 类型。
提取结果¶
原始日志:
{"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"}}
转换成功后:
timestamp、level、service、trace_id、order_id和amount成为独立字段;labels对象保存为紧凑 JSON 字符串;- DataKit 不再额外生成保存整段原始 JSON 的
message; - 如果原始 JSON 本身包含
message,该字段会正常保留。
主要字段转换规则如下:
- 顶层字符串、布尔值、整数和小数保持类型;对象和数组保存为紧凑 JSON 字符串;
null被忽略; - 非法 JSON、根节点不是对象或没有有效字段时,回退为原始
message; - 字段名中的
.会转换为_,换行符会转换为空格,字段名最长为 256 字节; - 每条日志最多保留 1024 个 field,不包含 tag;
- JSON 字段会覆盖采集器中的同名 tag 或 field;
- JSON 中的
time、source、date、storage_index会分别改名为json_time、json_source、json_date、json_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=["*"])
处理后会得到 service、status、trace_id、order_id 和 amount 等独立字段。
json_all() 只提取顶层字符串、数字和布尔值,不递归展开对象或数组,也不会保存 null。include_keys 和 key_patterns 均未配置时不会提取任何字段;需要提取所有顶层标量字段时,必须显式设置 key_patterns=["*"]。
只提取指定字段¶
这种方式可以控制进入全行索引的字段范围,也可以将不同日志中的字段统一为相同名称。
对象或数组不会被 json_all() 提取。需要保留此类内容时,可使用 json() 指定字段提取;提取结果会保存为 JSON 字符串。
提取字段后删除 message¶
通过 Pipeline 提取字段时,原始日志默认仍会保存在 message 中。如果结构化字段已经能够满足展示和查询需求,可以在完成字段提取后调用 drop_origin_data(),不再保存原始内容。
也可以在提取指定字段后删除:
json(_, service)
json(_, level, status)
json(_, trace_id)
json(_, order_id)
json(_, amount)
drop_origin_data()
如果 JSON 中本身包含 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 参与全文索引。
全行索引能否搜索系统字段?¶
不能。全行索引只包含业务字段,不包含系统字段。系统字段仍可通过字段筛选等方式查询。