1.6.x ロギング・エージェント をカスタマイズし、非オーケストレーション環境での Log4j による Java アプリケーションのカスタム複数行構文解析をサポートする

このチュートリアルでは、 Java アプリケーションの IBM® Cloud Logs ロギング・エージェント 複数行ログ処理を設定する方法を示します。 Log4j ロギングフレームワークを使います。 このコンフィギュレーションは、 Linux や Windows などの非オーケストレーション環境用のもので、コンフィギュレーション・ファイルを変更する。 この設定により、スタックトレースとマルチラインログが IBM Cloud Logs で正しくグループ化される。

このチュートリアルには IBM Cloud Logs ロギング・エージェント 1.6.2 以降が必要です。

開始前に

このチュートリアルを使い始める前に、 ロギング・エージェント とマルチラインの概念を理解するために、以下の情報を確認してください。

また、このチュートリアルは、あなたが持っていることを前提としている:

  • IBM Cloud Logs インスタンスのプロビジョニングとコンフィギュレーション。

  • ロギング・エージェント、非オーケストレーション環境で展開された。

このチュートリアルで説明する設定ファイルは、 ロギング・エージェント をインストールした際にダウンロードしたパッケージファイルの場所にあります。

サンプル 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 ファイルで定義されたパターンが、マルチラインパーサーの正規表現と一致することが重要である。

マルチライン・パーサーの定義

Log4j 出力パターンにマッチするカスタム・マルチライン・パーサーを定義する。 正規表現は、タイムスタンプで始まる行を新しいエントリーとして識別し、タイムスタンプのない後続の行を前のエントリーの続きとして扱う。 ロギング・エージェント 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"

正規表現は、新しいログ行がそれぞれ yyyy-MM-dd HH:mm:ss.SSS. 最初のルールは、タイムスタンプを持つスタートラインをキャプチャし、継続状態に移行する。 2番目のルールは、タイムスタンプで始まらない行にマッチする。

このアプローチは、 Java スタックトレースや例外などの複数行のログ行を、 IBM Cloud Logs に転送する前に1つのログエントリとしてグループ化する方法を示す単なる例です。 同じことを達成するにも、さまざまな方法がある。

複数行フィルタでパーサーを適用する

ロギング・エージェント 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 インスタンスにアクセスし、マルチラインエントリ(スタックトレースなど)が正しくグループ化されていることを確認してください。

  1. IBM Cloud Logs インスタンスにアクセスします。

  2. Logs Explore logsアイコン ビューを使用して、マルチラインエントリーが正しくグループ化されていることを確認します。

    グループ化されたログデータは、 log フィールドに含まれる。