torutkのブログ

ソフトウェア・エンジニアのブログ

[Java]Java SE標準ロギングのプロパティ設定で複数のファイルにログを分けて出力する

プロパティファイルでロギング設定をする場合、デフォルトではFileHandlerクラスに対してロガーへの紐付け、ファイル名、ログレベル、ローテーションなどを定義するルールとなっています。そのため、プロパティファイルを使った設定方法では、実レベルでよく必要となるログの用途に応じてファイルを分けるという運用を定義することができません。プロパティファイルではなくプログラムでAPIを読んで設定する必要があります。

ところが、これとは別のアプローチがありました。
http://stackoverflow.com/questions/3639694/java-util-logging-properties-how-to-log-to-two-different-files

これによると、標準のjava.util.logging.FileHandlerとは別に、FileHandlerのサブクラスを作ってしまうと、プロパティファイルから個別に設定をすることができるようになります。サブクラスといっても実装するのはコンストラクタでsuperを呼び出すだけなのでかなり単純です。

独自FileHandlerクラスの作成

package logging.auxiliary;

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.LogManager;

public class DebugFileHandler extends FileHandler {

    public DebugFileHandler() throws IOException {
        super(LogManager.getLogManager().getProperty("logging.auxiliary.DebugFileHandler.pattern"));
    }
}

独自FileHandlerと標準FileHandlerをプロパティファイルで設定

handlers = java.util.logging.FileHandler
.level = ALL

debug.handlers = logging.auxiliary.DebugFileHandler
debug.useParentHandlers = false

java.util.logging.FileHandler.pattern = myapp%u.log

logging.auxiliary.DebugFileHandler.pattern = myapp_debug%u.log

この設定で、通常のロガーの出力は標準FileHandlerへ、debugロガーの出力はDebugFileHandlerへ送られます。

debug.useParentHandlers = false を設定しているのは、デフォルトでは親ロガーのハンドラーにもログ出力が送られるので、同じログが両方のログファイルに出てしまうのを抑止するためです。

debugロガーは、ロガー名が debugまたはdebug.で始まる文字列に該当するので、用途に応じてロガー名を指定すればよいです。

また、独自のFileHandlerサブクラスを複数作れば、3つ以上のログファイルへの出力も可能です。

実際のところ、Java標準のロギングのプロパティファイル設計がいけてなさ過ぎるのですが、標準になっている以上この先ずっとしがらみを引き続けることになります。そんなJava標準ロギングでプロパティファイルでログを制御したい場合に活用できるテクニックの1つになるかと思います。