1. 概要

ログファイルは有用な情報を伝えることがよくありますが、時間の経過とともに自然に大きくなります。 無期限に成長することを許可された場合、それらのサイズが問題になる可能性があります。

ロギングライブラリは、現在のログファイルを自動的に「ロール」またはアーカイブするローリングファイルアペンダーを使用してこの問題に対処し、特定の事前定義された条件が発生したときに新しいファイルへのロギングを再開して、不要なダウンタイムを防ぎます。

このチュートリアルでは、最も広く使用されているロギングライブラリのいくつか(Log4j、Log4j2、およびSlf4j)でローリングファイルアペンダーを構成する方法を学習します。

サイズ、日付/時刻、およびサイズと日付/時刻の組み合わせに基づいてログファイルをロールする方法を示します。 また、古いログファイルを自動的に圧縮し、後で削除して、面倒なハウスキーピングコードを記述しないように、各ライブラリを構成する方法についても説明します。

2. サンプルアプリケーション

いくつかのメッセージをログに記録するサンプルアプリケーションから始めましょう。 このコードはLog4jに基づいていますが、Log4j2またはSlf4jで動作するように簡単に変更できます。

import org.apache.log4j.Logger;

public class Log4jRollingExample {

    private static Logger logger = Logger.getLogger(Log4jRollingExample.class);

    public static void main(String[] args) throws InterruptedException {
        for(int i = 0; i < 2000; i++) {
            logger.info("This is the " + i + " time I say 'Hello World'.");
            Thread.sleep(100);
        }
    }
}

アプリケーションは非常に素朴です。 反復間の短い遅延で、ループ内にいくつかのメッセージを書き込みます。 実行するループが2,000で、各ループで100ミリ秒の休止がある場合、アプリケーションの完了には3分強かかります。

このサンプルを使用して、さまざまな種類のローリングファイルアペンダーのいくつかの機能を示します。

3. Log4jのローリングファイルアペンダー

3.1. Mavenの依存関係

まず、アプリケーションでLog4jを使用するために、この依存関係をプロジェクトのpom.xmlファイルに追加します。

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

次の例で使用するapache-log-extrasによって提供される追加のアペンダーについては、次の依存関係を追加します。必ず、Log4jに対して宣言したのと同じバージョンを使用してください。完全な互換性を確保する:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>apache-log4j-extras</artifactId>
    <version>1.2.17</version>
</dependency>

Log4jおよびApacheLog4jExtrasの最新リリースはMavenCentralで見つけることができます。

3.2. ファイルサイズに基づくローリング

Log4jでは、他のログライブラリと同様に、ファイルのローリングはアペンダーに委任されます。 ファイルサイズに基づいてローリングするLog4jのローリングファイルアペンダーの構成を見てみましょう。

<appender name="roll-by-size" class="org.apache.log4j.RollingFileAppender">
    <param name="file" value="target/log4j/roll-by-size/app.log" />
    <param name="MaxFileSize" value="5KB" />
    <param name="MaxBackupIndex" value="2" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n" />
        </layout>
</appender>

ここでは、 MaxFileSize パラメーターを使用して、ログファイルのサイズが5KBに達したときにログファイルをロールするようにLog4jを構成しました。 また、 MaxBackupIndex パラメーターを使用して、最大2つのロールされたログファイルを保持するようにLog4jに指示しました。

サンプルアプリケーションを実行すると、次のファイルが取得されます。

27/11/2016  10:28    138 app.log
27/11/2016  10:28  5.281 app.log.1
27/11/2016  10:28  5.281 app.log.2

どうしたの? Log4jはapp.logファイルへの書き込みを開始しました。 ファイルサイズが5KBの制限を超えると、Log4jはapp.logapp.log.1に移動し、新しい空の app.log を作成して、書き込みを続行しましたapp.logへの新しいログメッセージ。

次に、新しい app.log が5KBの制限を超えた後、このローリングプロセスが繰り返されました。 今回は、 app.log.1app.log.2に移動され、別の新しい空のapp.log用のスペースが確保されました。

このローリングプロセスは実行中に数回繰り返されましたが、ローリングされたファイルを最大2つ保持するようにアペンダーを構成したため、app.log.3というファイルはありません。

生成されるログファイルのサイズに制限を設定できるようになったため、元の問題の1つを解決しました。

app.log.2 の最初の行を確認すると、700回目の反復に関連するメッセージが含まれています。これは、以前のすべてのログメッセージが失われたことを意味します。

