Filebeat默认不合并多行日志,因其按行分割事件;需在filestream或log输入中显式配置multiline解析器,pattern应匹配日志起始行(如时间戳),negate: true + match: after才正确合并堆栈。

Filebeat 能可靠处理多行日志,但必须显式启用 multiline 解析器,且配置顺序和正则逻辑稍有偏差就会导致合并失败或漏行。
为什么默认不合并多行?
Filebeat 默认按行分割日志(每行一个事件),Java 异常堆栈、JSON 日志、带换行的 SQL 日志等会被切碎。只有在 filestream 或 log 输入中显式声明 multiline 解析器,它才开始尝试合并。
-
multiline是 parser,不是全局开关,必须嵌套在每个input的parsers(filestream)或同级(log)下 - Filebeat 7.16+ 推荐用
filestream类型,log类型已标记为 deprecated(但仍可用) - 匹配失败时,Filebeat 不报错,只是“当作单行处理”,这是最常被忽略的隐形故障
怎么写 multiline.pattern 才能匹配 Java 堆栈?
关键不是“匹配异常开头”,而是“识别新日志行的起始特征”。Java 日志通常以时间戳或类名开头,而堆栈中间行以空格或 at 、Caused by 开头 —— 这些该被合并,而不是触发新事件。
- 推荐 pattern:
^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}(匹配标准 Spring Boot 时间戳) - 或更宽松:
^\d{4}-\d{1,2}-\d{1,2}\s+\d{1,2}:\d{2}:\d{2}(适配不同格式) -
negate: true表示:**不匹配该 pattern 的行,就合并到上一行** -
match: after表示:把不匹配的行追加到前一个匹配行之后(即“堆栈属于上面那条日志”)
错误示例:pattern: 'Caused by|at ' + negate: false —— 这会让每行 at xxx 都变成独立事件,完全反效果。
多个路径 + 不同多行规则怎么配?
不能在一个 input 里混用多种 multiline 规则。每个路径组需单独定义 input,并各自绑定解析逻辑。
- 用
filestream类型时,每个 input 必须有唯一id,例如:id: "java-app-logs" - 路径支持 glob,如:
/data/app/logs/*.log,但避免跨业务混写(比如把 Nginx 和 Java 日志塞进同一个 input) - 若某路径下日志格式不统一(如同时含 access.log 和 error.log),优先拆成两个 input,分别配
tags和fields
示例片段:
filebeat.inputs:
- type: filestream
id: java-service-logs
paths: ["/data/service/logs/*.log"]
parsers:
- multiline:
type: pattern
pattern: '^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}'
negate: true
match: after
fields:
log_type: "java-service"
<ul><li>type: filestream
id: nginx-access-logs
paths: ["/var/log/nginx/access.log"]<h1>不配 parsers → 单行处理</h1><p>fields:
log_type: "nginx-access"容易被忽略的坑:clean_inactive 和 ignore_older
多行日志往往伴随轮转频繁、文件名带时间戳的场景。如果只配了 multiline 却没调清理策略,Filebeat 可能卡在旧文件末尾反复扫描,或错过刚轮转出的新文件。
-
ignore_older: 72h:跳过修改时间早于 72 小时的文件(防止扫历史归档) -
clean_inactive: 96h:对连续 96 小时无更新的文件,释放其 registry 状态(避免 registry 文件膨胀) - 二者必须配合使用;只设
ignore_older不清 registry,会导致 Filebeat 记住已删除文件的位置,下次启动时报错找不到文件
真正稳定的采集,从来不只是写对 pattern,而是 registry 行为、文件生命周期、输入类型三者对齐。

















