syslog/rsyslog 如何处理多行日志记录(如堆栈跟踪)?
syslog 消息边界由传输分帧决定;多行文件日志可在 rsyslog 配置 multiline 支持(imfile 的 startmsg.regex),或在采集侧/解析侧做行合并。本文介绍配置方法。
多行文件日志(Java 堆栈等)可能被逐行采集拆散,但 syslog 本身不统一限定一行一条。文件采集可用:用 rsyslog imfile 模块的 startmsg.regex 参数定义新消息的开始模式,把后续行合并进上一条。
imfile 多行配置
module(load="imfile")
input(type="imfile"
File="/var/log/myapp/app.log"
Tag="myapp"
startmsg.regex="^[0-9]{4}-[0-9]{2}-[0-9]{2}"
readTimeout="5"
)
startmsg.regex 匹配"新日志行的开头"(如日期开头),不匹配的行被追加到上一条消息——Java 堆栈这样被合并成完整的一条。
旧式 legacy 语法
不要使用不存在的 $InputFileStartRegex 指令;多行起始正则应按上面的现代 input() 参数配置,并核对 rsyslog 版本支持。readTimeout 用于没有后续起始行时刷新待处理消息。
行内嵌入换行的替代方案
有些场景不改采集配置,而是在写入侧把多行转成单行:
- 日志框架输出 JSON(堆栈作为字段,换行转义为 \n);
- log4j 配置 PatternLayout 把
%ex堆栈替换换行符。
接收端的处理
UDP 报文或 TCP framing 决定消息边界,并非每个换行必定拆成一条;若发送端已经把各行拆成独立消息,接收端就难以可靠重组。应先在采集端合并,再核对换行转义、传输 framing 与两端消息大小限制。
使用观测云 DataKit 读取文件时,可按多行日志配置设置 multiline_match 来识别一条新事件的行首。测试一条完整异常堆栈和紧随其后的正常日志,检查是否拆散或误合并,并核对长度限制与发送超时。
常见问题(FAQ)
Q:合并后的超长堆栈会被截断吗?
A:rsyslog 及上下游有消息大小限制,超长时可能截断或丢弃,行为取决于输入模块和配置;调整 maxMessageSize 后仍需端到端验证。
Q:正则写错了会怎样?
A:如果所有行都不匹配 startmsg.regex,可能持续合并/等待直到超时或达到限制,不会自动退化成逐行消息;如果所有行都匹配,则无法合并。先用小文件验证。
Q:Filebeat 怎么处理多行?
A:Filebeat 的 multiline.pattern + multiline.negate + multiline.match 配置,在采集端合并后发送。