Logstash 如何正确处理多行日志(如 Java 堆栈)?

Logstash 处理多行日志用 multiline codec:pattern 定义新日志行的开始模式,negate=true + what=previous 把不匹配的行追加到上一条。本文给出完整配置。

最佳实践
Logstash 如何正确处理多行日志(如 Java 堆栈)?封面

核心:在 file input 中使用 codec => multiline,通过 pattern 正则定义"新日志行的开头"(如时间戳),negate => true + what => "previous" 表示不匹配的行追加到上一条日志。

完整配置

input {
  file {
    path => "/var/log/myapp/*.log"
    start_position => "beginning"

    codec => multiline {
      pattern => "^\["          # 以 [ 开头的行是新日志
      negate => true            # 不匹配 pattern 的行...
      what => "previous"        # ...追加到上一条事件
    }
  }
}

原理解释

假设日志格式如下:

[2024-01-15 10:30:00] ERROR 处理请求失败
java.lang.NullPointerException
    at com.example.Service.process(Service.java:42)
    at com.example.Controller.handle(Controller.java:15)
[2024-01-15 10:30:01] INFO 请求完成
  • pattern => "^\[":以 [ 开头的行是新日志的开始;
  • negate => true:不以 [ 开头的行(堆栈行)不是新日志;
  • what => "previous":这些行追加到上一条日志中。

结果:Java 堆栈被合并为一条完整的日志事件,而不是每一行都是独立事件。

常见日志格式的 pattern

# 时间戳开头(YYYY-MM-DD)
pattern => "^\d{4}-\d{2}-\d{2}"

# log4j 风格 [LEVEL]
pattern => "^\[(TRACE|DEBUG|INFO|WARN|ERROR)\]"

# Python logging 默认格式
pattern => "^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}"

观测云对照

观测云 DataKit 的日志采集配置支持多行合并:通过 multiline_match 参数指定新日志行的正则(如 ^\\d{4}-\\d{2}-\\d{2}),堆栈自动合并为一条完整日志。Pipeline 解析时不再需要处理拆散的堆栈行。

常见问题(FAQ)

Q:多行日志超过一定行数会截断吗?
A:会。multiline codec 有 max_lines 参数(默认 500 行),超长的堆栈会被截断。可调整:max_lines => 1000

Q:多行事件会等待超时吗?
A:如果最后一条日志没有后续新行触发"刷新",它会一直等待。设置 auto_flush_interval => 5(秒)确保最后一条也能及时输出。

Q:Filebeat 也能处理多行吗?
A:能。Filebeat 的 multiline.pattern + multiline.negate + multiline.match 配置与 Logstash 类似,在采集端就做合并。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台