- PR -

log4jのgetLoggerに指定するクラス名について

投稿者投稿内容
未記入
常連さん
会議室デビュー日: 2007/07/18
投稿数: 26
投稿日時: 2007-10-07 18:18
こんばんは。

現在log4jを使用して、ログを出力していますが、
その際以下のようにして、Loggerのオブジェクトを取得すると思います。

public class TestClass {
  private static final Logger log = Logger.getLogger(TestClass.class);
}


ここで、getLoggerに渡す引数は、クラス名にログを出力するクラス名に
すると思いますが、よく、別クラスから、上記1行をコピーして、
使う場合、クラス名の修正を忘れてしまうことがあります。

そこで、以下のようなクラス名を取得するUtilクラスを作成し、
以下のように使用しています。

// クラス名取得
public class Util {
  public static String getClassName(Throwable t) {
    if (t == null) {
      return "";
    }
    return t.getStackTrace()[0].getClassName();
  }
}


実際のgetLoggerは、以下のような感じです。

public class TestClass {
  private static final Logger log = Logger.getLogger(Util.getClassName(new Throwable()));
}


このようにすれば、コピーしても、動的にクラス名を取得できるので、
問題ないのですが、クラス名を取得するだけで、Throwableをnewするのは、
ちょっと、もったいない気がします。

みなさんは、どのようにされていますでしょうか?

また、よい方法があれば、ぜひ、教えてください。

あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-10-07 18:30
引用:

未記入さんの書き込み (2007-10-07 18:18) より:
このようにすれば、コピーしても、動的にクラス名を取得できるので、
問題ないのですが、クラス名を取得するだけで、Throwableをnewするのは、
ちょっと、もったいない気がします。


別にもったいなくないと思います。

実行されるのは各クラスのロード時に一回だけですし、
寿命も短いので第一世代GCで回収されるため無害です。

あと、そこまでやるなら、

コード:

public static Logger getCallerLogger() {
  return Logger.getLogger(new Throwable().getStackTrace()[1].getClassName());
}


の方が使い勝手がよいのでは?
Ray
ベテラン
会議室デビュー日: 2007/09/13
投稿数: 88
投稿日時: 2007-10-09 01:02
staticから使えませんが、継承が多いと宣言の必要すらありません。
フレームワークとの間に一枚かます場合によく使います。

public Logger log(){
return Logger.getLogger(getClass());
}

コストについて考える場合はそこだけ対応した方が効率的かと。
未記入
常連さん
会議室デビュー日: 2007/07/18
投稿数: 26
投稿日時: 2007-10-09 22:12
返信ありがとうございました。


> 実行されるのは各クラスのロード時に一回だけですし、
> 寿命も短いので第一世代GCで回収されるため無害です。

確かにそうですね。
ただ、newしているのがちょっと、もったいない気がしたもので、
質問させていただきました。


また、
  return Logger.getLogger(new Throwable().getStackTrace()[1].getClassName());

確かにそちらの方が、使い勝手がよいですね。
ありがとうございます。


> フレームワークとの間に一枚かます場合によく使います。

なるほど。ただ、やっぱりログを出力している、クラス名を
表示したいです。

今回は、どうもありがとうございました。



あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-10-09 22:32
引用:

未記入さんの書き込み (2007-10-09 22:12) より:
確かにそうですね。
ただ、newしているのがちょっと、もったいない気がしたもので、
質問させていただきました。


そうでもないです。第一世代のアロケーションは
ポインタを進める程度のコストで済むらしいですし、
JavaSE6ならエスケープ解析もあります。

この辺りの情報はIBM developerWorksに詳しい記事があります。
http://www-06.ibm.com/jp/developerworks/java/051104/j_j-jtp09275.shtml
flatline
大ベテラン
会議室デビュー日: 2005/09/22
投稿数: 102
投稿日時: 2007-10-09 23:18
私は、

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
:
:
private Log logger = LogFactory.getLog(this.getClass());

と記述して、コピペしてますね。

かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-10-10 13:40
>flatlineさん
それはあまりオススメしません。
何故かというと継承することによってロガーのファクトリの引数が変わってしまうためです。
「ベースクラスはログ出力いらないけど、継承したクラスのある部分ではログを出したい」
というような要件の時に困りますよ。

他のフレームワークのクラスを継承したときの、
基底クラスのログって結構うるさいですから。

SpringFrameworkも非staticでロガーを保持しているので、
オリジナルのApplicationContextを継承して作成したときに、
何故いらないログが出るんだ?ということで調べると、
そんな感じの現象でした。参考までに。
flatline
大ベテラン
会議室デビュー日: 2005/09/22
投稿数: 102
投稿日時: 2007-10-10 17:29
引用:

何故かというと継承することによってロガーのファクトリの引数が変わってしまうためです。
「ベースクラスはログ出力いらないけど、継承したクラスのある部分ではログを出したい」
というような要件の時に困りますよ。



それはわかっているのですが、そもそもログを出すようなクラスで、継承をあまり使用しないので、記述の簡易性(つまりコピペ可能)を優先してます。
アプリケーションの作り方にもよるでしょうが、個人的には作成するクラスの種類としては、
・Page(Form)系
・Action系
・Logic系
の3種類で、この中で継承する可能性があるのはPage系 だけ、ログを出す可能性があるのは、Logic系だけです。

スキルアップ/キャリアアップ(JOB@IT)