Anpassung von 1.6.x Protokollierungsagent zur Unterstützung von benutzerdefiniertem mehrzeiligem Parsing für Java Anwendungen mit Log4j in nicht-orchestrierten Umgebungen

Dieses Tutorial zeigt, wie man die IBM® Cloud Logs Protokollierungsagent mehrzeilige Protokollierung für eine Java Anwendung mit Hilfe des Log4j logging-Framework. Diese Konfiguration ist für nicht-orchestrierte Umgebungen gedacht, z. B. Linux und Windows, und ändert die Konfigurationsdatei. Diese Konfiguration stellt sicher, dass Stack Traces und mehrzeilige Logs in IBM Cloud Logs korrekt gruppiert werden.

Für dieses Tutorial ist die Website IBM Cloud Logs Protokollierungsagent 1.6.2 oder höher erforderlich.

Vorbereitende Schritte

Bevor Sie mit diesem Lernprogramm beginnen, sollten Sie die folgenden Informationen lesen, um die Konzepte von Protokollierungsagent und Multiline zu verstehen.

Diese Anleitung setzt außerdem voraus, dass Sie über die entsprechenden Kenntnisse verfügen:

  • Eine bereitgestellte und konfigurierte IBM Cloud Logs-Instanz.

  • Die Protokollierungsagent wurde in einer nicht-orchestrierten Umgebung eingesetzt.

Die Konfigurationsdateien in diesem Tutorial finden Sie dort, wo die Paketdateien bei der Installation von Protokollierungsagent heruntergeladen wurden.

Beispielkonfiguration Log4j

Nehmen wir an, dass Ihre Anwendung Java Log4j zur Protokollierung auf der Konsole (stdout) ähnlich wie folgt aussieht:

<?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>

Diese Konfiguration gibt Protokolle im Format aus: yyyy-MM-dd HH:mm:ss.SSS [thread] LEVEL logger - message, gefolgt von einem Zeilenumbruch. Mehrzeilige Meldungen, wie z. B. Stack Traces, erscheinen in den nachfolgenden Zeilen ohne Zeitstempelpräfix. Zum Beispiel:

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) [?:?]

Manuelle Konfiguration des mehrzeiligen Parsings mit Hilfe einer Konfigurationsdatei

Wenn Sie Protokollierungsagent manuell mit Hilfe einer Konfigurationsdatei konfigurieren, können Sie das mehrzeilige Parsing konfigurieren, indem Sie die entsprechende Protokollierungsagent Konfigurationsdatei bearbeiten.

Es ist wichtig, dass das in der Datei log4j.xml definierte Muster mit der Regex im mehrzeiligen Parser übereinstimmt, um eine korrekte Protokollgruppierung zu gewährleisten.

Definieren Sie den mehrzeiligen Parser

Definieren Sie Ihren eigenen mehrzeiligen Parser, der dem Ausgabemuster Log4j entspricht. Die Regex identifiziert Zeilen, die mit dem Zeitstempel beginnen, als neue Einträge und behandelt nachfolgende Zeilen ohne Zeitstempel als Fortsetzungen des vorherigen Eintrags. Fügen Sie dies zu Ihrer Protokollierungsagent parsers.conf Datei hinzu.

Beispiel:

[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"

Die Regex geht davon aus, dass jede neue Protokollzeile mit einem Zeitstempel im Format yyyy-MM-dd HH:mm:ss.SSS beginnt. Die erste Regel erfasst Anfangszeilen mit Zeitstempeln und geht in einen Fortsetzungszustand über. Die zweite Regel entspricht jeder Zeile, die nicht mit einem Zeitstempel beginnt.

Dieser Ansatz ist nur ein Beispiel, um Ihnen zu zeigen, wie Sie sicherstellen können, dass mehrzeilige Protokollzeilen, wie Java Stack Traces und Exceptions, als ein einziger Protokolleintrag gruppiert werden, bevor sie an IBM Cloud Logs weitergeleitet werden. Es gibt verschiedene Möglichkeiten, das Gleiche zu erreichen.

Den Parser mit dem Mehrzeilenfilter anwenden

Fügen Sie einen Filter zu Ihrer Protokollierungsagent filters.conf Datei hinzu, um den benutzerdefinierten Parser auf Protokolle anzuwenden, die den Tags Ihrer Anwendung entsprechen.

Zum Beispiel:

[FILTER]
    Name              multiline
    Match             kube.*
    Multiline.key_content log
    Multiline.parser  multiline-java-example
    Emitter_Name      multiline-java

Starten Sie den Agenten erneut.

Starten Sie den Agenten nach der Aktualisierung der Konfigurationskarte neu.

  • Linux Für Linux Umgebungen, führen Sie:

    systemctl daemon-reload && systemctl restart fluent-bit
    
  • Windows Für Windows-Umgebungen, führen Sie:

    sc.exe stop fluent-bit && sc.exe start fluent-bit
    

Überprüfen Sie Ihre mehrzeiligen Protokolle

Rufen Sie Ihre Instanz IBM Cloud Logs auf und überprüfen Sie, ob Ihre mehrzeiligen Einträge (z. B. Stack Traces) korrekt gruppiert sind.

  1. Rufen Sie Ihre Instanz IBM Cloud Logs auf.

  2. Verwenden des Symbols „ Protokolle durchsuchen“ die Protokollansicht und überprüfen Sie, ob Ihre mehrzeiligen Einträge richtig gruppiert sind.

    Die gruppierten Protokolldaten werden in das Feld log aufgenommen.