Fluentd 如何解析嵌套 JSON 字段?
Fluentd 解析嵌套 JSON 的两步:parser 先用 json 解析器解析整条日志,字符串类型的内嵌 JSON 字段再用 filter 阶段的 json 解析器二次展开。本文给出完整配置与 record_accessor 点路径用法。
两层处理:第一层 <parse> @type json </parse> 解析日志本体;如果某个字段的值还是 JSON 字符串(如 request_body),第二层在 filter 里再对该字段执行一次 JSON 解析,解析结果可合并为字段;已经是对象的字段不应再当 JSON 字符串解析。
完整配置
<source>
@type tail
path /var/log/app/*.log
tag app.json
<parse>
@type json # 第一层:整行是 JSON
</parse>
</source>
<filter app.json>
@type parser
key_name request_body # 第二层:该字段的值是 JSON 字符串
reserve_data true
reserve_time true
<parse>
@type json
</parse>
</filter>
<match app.json>
@type stdout
</match>
<label @ERROR>
<match **>
@type stdout
</match>
</label>
原始日志:
{"level":"INFO","request_body":"{\"order_id\":123,\"amount\":99.5}"}
解析后 order_id、amount 成为顶层可检索字段。
访问深层字段
record_accessor 是部分 Fluentd 插件使用的 helper,不是需要安装的独立插件。record_transformer 中使用 Ruby 访问嵌套对象:
<filter app.json>
@type record_transformer
enable_ruby true
<record>
user_city ${record.dig("user", "profile", "city")}
</record>
</filter>
常见问题(FAQ)
Q:字段值有时不是 JSON 会报错吗? 解析失败通常发往 @ERROR;应配置该 label 的输出。reserve_data true 时,常见缺键或无解析结果的记录也可能继续正常路由,因此错误路由不保证隔离或去重;意外异常路径可能不同。它不会自动给正常记录统一加 parse error 字段。
上述 dig 允许缺键得到 nil,但要求中间存在的 user/profile 值具有预期对象类型。
Q:数组怎么展开? record_accessor 支持 [0] 下标;要把数组元素拆成多条事件需要用专门插件。