- PR -

log4jの使い方について

投稿者投稿内容
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-03-16 17:00
まず、これだとlognameが同じであればobjectのクラスが異なっても同じLoggerのインスタンスを
返すことになりますが、それは目的に合っていますか? それから、Category#getInstanceが
新しいLoggerのインスタンスを生成して返す、と思われているようですがそれは間違いです。
APIドキュメントを読めばわかるとおり、Logger#getLoggerと同じく、同じ引数に対しては
同じLoggerのインスタンスを返します。もしLoggerのインスタンスを自分で生成したいので
あれば、以下のようなクラスを作れば可能です。

public class CustomLogger extends Logger {
public CustomLogger(String name) {
super(name);
}
}
引用:

hiroさんの書き込み (2005-03-16 13:42) より:
自己スレです。

共通関数で以下のようにCategoryを新規作成することで実現できそうです。

・共通関数(LogManager.java)
--------------------------------------------------------------------------------
private static HashMap logger_map = null;
/**
* log4jのLogger獲得
*
* @param obj:呼出元オブジェクト
* @param logname:ログ名称
* @return 準備済みのLogger
*/
public static Logger setupLog(Object obj, String logname) {
try {
// Loggerキャッシュなし?
if( null==logger_map ) logger_map = new HashMap();
// 作成済みであればそれを返す
if( null!=logger_map.get(logname) ) return (Logger)logger_map.get(logname);

// CommonsのLog取得
Log log = LogFactory.getLog(obj.getClass());

// Log4Jを利用しているかチェック
if(log instanceof org.apache.commons.logging.impl.Log4JLogger){
//log.debug("Log4Jです log="+log);
try{
// DefaultのLogger取得
Logger nlogger = Logger.getLogger("DefaultLogger");
//log.debug("nlogger="+nlogger);

// デフォルトのAppenderを取得
// コンソール用
Appender A1 = nlogger.getAppender("A1");
// ファイル出力用
RollingFileAppender A2 = (RollingFileAppender) nlogger.getAppender("A2");
// 対象ファイル用のAppenderを新規作成
RollingFileAppender rfapd = new RollingFileAppender();
// デフォルトのAppenderオプション設定
rfapd.setMaximumFileSize(A2.getMaximumFileSize());
rfapd.setMaxBackupIndex(A2.getMaxBackupIndex());
rfapd.setAppend(A2.getAppend());
rfapd.setLayout(A2.getLayout());
// 出力先設定
rfapd.setFile(Param.getInstance().log_path + logname + ".log");
// オプションを有効化
rfapd.activateOptions();

// 対象Loggerを作成
Logger obj_logger = (Logger) Logger.getInstance(obj.getClass());
// ログ出力レベルを設定
obj_logger.setLevel(nlogger.getLevel());
// Appenderを追加
obj_logger.addAppender(A1);
obj_logger.addAppender(rfapd);
//log.info("setupLog: ログ出力先設定完了: "+Param.getInstance().log_path + logname + ".log");

// ヘッダを出力
String sep = System.getProperty("line.separator");
obj_logger.info(sep + sep + "<< ログ出力開始[" + Param.getInstance().log_path + logname + ".log" + "]>>");

// Loggerをキャッシュする
logger_map.put(logname,obj_logger);

// Log4JのLoggerをreturn(正常)
return obj_logger;

}catch(Exception ee){
System.out.println("エラー: ログが出力できません: log4j.propertiesがCLASSPATH上に見つかりません");
ee.printStackTrace();
}

}

} catch (Exception e) {
System.out.println("エラー: ログが出力できません: その他のエラー: "+e.toString());
e.printStackTrace();
}

//System.out.println("仮のLoggerを新規作成");
Logger logger = Logger.getLogger(obj.getClass());

return logger;
}
--------------------------------------------------------------------------------

LoggerはCategoryを継承しているので以上のような実現方法でも問題ないでしょうか?
またこの時、任意作成したLoggerをキャッシュして再利用するようにしているのですが、
log4jがスレッドセーフであるので共通関数で排他処理は実施していません。


hiro
常連さん
会議室デビュー日: 2004/09/02
投稿数: 21
投稿日時: 2005-03-17 11:58
uk殿
お世話になっております。
今回は、以下の対応でいこうと思ってます。
引用:

ukさんの書き込み (2005-03-16 17:00) より:
まず、これだとlognameが同じであればobjectのクラスが異なっても同じLoggerのインスタンスを返すことになりますが、それは目的に合っていますか?


目的にあっています。
理由:lognameが各業務処理の識別子となっているため。

引用:

それから、Category#getInstanceが新しいLoggerのインスタンスを生成して返す、と思われているようですがそれは間違いです。
APIドキュメントを読めばわかるとおり、Logger#getLoggerと同じく、同じ引数に対しては
同じLoggerのインスタンスを返します。


getLoggerのAPIで
「If the named logger already exists, then the existing instance will be returned. Otherwise, a new instance is created. 」
となっていたので任意のLogger名称を引数にした場合は、新規で作成されると思っています。
また、ログの管理単位は業務処理単位としたいので現状の処理で問題ないと思っています。

引用:

もしLoggerのインスタンスを自分で生成したいのであれば、以下のようなクラスを作れば可能です。

public class CustomLogger extends Logger {
public CustomLogger(String name) {
super(name);
}
}


上記のインスタンスを利用した場合は、CustomLogger#addAppenderでNullPointerが発生し、思った通りの動作は得られませんでした。


以上のことから、今回はLogger#getLoggerを利用したいと思います。
質問内容に多々不備があったことをお詫びします。
ありがとうございました。

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