Q6:Log4jをラップしたクラスで出力したログの位置情報(行番号など)を、ラッパークラスを呼び出した位置情報にするためには?

log()メソッドの使用

以下のようにLog4jをラップするクラスを作成し、そのクラス経由でログを出力することを考えます(これが良い方法かどうかは問わない)。

package sample;

public class MyLogger {
    private static Logger logger = Logger.getLogger(MyLogger.class);

    public void error(String message, Throwable t) {
        logger.error(message, t);
    }

    public void info(String message) {
        logger.info(message);
    }
}

この MyLogger クラスを使ってログ出力を行うクラスを次のように作成し、

package sample;

public class Sample {
    private static MyLogger logger = new MyLogger();

    public static void main(String[] args) {
        logger.info("info");
    }
}

以下のアペンダを用いてログ出力を行うと、

<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
  <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" value="%C (%F:%L) - %m%n"/>
  </layout>           
</appender>

次のように出力されます。

sample.MyLogger (MyLogger.java:11) - info

当然のことながら、ログには Mylogger クラスの logger.info() を実行した位置情報(クラス名, ファイル名, 行番号)が出力されます。しかし本来出力されて欲しいのはMyLogger クラスのメソッドを呼び出した位置の情報でしょう。

このような Log4j をラップしたクラスを使ってログ出力を行い、かつラップしたクラスを呼び出した位置の位置情報をログに出力したい場合は、log(String callerFQCN, Priority level, Object message, Throwable t) メソッドを使用します。以下は log メソッドを使用するよう変更した MyLogger クラスです。

public class MyLogger {

    private static final String FQCN = MyLogger.class.getName();
    private static Logger logger = Logger.getLogger(MyLogger.class);

    public void error(String message, Throwable t) {
        logger.log(FQCN, Level.ERROR, message, t);
    }

    public void info(String message) {
        logger.log(FQCN, Level.INFO, message, null);
    }
}

log メソッドの第1引数にはラップクラスのパッケージを含めたクラス名(FQCN)、第2引数はログレベル、第3引数, 第4引数はそれぞれログメッセージと例外オブジェクトです。この MyLogger によってログ出力を行うと、

sample.Sample (Sample.java:7) - info

このように MyLogger のメソッドを呼び出した位置の位置情報がログに出力されます。Log4j はログの位置情報を取得するために例外オブジェクトを生成し、そのスタックトレースを解析するといったことを行います。上記の log() メソッドの第1引数にラッパクラスの FQCN を渡すことにより、スタックトレース解析時にラッパクラス情報を除外してくれるようになり、期待する結果が得られるようになります。

注意点

PatternLayoutで %c を使用してログのロガー名(=ほとんどの場合クラス名)を出力すると、MyLogger のロガー名が出力されます。例えば以下のようにアペンダを定義した場合、

<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
  <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" value="%c - %m%n"/>
  </layout>           
</appender>

次のように出力されます。

sample.MyLogger - info

%C を使えば sample.Sample と出力されますが、その代わり速度は大幅に低下します。位置情報を出力する変換パターン記号を使う場合にのみ有効な方法ですので、その点だけ注意が必要です。


トップページへ戻る