syslog/rsyslog 如何处理多行日志记录(如堆栈跟踪)?
syslog 协议本身按行处理,多行日志需要 rsyslog 配置 multiline 支持(imfile 的 startmsg.regex),或在采集侧/解析侧做行合并。本文介绍配置方法。
syslog 协议以"一条消息一行"为基本假设,多行日志(Java 堆栈等)会被拆散。解决方案:用 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}"
)
startmsg.regex 匹配"新日志行的开头"(如日期开头),不匹配的行被追加到上一条消息——Java 堆栈这样被合并成完整的一条。
旧式 legacy 语法
$InputFileName /var/log/myapp/app.log
$InputFileTag myapp
$InputFileStartRegex "^[0-9]{4}-[0-9]{2}-[0-9]{2}"
$InputRunFileMonitor
行内嵌入换行的替代方案
有些场景不改采集配置,而是在写入侧把多行转成单行:
- 日志框架输出 JSON(堆栈作为字段,换行转义为 \n);
- log4j 配置 PatternLayout 把
%ex堆栈替换换行符。
接收端的处理
如果多行日志经 UDP syslog 发送,每行会成为独立报文,接收端无法可靠重组。多行内容不应走原生 syslog 传输,应在采集端(imfile/Filebeat/DataKit)合并后再发送。
观测云对照
观测云 DataKit 的日志采集配置中,multiline_match 参数指定新日志行的正则(如 ^\\d{4}-\\d{2}-\\d{2}),堆栈在采集侧即合并为完整日志,平台中检索时就是完整的一条。
常见问题(FAQ)
Q:合并后的超长堆栈会被截断吗?
A:rsyslog 有 $MaxMessageSize 限制(默认 8KB),超长消息被截断。可调大:$MaxMessageSize 64k。
Q:正则写错了会怎样?
A:如果所有行都不匹配 startmsg.regex,所有行各自成独立消息(等于没合并);如果所有行都匹配,则无法合并。先用小文件验证。
Q:Filebeat 怎么处理多行?
A:Filebeat 的 multiline.pattern + multiline.negate + multiline.match 配置,在采集端合并后发送。