まずは実行 †
com.snail.exam.log4j.Log4jExamApplication? †
package com.snail.exam.log4j;
import org.apache.log4j.Logger;
import com.snail.exam.log4j.app.buggy.BuggyClass;
import com.snail.exam.log4j.app.gentle.GentleClass;
public class Log4jExamApplication {
private static Logger logger = Logger.getLogger(Log4jExamApplication.class);
/**
* @param args
*/
public static void main(String[] args) {
logger.fatal("本当にやばいログ ");
logger.error("普通にやばいログ ");
logger.warn( "ちょっとやばいログ ");
logger.info( "運用時に必要なログ ");
logger.debug("開発時に必要なログ ");
logger.trace("デスマ時に必要なログ");
new BuggyClass().doSomething();
new GentleClass().doSomething();
}
}
com.snail.exam.log4j.app.buggy.BuggyClass? †
package com.snail.exam.log4j.app.buggy;
import org.apache.log4j.Logger;
public class BuggyClass {
private static Logger logger = Logger.getLogger(BuggyClass.class);
/**
* @param args
*/
public void doSomething() {
logger.fatal("本当にやばいログ ");
logger.error("普通にやばいログ ");
logger.warn( "ちょっとやばいログ ");
logger.info( "運用時に必要なログ ");
logger.debug("開発時に必要なログ ");
logger.trace("デスマ時に必要なログ");
}
}
com.snail.exam.log4j.app.gentle.GentleClass? †
package com.snail.exam.log4j.app.gentle;
import org.apache.log4j.Logger;
public class GentleClass {
private static Logger logger = Logger.getLogger(GentleClass.class);
/**
* @param args
*/
public void doSomething() {
logger.fatal("本当にやばいログ ");
logger.error("普通にやばいログ ");
logger.warn( "ちょっとやばいログ ");
logger.info( "運用時に必要なログ ");
logger.debug("開発時に必要なログ ");
logger.trace("デスマ時に必要なログ");
}
}
log4j.xml †
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<!-- STDOUT1 -->
<appender name="STDOUT1" class="org.apache.log4j.ConsoleAppender">
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="STDOUT1 [%-5p] %x %m from %c%n" />
</layout>
</appender>
<!-- STDOUT2 -->
<appender name="STDOUT2" class="org.apache.log4j.ConsoleAppender">
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="STDOUT2 [%-5p] %x %m from %c%n" />
</layout>
</appender>
<!-- STDOUT3 -->
<appender name="STDOUT3" class="org.apache.log4j.ConsoleAppender">
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="STDOUT3 [%-5p] %x %m from %c%n" />
</layout>
</appender>
<!-- LOGGER1 -->
<logger name="com.snail.exam.log4j.app.buggy">
<level value="debug"/>
<appender-ref ref="STDOUT3"/>
</logger>
<!-- LOGGER2 -->
<logger name="com.snail.exam.log4j.app">
<level value="info"/>
<appender-ref ref="STDOUT2"/>
</logger>
<!-- LOGGER ROOT -->
<root>
<priority value="warn" />
<appender-ref ref="STDOUT1" />
</root>
</log4j:configuration>
実行結果 †
STDOUT1 [FATAL] 本当にやばいログ from com.snail.exam.log4j.Log4jExamApplication
STDOUT1 [ERROR] 普通にやばいログ from com.snail.exam.log4j.Log4jExamApplication
STDOUT1 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.Log4jExamApplication
STDOUT1 [FATAL] 本当にやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT1 [ERROR] 普通にやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT1 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT1 [INFO ] 運用時に必要なログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT1 [DEBUG] 開発時に必要なログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT1 [FATAL] 本当にやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT1 [ERROR] 普通にやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT1 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT1 [INFO ] 運用時に必要なログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT2 [FATAL] 本当にやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT2 [ERROR] 普通にやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT2 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT2 [INFO ] 運用時に必要なログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT2 [DEBUG] 開発時に必要なログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT2 [FATAL] 本当にやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT2 [ERROR] 普通にやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT2 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT2 [INFO ] 運用時に必要なログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT3 [FATAL] 本当にやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [ERROR] 普通にやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [INFO ] 運用時に必要なログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [DEBUG] 開発時に必要なログ from com.snail.exam.log4j.app.buggy.BuggyClass
何でこうなるの? †
root と logger は継承関係にある †
- root
- STDOUT1 に、全てのパッケージの warn 以上のログを出力
- LOGGER2 : root + com.snail.exam.log4j.app
- STDOUT2 に、com.snail.exam.log4j.app.* のパッケージの info 以上のログを出力
- root からの継承
- STDOUT1 に、全てのパッケージの warn 以上のログを出力
- STDOUT1 に、com.snail.exam.log4j.app.* のパッケージの info 以上のログを出力
- LOGGER3 : root + com.snail.exam.log4j.app + com.snail.exam.log4j.app.buggy
- STDOUT3 に、com.snail.exam.log4j.app.buggy.* のパッケージの debug 以上のログを出力
- LOGGER2 からの継承
- STDOUT2 に、com.snail.exam.log4j.app.* のパッケージの info 以上のログを出力
- STDOUT2 に、com.snail.exam.log4j.app.buggy.* のパッケージの debug 以上のログを出力
- root からの継承
- STDOUT1 に、全てのパッケージの warn 以上のログを出力
- STDOUT1 に、com.snail.exam.log4j.app.* のパッケージの info 以上のログを出力
- STDOUT1 に、com.snail.exam.log4j.app.buggy.* のパッケージの debug 以上のログを出力
実行結果を検証 †
logger | class | trace | debug | info | warn | error | fatal |
STDOUT1 | com.snail.exam.log4j.Log4jExamApplication? | × | × | × | ○ | ○ | ○ |
com.snail.exam.log4j.app.buggy.BuggyClass? | × | ○ | ○ | ○ | ○ | ○ |
com.snail.exam.log4j.app.gentle.GentleClass? | × | × | ○ | ○ | ○ | ○ |
logger | class | trace | debug | info | warn | error | fatal |
STDOUT2 | com.snail.exam.log4j.Log4jExamApplication? | × | × | × | × | × | × |
com.snail.exam.log4j.app.buggy.BuggyClass? | × | ○ | ○ | ○ | ○ | ○ |
com.snail.exam.log4j.app.gentle.GentleClass? | × | × | ○ | ○ | ○ | ○ |
logger | class | trace | debug | info | warn | error | fatal |
STDOUT3 | com.snail.exam.log4j.Log4jExamApplication? | × | × | × | × | × | × |
com.snail.exam.log4j.app.buggy.BuggyClass? | × | ○ | ○ | ○ | ○ | ○ |
com.snail.exam.log4j.app.gentle.GentleClass? | × | × | × | × | × | × |
- つまり、logger の name の包含関係によって logger が継承関係になっている
logger に設定内容の継承をさせないようにする †
- logger に additivity="false" 属性を設定する
log4j.xml †
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<!-- STDOUT1 -->
<appender name="STDOUT1" class="org.apache.log4j.ConsoleAppender">
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="STDOUT1 [%-5p] %x %m from %c%n" />
</layout>
</appender>
<!-- STDOUT2 -->
<appender name="STDOUT2" class="org.apache.log4j.ConsoleAppender">
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="STDOUT2 [%-5p] %x %m from %c%n" />
</layout>
</appender>
<!-- STDOUT3 -->
<appender name="STDOUT3" class="org.apache.log4j.ConsoleAppender">
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="STDOUT3 [%-5p] %x %m from %c%n" />
</layout>
</appender>
<!-- LOGGER1 -->
<logger name="com.snail.exam.log4j.app.buggy" additivity="false">
<level value="debug"/>
<appender-ref ref="STDOUT3"/>
</logger>
<!-- LOGGER2 -->
<logger name="com.snail.exam.log4j.app" additivity="false">
<level value="info"/>
<appender-ref ref="STDOUT2"/>
</logger>
<!-- LOGGER ROOT -->
<root>
<priority value="warn" />
<appender-ref ref="STDOUT1" />
</root>
</log4j:configuration>
実行結果 †
STDOUT1 [FATAL] 本当にやばいログ from com.snail.exam.log4j.Log4jExamApplication
STDOUT1 [ERROR] 普通にやばいログ from com.snail.exam.log4j.Log4jExamApplication
STDOUT1 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.Log4jExamApplication
STDOUT3 [FATAL] 本当にやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [ERROR] 普通にやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [INFO ] 運用時に必要なログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [DEBUG] 開発時に必要なログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT2 [FATAL] 本当にやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT2 [ERROR] 普通にやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT2 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT2 [INFO ] 運用時に必要なログ from com.snail.exam.log4j.app.gentle.GentleClass
どちらかというと、こっちの方が期待した動きかな・・・
logger のログレベルと appender のログレベルの関係 †
- log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<!-- STDOUT1 -->
<appender name="STDOUT1" class="org.apache.log4j.ConsoleAppender">
<param name="threshold" value="warn" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="STDOUT1 [%-5p] %x %m from %c%n" />
</layout>
</appender>
<!-- STDOUT2 -->
<appender name="STDOUT2" class="org.apache.log4j.ConsoleAppender">
<param name="threshold" value="info" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="STDOUT2 [%-5p] %x %m from %c%n" />
</layout>
</appender>
<!-- STDOUT3 -->
<appender name="STDOUT3" class="org.apache.log4j.ConsoleAppender">
<param name="threshold" value="trace" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="STDOUT3 [%-5p] %x %m from %c%n" />
</layout>
</appender>
<!-- LOGGER1 -->
<logger name="com.snail.exam.log4j.app.buggy" additivity="false">
<level value="debug"/>
<appender-ref ref="STDOUT3"/>
</logger>
<!-- LOGGER2 -->
<logger name="com.snail.exam.log4j.app" additivity="false">
<level value="debug"/>
<appender-ref ref="STDOUT2"/>
</logger>
<!-- LOGGER ROOT -->
<root>
<priority value="debug" />
<appender-ref ref="STDOUT1" />
</root>
</log4j:configuration>
- 実行結果
STDOUT1 [FATAL] 本当にやばいログ from com.snail.exam.log4j.Log4jExamApplication
STDOUT1 [ERROR] 普通にやばいログ from com.snail.exam.log4j.Log4jExamApplication
STDOUT1 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.Log4jExamApplication
STDOUT3 [FATAL] 本当にやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [ERROR] 普通にやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [INFO ] 運用時に必要なログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT3 [DEBUG] 開発時に必要なログ from com.snail.exam.log4j.app.buggy.BuggyClass
STDOUT2 [FATAL] 本当にやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT2 [ERROR] 普通にやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT2 [WARN ] ちょっとやばいログ from com.snail.exam.log4j.app.gentle.GentleClass
STDOUT2 [INFO ] 運用時に必要なログ from com.snail.exam.log4j.app.gentle.GentleClass
- つまり、logger と appender で指定したログレベルのうち、厳しい方が使われる
logger | appender | 出力されるログレベル |
warn | debug | warn以上 |
info | debug | info以上 |
debug | debug | debug以上 |
debug | warn | warn以上 |
debug | info | info以上 |
debug | trace | debug以上 |
Java#Jakarta