2013年10月2日水曜日

【ログ】log4jを動的に【java】

ログはデバッグ用に出力したり、エラー情報を出力したり、システム開発では必要不可欠である。
小規模開発では標準出力で事足りる場合もあるが、中、大規模開発になるとやはりファイルに残したい。
javaではlog4jという便利ライブラリがあるので安易にこれを使っている。
しかし、本当に便利なのだろうかと・・・・

log4jを使っている人はどれだけいるだろう・・・
これを使うからにはログ出力の必要性があり、ログを出力する機会が多いシステムに違いない。
そして、機能や用途ごとにログを出し分けてるに違いない。
log4jの定石(?)では、複数ファイルにログを出し分けるには、loggerとappenderをそれごとに設定ファイルに定義する。
これってとってもわずらわしくないですかね?僕だけでしょうか?
google先生に聞いても、loggerとappenderを複数定義する的な回答しか得られないんですよね・・・
みんなどうしてるのかなと疑問なんです。

そこで考えました。以下のような方法を。

 public static Logger getLogger(String name) {
  Logger logger = Logger.getLogger(name);

  Enumeration appenders = logger.getAllAppenders();
  if (!appenders.hasMoreElements()) {
   Logger base_logger = Logger.getLogger("base_logger");

   logger.setAdditivity(base_logger.getAdditivity());
   logger.setLevel(base_logger.getLevel());
   Enumeration base_appenders = base_logger.getAllAppenders();
   while (base_appenders.hasMoreElements()) {
    Appender appender = (Appender)base_appenders.nextElement();
    if (appender instanceof RollingFileAppender) {
     RollingFileAppender base_appender = (RollingFileAppender)appender;
     RollingFileAppender new_appender = new RollingFileAppender();
     new_appender.setFile(LogDir + "/" + name + ".log");
     new_appender.setAppend(base_appender.getAppend());
     new_appender.setMaximumFileSize(base_appender.getMaximumFileSize());
     new_appender.setMaxBackupIndex(base_appender.getMaxBackupIndex());
     Layout layout = base_appender.getLayout();
     if (layout instanceof PatternLayout) {
      PatternLayout new_layout = new PatternLayout(((PatternLayout) layout).getConversionPattern());
      new_appender.setLayout(new_layout);
     } else {
      System.err.println("no support layout");
     }
     new_appender.activateOptions();
     logger.addAppender(new_appender);
    } else {
     System.err.println("no support logger");
    }

   }

  }


設定ファイルには、ベースとなるloggerとappenderのみ定義します。
このメソッドは、{name} というLoggerにAppender の設定が無ければベースのAppenderの設定を元に、{name}.log というファイル名でログを出力するLogger を返します。
これで、いちいち出力ファイルを増やすたびに logger/appender の定義を追加する必要がなくなりました。
僕の場合、ファイル名以外の設定はほぼ共通でよかったのでベースの設定のみ定義しておくだけでよくなりました。
また、個別に{name}に対応する設定を追加してやれば、それだけ別の振る舞いをさせることができるので、log4jの設定ファイルというわずらわしさがかなり解消されました。