便利なコードパーツ集!

やまろうのプログラミングTips

Java

Log4jがログを出力したソースファイル名、行番号等を出力する仕組みを解明

投稿日:

2006/07

Log4jでフォーマットに(%F:%L)を指定すると(HogeServlet.java:75)
みたくログを出力したソースファイル名や行番号を出力してくれますが、

「なんでソースファイル名や行番号が分かるんだろう?」

「何かJVMの力を借りたりして裏技なのかなぁ?」

ということでLog4jのクラスを調べてみると
org.apache.log4j.spi.LocationInfoというクラスで
ソースファイル名、行番号等を取得しているようです。

やり方はといと
「例外のStackTraceを文字列解析してる」だけでした。

つまり、
「ソースファイル名、行番号等を取得するためだけにわざわざ例外を
newしてStackTraceを文字列解析してるわけです。」

なんの裏技でもないわけです。
「コンピュータの世界に魔法なんてないんだよね。」

JDK1.4からStackTraceを文字列解析しなくても簡単に情報を取得できる
「java.lang.StackTraceElement」というクラスがあります。今回はそれを使って
ログを出力したクラス名、メソッド名、ソースファイル名、行番号を出力する
シンプルなロガークラスを作成します。

package log;

public class SimpleLogger {
  /**
   * ログを出力したクラス名、メソッド名、ソースファイル名、行番号、message
   * を出力する。
   * @param message ログに出力するメッセージ
   */
  public void debug(Object message) {
    /*
     * ログを出力したクラス名、メソッド名、ソースファイル名、行番号を
     * 取得するために例外をnewしてStackTraceElement[]を取得する。
     */
    StackTraceElement[] stackTrace = new Exception().getStackTrace();

    // StackTraceElement[]の一番後ろの要素がログを出力したクラスの情報になる。
    StackTraceElement info = stackTrace[stackTrace.length - 1];

    // 出力内容を編集して標準出力に出力する。      
    System.out.println(
      info.getClassName()
        + "."
        + info.getMethodName()
        + "("
        + info.getFileName()
        + ":"
        + info.getLineNumber()
        + ") "
        + message);
  }
}

package log;

public class Main {
  public static void main(String[] args) {
    SimpleLogger log = new SimpleLogger();
    log.debug("Hello SimpleLogger !!");
  }
}

[実行結果]

log.Main.main(Main.java:13) Hello SimpleLogger !!
スポンサーリンク

-Java

Copyright© やまろうのプログラミングTips , 2022 AllRights Reserved Powered by AFFINGER4.