Docker 的 Fluentd 日志驱动如何处理多行日志?
Docker fluentd 日志驱动本身按行切割堆栈等多行日志,需配 fluentd 的 concat 过滤器按模式合并(如 Java 堆栈以空白开头并入上行)。本文给出 fluentd 侧 concat 配置与容器标签方案。
fluentd 日志驱动只负责按行转发,多行合并在 Fluentd 侧用 concat 过滤器完成:定义"新行起始模式"(如日期开头),不符合的行并入上一条——Java 堆栈、多行 SQL 就能还原为一条日志。
Fluentd concat 配置
<filter docker.**>
@type concat
key log # 消息字段名
multiline_start_regexp /^\d{4}-\d{2}-\d{2}/ # 新日志以日期开头
separator "" # 合并时不加分隔符
flush_interval 5
</filter>
驱动侧配置
docker run --log-driver=fluentd \
--log-opt fluentd-address=fluentd:24224 \
--log-opt tag="docker.{{.Name}}" \
myapp
tag 里带容器名,concat 的 key 对应 json 消息中的 log 字段。
注意事项
- concat 按 stream + 容器 分组缓冲,多副本交错输出可能串行——高并发场景在容器标签帮助下按容器隔离;
flush_interval是等待"后续行"的超时,太小会把正常多行切断;- 更稳的方案是应用直接输出单行 JSON(堆栈整体放字段里),天然无多行问题。
观测云对照
观测云 DataKit 容器日志采集支持行首正则多行合并,控制台配置即可;若应用直接输出 JSON,DataKit 自动解析为结构化字段,多行问题从源头消失。
常见问题(FAQ)
Q:concat 后时间戳是哪行的? 首行时间。
Q:能按"缩进行并入上行"吗? 可以:multiline_start_regexp /^\S/,非空白开头的才算新行。