log4jメモ
log4j
commons-loggingとlog4jを使用する場合は下記の設定ファイルをクラスパス配下に置いておく。■commons-logging.properties
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
log4jの設定は「log4j.properties」に行う。
※もしくは「log4j.xml」にも可能だが、ここでは省略。
log4jの設定は、
- Category(かつてはLoggerだったらしい)
- Appender
- Layout
からなる。
Category
Category名はソースの中で下記のように指定する。(かつてはLoggerだったらしい)
// commons-logging Log log = LogFactory.getLog("[Category名]"); // log4j Logger log = Logger.getLogger("[Category名]");
ソースの中で指定したCategory名に対して、ログレベルとAppenderを下記のようにlog4j.propertiesで設定する。
# RootCategory(全てのCategory対する設定)(かつてはlog4j.rootLoggerという書きっぷりだったらしい) log4j.rootCategory=[ログレベル],[appenderName1],[appenderName2], ... # Category(かつてはlog4j.loggerという書きっぷりだったらしい) log4j.category.[Category名]=[ログレベル|INHERITED], [appenderName1], [appenderName2], ... # INHERITED と書くと、RootCategoryと同じレベルになる。
また、Categoryには下記のように階層構造を持つことができる。
- Root
- jp
- co
- hogehoge
- ClassA
- ClassB
- hogehoge
- hoge
- ClassC
- co
- org
- fuge
- ClassD
- fuge
- jp
このため、Category名の指定を下記のように行うと、パッケージ単位でログレベル、Appenderの設定が可能となる。
// commons-logging Log log = LogFactory.getLog(ClassA.class); // log4j Logger log = Logger.getLogger(ClassA.class);
例えば、上記のCategory階層(パッケージ階層)の例だと、下記のように設定するとClassAとClassBはログレベルにDEBUG、AppenderにA1とA2が設定される。
# Logger log4j.category.jp.co.hogehoge=DEBUG, A1, A2
はまりポイント
下記のようにrootCategoryと下位の階層のCategoryに同じAppenderを定義した場合、同じログが複数回出力されてしまう。
log4j.rootCategory=DEBUG, A1 log4j.category.jp.co.hogehoge=DEBUG, A1 log4j.category.jp.co.hogehoge.ClassA=DEBUG, A1
上記のように定義するとrootCategoryはjp.co.hogehogeもjp.co.hogehoge.ClassAの両方のCategoryを、jp.co.hogehogeはjp.co.hogehoge.ClassAのCategoryも含むため、ClassAで出力されるログはA1のAppenderに対して同じログを3回出力することになる。
なので、上位のCategoryのログ、Appenderの定義を引き継がないように下記のように記述を追加する必要がある。
log4j.additivity.jp.co.hogehoge=false log4j.additivity.jp.co.hogehoge.ClassA=false
上記の定義を追加することで、jp.co.hogehogeとjp.co.hogehoge.ClassAのCategoryは上位のCategoryのログ、Appdenderの定義を引き継がず、ClassAで出力されるログは1つとなる。
Appender
Categoryの設定のところで名前だけ設定したAppenderの設定を行う。
使用するAppenderとそのオプションの値を設定することができる。
log4j.appender.[Appender名]=[Appenderクラス] log4j.appender.[Appender名].[オプション]=[設定値]
■例(Appender名A1をコンソール出力で設定)
log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.Target=System.out
■Appenderクラス
- org.apache.log4j.ConsoleAppender
- コンソールにログ出力する
- org.apache.log4j.FileAppender
- ファイルにログ出力する
- org.apache.log4j.DailyRollingFileAppender
- ファイルにログ出力する。日次でログローテーションする
- org.apache.log4j.RollingFileAppender
- ファイルにログ出力する。一定サイズでログローテーションする。
- org.apache.log4j.net.JMSAppender JMSにログ出力する。
- org.apache.log4j.nt.NTEventLogAppender
- Windowsイベントログにログ出力する
- org.apache.log4j.net.SMTPAppender
- メールにログ出力する。
- org.apache.log4j.net.SocketAppender
- ソケットにログ出力する。
- org.apache.log4j.net.SyslogAppender
- Syslogにログ出力する。
- org.apache.log4j.AsyncAppender
- 非同期ログ出力
- org.apache.log4j.jdbc.JDBCAppender
- DBへログを出力する
■設定項目
Layout
Appenderに対して出力フォーマットの設定を行う。
log4j.appender.[Appender名].layout=[Layoutクラス] log4j.appender.[Appender名].layout.[オプション]=[設定値]
■例(Appender名A1のレイアウトを設定)
log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=[%d{yyyy/MM/dd HH:mm:ss.SSS}][%-5p][%t][%c{1}] %m%n
■レイアウトクラス
設定例
■log4j.properties
log4j.rootCategory=INFO, CONSOLE, FILE log4j.category.jp.co.hogehoge=DEBUG, CONSOLE log4j.category.jp.co.hogehoge.ClassA=DEBUG, FILE log4j.additivity.jp.co.hogehoge=false log4j.additivity.jp.co.hogehoge.ClassA=false log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.Target=System.out log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=[%d{yyyy/MM/dd HH:mm:ss}][%-5p][%t][%c{1}] %m%n log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender log4j.appender.FILE.DatePattern='.'yyyy-MM-dd log4j.appender.FILE.Append=true log4j.appender.FILE.File=/log/hoge.log log4j.appender.FILE.layout=org.apache.log4j.PatternLayout log4j.appender.FILE.layout.ConversionPattern=[%d{yyyy/MM/dd HH:mm:ss}][%-5p][%t][%c{1}] %m%n
■log4j.xml(上記log4j.propertiesと同じ設定)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.out" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{yyyy/MM/dd HH:mm:ss}][%-5p][%t][%c{1}] %m%n" /> </layout> </appender> <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender"> <param name="DatePattern" value="'.'yyyy-MM-dd" /> <param name="Append" value="true" /> <param name="File" value="/log/hoge.log" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{yyyy/MM/dd HH:mm:ss}][%-5p][%t][%c{1}] %m%n" /> </layout> </appender> <category name="jp.co.hogehoge" additivity="false"> <priority value="DEBUG" /> <appender-ref ref="CONSOLE" /> </category> <category name="jp.co.hogehoge.ClassA" additivity="false"> <priority value="DEBUG" /> <appender-ref ref="FILE" /> </category> <root additivity="false"> <priority value="INFO" /> <appender-ref ref="CONSOLE" /> <appender-ref ref="FILE" /> </root> </log4j:configuration>
log4j.xml独自設定
■org.apache.log4j.AsyncAppender
通常のアペンダクラスは、ログ出力は完了復帰タイプで、ログ出力指示をして処理が完了するまで、後続処理を実行しない。
しかし、アペンダクラス「org.apache.log4j.AsyncAppender」を使用すると、ログ出力指示だけして、処理終了を待たずに、後続処理が実行できるようになる。
つまり非同期でログ出力処理ができるようになる。
使い方は通常通り設定したAppenderに対してさらにappender-refでラッピングする形で書く。
■例
<appender name="FILE" class="rg.apache.log4j.DailyRollingFileAppender"> <param name="DatePattern" value="'.'yyyy-MM-dd" /> <param name="Append" value="true" /> <param name="File" value="/log/hoge.log" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{yyyy/MM/dd HH:mm:ss}][%-5p][%t][%c{1}] %m%n" /> </layout> </appender> <appender name="AsyncFILE"> <appender-ref ref="FILE" /> </appender>
ソースの書き方
Log log = LogFactory.getLog(ClassA.class); if(log.isDebugEnabled()){ log.debug("DEBUGレベルのログメッセージ"); } if(log.isInfoEnabled()){ log.info("INFOレベルのログメッセージ"); }
MDC(Mapped Diagnostic Context)
log4jの設定ファイルでlayoutのConversionPatternにて「"[%d{yyyy/MM/dd HH:mm:ss}][%-5p][%t][%c{1}] %m%n"」のようにメッセージのパターンを設定する。
「%X{key}」というパターンがあった場合、MDCを使用してメッセージを埋め込むことができる。
MDCは難しそうだが、ただのMapと考えてしまえばよい。
例えば
%X{hoge}
というパターンがあった場合
MDC.put("hoge", "ほげ");
ログレベル
ログレベル | 出力項目 | 出力内容 |
---|---|---|
TRACE | 性能ログ | 処理の開始・終了時間(ms) |
DEBUG | デバッグログ | 任意 |
INFO | アクセスログ 通信ログ |
サービスへのアクセス時刻、ユーザID、サービスを判別できるID(クラス名、メソッド名等) |
WARN | 業務エラーログ | 入力情報、例外情報 |
ERROR | システムエラーログ 監視ログ |
入力情報、システムエラー情報、監視ログは極力一行で |
※本番環境ではINFO以上を想定
参考:
http://www.techscore.com/tech/Java/ApacheJakarta/Log4J/index/
http://iihito.dip.jp/docs/java/no15/log-9.html
http://struts.wasureppoi.com/util/05_category.html
http://nobuit.blog56.fc2.com/?mode=m&no=115
http://www.nurs.or.jp/~sug/soft/log4j/log4j10.htm
http://www.nurs.or.jp/~sug/soft/log4j/log4j3.htm
http://d.hatena.ne.jp/torutk/20110429/p1
http://struts.wasureppoi.com/util/05_async.html
log4jに関連する話題
ログをDBへ出力したい場合
AppenderにJDBCAppenderを使用する。
しかし、DBのコネクションプールに対応していないため性能問題に発展するケースが多発すると思われる。
log4j 1.3では、コネクションプールに対応しているかわからないがDBAppenderというものになるようだ。
動的にlog4jの設定を変更したい場合
アプリケーションが起動している間にもlog4jの設定変更は可能だ。
例えば、ログレベルの変更は下記のようにソース中で変更できる。
// ルートカテゴリのログレベルの変更 Logger rootLogger = LogManager.getRootLogger(); rootLogger.setLevel(Level.INFO); // 他カテゴリのログレベルの変更 Logger logger = LogManager.getLogger(ClassA.class); logger.setLevel(Level.INFO);
さらにlog4jにはjmxから設定変更が可能のようだ。
「org.apache.log4j.jmx」パッケージにMBeanが提供されている。。。
log4jdbc
発行したSQLをログとして出力したいケースがある。
その場合、log4jdbcが使える。
参考:
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=26852&forum=12