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 "\n" # 保留多行边界
use_first_timestamp true
stream_identity_key source
timeout_label @CONCAT_TIMEOUT
flush_interval 5
</filter>
超时记录需要对应 label 输出,例如:
<label @CONCAT_TIMEOUT>
<match **>
@type stdout
</match>
</label>
这处理应用多行,不等同于 Docker 因长度拆分的 partial records 重组,后者需按插件 partial 配置处理。
驱动侧配置
docker run --log-driver=fluentd \
--log-opt fluentd-address=127.0.0.1:24224 \
--log-opt tag="docker.{{.ID}}" \
myapp
tag 里带容器 ID,concat 的 key 对应消息中的 log 字段,source 区分 stdout/stderr。fluentd-address 由 Docker 守护进程访问,不会自动使用应用容器的服务名解析;请替换为守护进程可达的地址。
注意事项
- concat 不会自动按容器与输出流隔离;本例用唯一容器 tag 和 stream_identity_key source 防止混合;
flush_interval是等待"后续行"的超时,太小会把正常多行切断;- 更稳的方案是应用直接输出单行 JSON(堆栈整体放字段里),天然无多行问题。
常见问题(FAQ)
Q:concat 后时间戳是哪行的? 仅在 use_first_timestamp true 时使用首条时间,本例已显式开启。
Q:能按"缩进行并入上行"吗? 可以:multiline_start_regexp /^\S/,非空白开头的才算新行。