2016-11-27 10:28:34 INFO  This is the 700 time I say 'Hello World'.

次に、ログメッセージを失うことが最善のアプローチとは見なされない、本番環境により適したセットアップを考案できるかどうかを見てみましょう。

これを行うには、apache-log4j-extrasと呼ばれる専用パッケージで出荷される他のより強力で柔軟で構成可能なLog4jアペンダーを使用します。

このアーティファクトに含まれるアペンダーは、ログローリングを微調整するための多くのオプションを提供し、トリガーポリシーおよびローリングポリシーの明確な概念を紹介します。 トリガーポリシーはロールが発生するタイミングを説明し、ローリングポリシーはローリングの実行方法を説明します。 これらの2つの概念は、ログファイルをローリングするための鍵であり、他のライブラリも多かれ少なかれ明示的にそれらを使用します。

3.3. 自動圧縮によるローリング

Log4jの例に戻り、ロールされたファイルの自動圧縮を追加してスペースを節約することにより、セットアップを改善しましょう。

<appender name="roll-by-size" class="org.apache.log4j.rolling.RollingFileAppender">
    <rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy">
        <param name="ActiveFileName" value="target/log4j/roll-by-size/app.log" />
        <param name="FileNamePattern" value="target/log4j/roll-by-size/app.%i.log.gz" />
    <param name="MinIndex" value="7" />
    <param name="MaxIndex" value="17" /> 
    </rollingPolicy>
    <triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy">
        <param name="MaxFileSize" value="5120" />
    </triggeringPolicy>
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n" />
    </layout>
</appender>

トリガーポリシー要素を使用して、ログが5,120バイトのサイズを超えたときにロールが発生する必要があることを示しました。

ローリングポリシータグ内で、 ActiveFileName パラメーターは、最新のメッセージを含むメインログファイルのパスを示し、FileNamePatternパラメーターはロールされたファイルのパスを説明するテンプレートを指定します。 特別なプレースホルダー%iがロールされたファイルのインデックスに置き換えられるため、これは確かにパターンであることに注意してください。

FileNamePatternが「.gz」拡張子で終わることにも注意してください。 サポートされている圧縮形式に関連付けられた拡張機能を使用する場合は常に、私たちの側から余分な労力をかけることなく、古いロールファイルを圧縮します。

これで、アプリケーションを実行すると、別のログファイルのセットが取得されます。

03/12/2016 19:24 88 app.1.log.gz
...
03/12/2016 19:26 88 app.2.log.gz
03/12/2016 19:26 88 app.3.log.gz
03/12/2016 19:27 70 app.current.log

ファイルapp.current.logは、最後のログが発生した場所です。 以前のログは、サイズが設定された制限に達するとロールおよび圧縮されます。

3.4. 日付と時刻に基づくローリング

他のシナリオでは、ファイルのサイズではなく、ログメッセージの日付と時刻に基づいてファイルをロールするようにLog4jを構成したい場合があります。 たとえば、Webアプリケーションでは、すべてのログメッセージを同じログファイルに1日で発行したい場合があります。

これを行うには、TimeBasedRollingPolicyを使用できます。 このポリシーでは、時間に関連するプレースホルダーを含むログファイルのパスのテンプレートを指定する必要があります。 ログメッセージが発行されるたびに、アペンダーは結果のログパスがどうなるかを確認します。 最後に使用したパスと異なる場合、ロールが発生します。 このようなアペンダーを構成する簡単な例を次に示します。

<appender name="roll-by-time"
    class="org.apache.log4j.rolling.RollingFileAppender">
    <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
        <param name="FileNamePattern" value="target/log4j/roll-by-time/app.%d{HH-mm}.log.gz" />
    </rollingPolicy>
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p - %m%n" />
    </layout>
</appender>

3.5. サイズと時間に基づくローリング

SizeBasedTriggeringPolicyTimeBasedRollingPolicyを組み合わせると、日付/時刻に基づいてロールするアペンダーを取得でき、ファイルのサイズが設定された制限に達すると、サイズにも基づいてロールします。 :

<appender name="roll-by-time-and-size" class="org.apache.log4j.rolling.RollingFileAppender">
    <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
        <param name="ActiveFileName" value="log4j/roll-by-time-and-size/app.log" />
        <param name="FileNamePattern" value="log4j/roll-by-time-and-size/app.%d{HH-mm}.%i.log.gz" />
    </rollingPolicy>
    <triggeringPolicy
        class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy">
        <param name="MaxFileSize" value="100" />
    </triggeringPolicy>
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p - %m%n" />
    </layout>
