定制 1.6.x 日志记录代理,以支持在非协调环境中使用 Log4j 的 Java 应用程序的自定义多行解析功能
本教程演示如何为 Java 应用程序配置 IBM® Cloud Logs 日志记录代理 多行日志处理,使用 Log4j 多行日志处理。 该配置适用于非协调环境,例如 Linux 和 Windows,并修改配置文件。 此配置可确保堆栈跟踪和多行日志在 IBM Cloud Logs 中正确分组。
本教程需要 IBM Cloud Logs 日志记录代理 1.6.2 或更高版本。
准备工作
在开始使用本教程之前,请查看以下信息以了解 日志记录代理 和多行概念。
本教程还假定您拥有
本教程中的配置文件可在安装 日志记录代理 时下载的软件包文件中找到。
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) [?:?]
使用配置文件手动配置多行解析功能
如果使用配置文件手动配置 日志记录代理,可以通过编辑相应的 日志记录代理 配置文件来配置多行解析。
log4j.xml 文件中定义的模式必须与多行分析器中的 regex 一致,以确保正确的日志分组。
定义多行分析器
定义与 Log4j 输出模式匹配的自定义多行解析器。 该 regex 将以时间戳开头的行识别为新条目,并将其后不带时间戳的行视为前一个条目的延续。 将其添加到 日志记录代理 parsers.conf 文件中。
示例:
[MULTILINE_PARSER]
Name multiline-java-example
Type regex
Flush_timeout 500
Rule "start_state" "/^(\d+-\d+-\d+ \d+:\d+:\d+\.\d+)(.*)$/" "cont"
Rule "cont" "/^(?!\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*$/" "cont"
该 regex 假定每个新日志行都以格式为 yyyy-MM-dd HH:mm:ss.SSS 的时间戳开始。 第一条规则捕捉带有时间戳的起始行,并移动到延续状态。 第二条规则匹配任何不以时间戳开头的行。
这种方法只是举例说明如何确保多行日志(如 Java 堆栈跟踪和异常)在转发到 IBM Cloud Logs 之前被归类为单个日志条目。 要实现同样的目标,有不同的方法。
使用多行过滤器应用解析器
在 日志记录代理 filters.conf 文件中添加过滤器,以便将自定义解析器应用于与应用程序标记相匹配的日志。
例如:
[FILTER]
Name multiline
Match kube.*
Multiline.key_content log
Multiline.parser multiline-java-example
Emitter_Name multiline-java
重新启动代理程序
更新配置地图后,重新启动代理。
-
Linux 对于 环境,请运行 Linux
systemctl daemon-reload && systemctl restart fluent-bit -
Windows 对于 Windows 环境,请运行:
sc.exe stop fluent-bit && sc.exe start fluent-bit
验证多行日志
访问 IBM Cloud Logs 实例,确认多行条目(如堆栈跟踪)已正确分组。
-
使用日志
视图,验证多行条目分组是否正确。
分组日志数据包含在
log字段中。