定制 1.6.x 日志记录代理,以支持在协调环境中使用 Log4j 的 Java 应用程序的自定义多行解析

本教程演示如何为 Java 应用程序配置 IBM® Cloud Logs 日志记录代理 多行日志处理,使用 Log4j 多行日志处理。 该配置适用于协调环境,例如 IBM Cloud Kubernetes Service 和 Red Hat OpenShift on IBM Cloud,并使用 Helm。 此配置可确保堆栈跟踪和多行日志在 IBM Cloud Logs 中正确分组。

本教程需要 IBM Cloud Logs 日志记录代理 1.6.0 或更高版本。

准备工作

在开始使用本教程之前,请查看以下信息以了解 日志记录代理 和多行概念。

本教程还假定您拥有

Log4j 配置示例

假设您的 Java 应用程序的 Log4j 日志到控制台 (stdout) 类似于下面的内容:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

该配置以以下格式输出日志:yyyy-MM-dd HH:mm:ss.SSS [thread] LEVEL logger - message 后跟换行符。 多行信息(如堆栈跟踪)将显示在没有时间戳前缀的后续行中。 例如:

2025-07-28 10:32:15.423 [main] INFO com.example.logging.Main - Application starting up
2025-07-28 10:32:16.191 [main] INFO com.example.logging.Main - This is an info message
2025-07-18 10:32:18.801 [main] ERROR com.example.logging.Main - This is an error message
java.lang.NullPointerException: null
at com.example.logging.Main.lambda$main$3(Main.java:30) ~[java-log4j-1.0.0.jar:?]
at spark.RouteImpl$1.handle(RouteImpl.java:72) ~[java-log4j-1.0.0.jar:?]
at spark.http.matching.Routes.execute(Routes.java:61) ~[java-log4j-1.0.0.jar:?]
at spark.http.matching.MatcherFilter.doFilter(MatcherFilter.java:134) ~[java-log4j-1.0.0.jar:?]
at spark.embeddedserver.jetty.JettyHandler.doHandle(JettyHandler.java:50) ~[java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1584) ~[java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.server.Server.handle(Server.java:501) ~[java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383) ~[java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:556) [java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375) [java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273) [java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) [java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) [java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) [java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806) [java-log4j-1.0.0.jar:?]
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938) [java-log4j-1.0.0.jar:?]
at java.lang.Thread.run(Unknown Source) [?:?]

使用 Helm

如果使用 Helm 部署 日志记录代理,可以在 Helm values.yaml 文件中配置多行解析。

启用多行解析

values.yaml 文件中将 enableMultiline 设置为 true,以激活多行处理:

enableMultiline: true

定义多行分析器

values.yaml 文件的 additionalMultilineParsers 部分下添加自定义多行分析器。

log4j.xml 文件中定义的模式必须与多行分析器中的 regex 一致,以确保正确的日志分组。

示例:

additionalMultilineParsers:
  - name: multiline-java-example
    type: regex
    flush_timeout: 500
    rules:
      - state: start_state
        regex: '/^(\d+-\d+-\d+ \d+:\d+:\d+\.\d+)(.*)$/'
        next_state: cont
      - state: cont
        regex: '/^(?!\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*$/'
        next_state: cont

该 regex 假定每个新日志行都以格式为 yyyy-MM-dd HH:mm:ss.SSS 的时间戳开始。 第一条规则捕捉带有时间戳的起始行,并移动到延续状态。 第二条规则匹配任何不以时间戳开头的行。

这种方法只是举例说明如何确保多行日志(如 Java 堆栈跟踪和异常)在转发到 IBM Cloud Logs 之前被归类为单个日志条目。 要实现同样的目标,有不同的方法。

定义多行预处理器

multilinePreprocessor 部分下配置预处理器,将解析器应用于日志。

例如:

multilinePreprocessor:
  - name: multiline
    multiline.parser: multiline-java-example
    multiline.key_content: log

应用更改。

如果您安装了 日志记录代理 以前的版本,并通过直接在群集中修改配置映射更新了代理配置,请在运行 helm upgrade 命令前从群集中复制一份配置映射。 更新 日志记录代理 时,对配置地图所做的任何更改都将被覆盖。

更新 values.yaml 文件后,在部署中运行以下操作来应用更改。 这将重新生成必要的配置。

helm upgrade

验证多行日志

访问 IBM Cloud Logs 实例,确认多行条目(例如堆栈跟踪)已正确分组。

  1. 访问 IBM Cloud Logs 实例。

  2. 使用日志 探索日志图标 视图,验证多行条目分组是否正确。