</appender>

この設定でアプリケーションを実行すると、次のログファイルが取得されます。

03/12/2016 19:25 234 app.19-25.1481393432120.log.gz
03/12/2016 19:25 234 app.19-25.1481393438939.log.gz
03/12/2016 19:26 244 app.19-26.1481393441940.log.gz
03/12/2016 19:26 240 app.19-26.1481393449152.log.gz
03/12/2016 19:26 3.528 app.19-26.1481393470902.log

file app.19-26.1481393470902.log は、現在のロギングが行われる場所です。 ご覧のとおり、19:25から19:26までのすべてのログは、「app.19-25」で始まる名前の複数の圧縮ログファイルに保存されます。「%i” プレースホルダーは、増え続ける数に置き換えられています。

4. Log4j2のローリングファイルアペンダー

4.1. Mavenの依存関係

Log4j2を優先ログライブラリとして使用するには、次の依存関係でプロジェクトのPOMを更新する必要があります。

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.7</version>
</dependency>

いつものように、最新バージョンはMavenCentralで見つけることができます。

4.2. ファイルサイズに基づくローリング

Log4j2ログライブラリを使用するようにサンプルアプリケーションを変更してみましょう。 log4j2.xml構成ファイルのログファイルのサイズに基づいてファイルローリングを設定します。

<RollingFile 
  name="roll-by-size" 
  fileName="target/log4j2/roll-by-size/app.log"
  filePattern="target/log4j2/roll-by-size/app.%i.log.gz" 
  ignoreExceptions="false">
    <PatternLayout>
        <Pattern>%d{yyyy-MM-dd HH:mm:ss} %p %m%n</Pattern>
    </PatternLayout>
    <Policies>
        <OnStartupTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="5 KB" />
    </Policies>
</RollingFile>

Policies タグで、適用するすべてのトリガーポリシーを指定しました。 OnStartupTriggeringPolicy は、アプリケーションが起動するたびにロールをトリガーします。これは、スタンドアロンアプリケーションに役立ちます。 また、 SizeBasedTriggeringPolicy、を指定して、ログファイルが5KBに達するたびにロールが発生するように指定しました。

4.3. 日付と時刻に基づくローリング

Log4j2が提供するポリシーを使用して、時間に基づいてログファイルをロールおよび圧縮するアペンダーを設定します。

<RollingFile name="roll-by-time" 
  fileName="target/log4j2/roll-by-time/app.log"
  filePattern="target/log4j2/roll-by-time/app.%d{MM-dd-yyyy-HH-mm}.log.gz"
  ignoreExceptions="false">
    <PatternLayout>
        <Pattern>%d{yyyy-MM-dd HH:mm:ss} %p %m%n</Pattern>
    </PatternLayout>
    <TimeBasedTriggeringPolicy />
</RollingFile>

ここで重要なのはTimeBasedTriggeringPolicy、です。これにより、ロールされたファイル名のテンプレートで時間関連のプレースホルダーを使用できます。 必要なトリガーポリシーは1つだけなので、前の例のようにPoliciesタグを使用する必要はないことに注意してください。

4.4. サイズと時間に基づくローリング

前に説明したように、より説得力のあるシナリオは、時間とサイズの両方に基づいてログファイルをロールおよび圧縮することです。 このタスク用にLog4j2を設定する方法の例を次に示します。

<RollingFile name="roll-by-time-and-size" 
  fileName="target/log4j2/roll-by-time-and-size/app.log"
  filePattern="target/log4j2/roll-by-time-and-size/app.%d{MM-dd-yyyy-HH-mm}.%i.log.gz" 
  ignoreExceptions="false">
    <PatternLayout>
        <Pattern>%d{yyyy-MM-dd HH:mm:ss} %p %m%n</Pattern>
    </PatternLayout>
    <Policies>
        <OnStartupTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="5 KB" />
        <TimeBasedTriggeringPolicy />
    </Policies>
    <DefaultRolloverStrategy>
        <Delete basePath="${baseDir}" maxDepth="2">
            <IfFileName glob="target/log4j2/roll-by-time-and-size/app.*.log.gz" />
            <IfLastModified age="20d" />
        </Delete>
    </DefaultRolloverStrategy>
</RollingFile>

この構成では、時間とサイズに基づいてロールが発生する必要があると述べました。 アペンダーは、ファイル名「app。%d{MM-dd-yyyy-HH-mm}。%i.log」に使用されているパターンにより、参照している時間間隔を理解できます。 .gz” 。これは、ロールが1分ごとに発生するように暗黙的に設定し、ロールされたファイルを圧縮します。

また、 DefaultRolloverStrategy を追加して、特定の基準に一致する古いロールファイルを削除しました。 20日以上経過した場合に、指定されたパターンに一致するファイルを削除するように構成しました。

4.5. Mavenの依存関係

Log4j2を優先ログライブラリとして使用するには、次の依存関係でプロジェクトのPOMを更新する必要があります。

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.7</version>
</dependency>

いつものように、最新バージョンはMavenCentralで見つけることができます。

5. Slf4jのローリングファイルアペンダー

5.1. Mavenの依存関係

LogbackバックエンドでSlf4j2をログライブラリとして使用する場合は、この依存関係をpom.xmlに追加します。

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.6</version>
</dependency>

いつものように、最新バージョンはMavenCentralで見つけることができます。

5.2. ファイルサイズに基づくローリング

次に、デフォルトのバックエンドLogbackでSlf4jを使用する方法を見てみましょう。 アプリケーションのクラスパスに配置されている構成ファイルlogback.xmlでファイルローリングを設定します。

<appender name="roll-by-size" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>target/slf4j/roll-by-size/app.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
        <fileNamePattern>target/slf4j/roll-by-size/app.%i.log.zip</fileNamePattern>
        <minIndex>1</minIndex>
        <maxIndex>3</maxIndex>
        <totalSizeCap>1MB</totalSizeCap>
    </rollingPolicy>
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
       <maxFileSize>5KB</maxFileSize>
    </triggeringPolicy>
    <encoder>
        <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
</appender>

ここでも、ローリングポリシーの概念に遭遇します。 基本的なメカニズムは、Log4jおよびLog4j2で使用されるメカニズムと同じです。 FixedWindowRollingPolicy を使用すると、ロールされたファイルの名前パターンでインデックスプレースホルダーを使用できます。

ログファイルのサイズが設定された制限を超えると、新しいファイルが割り当てられます。 古いコンテンツはリストの最初のファイルとして保存され、既存のコンテンツがさらに1つ移動します。

5.3. 時間に基づくローリング

Slf4jでは、提供されている TimeBasedRollingPolicy を使用して、時間に基づいてログファイルをロールできます。 このポリシーにより、日時に関連するプレースホルダーを使用して、ローリングファイルのテンプレート名を指定できます。

<appender name="roll-by-time" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>target/slf4j/roll-by-time/app.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>target/slf4j/roll-by-time/app.%d{yyyy-MM-dd-HH-mm}.log.zip
        </fileNamePattern>
        <maxHistory>20</maxHistory>
        <totalSizeCap>1MB</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} %p %m%n</pattern>
    </encoder>
</appender>

5.4. サイズと時間に基づくローリング

時間とサイズの両方に基づいてファイルをロールする必要がある場合は、提供されているSizeAndTimeBasedRollingPolicyを使用できます。 このポリシーを使用するときは、時間関連のプレースホルダーとインデックスプレースホルダーの両方を指定する必要があります。

特定の時間間隔のログファイルのサイズが構成されたサイズ制限を超えるたびに、時間関連のプレースホルダーの値が同じで、インデックスが増分された別のログファイルが作成されます。

<appender name="roll-by-time-and-size"
    class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>target/slf4j/roll-by-time-and-size/app.log</file>
    <rollingPolicy
      class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <fileNamePattern>
            target/slf4j/roll-by-time-and-size/app.%d{yyyy-MM-dd-mm}.%i.log.zip
        </fileNamePattern>
        <maxFileSize>5KB</maxFileSize>
        <maxHistory>20</maxHistory>
        <totalSizeCap>1MB</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} %p %m%n</pattern>
    </encoder>
</appender>

6. 結論

この記事では、ログライブラリを利用してファイルをロールすることで、ログファイルを手動で管理する負担を軽減できることを学びました。 代わりに、ビジネスロジックの開発に集中できます。 ローリングファイルアペンダーは、すべての開発者のツールボックスに含まれているはずの貴重なツールです。

いつものように、ソースはGitHub 利用できます。この記事で紹介するサンプルアプリケーションは、いくつかの異なるローリングセットアップを使用してログに記録するように構成されており、適切な基本構成を見つけて、さらに調整することができます。私たちのニーズ。