差異處
這裏顯示兩個版本的差異處。
下次修改 | 前次修改 | ||
java:log4j2:changeloglevelatruntime [2022/02/04 16:07] tony 建立 |
java:log4j2:changeloglevelatruntime [2023/06/25 09:48] (目前版本) |
||
---|---|---|---|
行 9: | 行 9: | ||
本篇文章主要分享在Log4j2可行的做法。範例程式可參考: [[https://github.com/frank007love/Log4j2Practice/tree/master/src/test/java/org/tonylin/practice/log4j2/example1|link]]。 | 本篇文章主要分享在Log4j2可行的做法。範例程式可參考: [[https://github.com/frank007love/Log4j2Practice/tree/master/src/test/java/org/tonylin/practice/log4j2/example1|link]]。 | ||
===== How to? ===== | ===== How to? ===== | ||
+ | ==== SUT ==== | ||
+ | <code java> | ||
+ | public class TestLogger { | ||
+ | private static final Logger LOGGER = LoggerFactory.getLogger(TestLogger.class); | ||
+ | | ||
+ | public static void debug(String message) { | ||
+ | LOGGER.debug(message); | ||
+ | } | ||
+ | | ||
+ | public static void error(String message) { | ||
+ | LOGGER.error(message); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | ==== Configuration properties ==== | ||
+ | 預設啟用了ConsoleAppender,而SUT的level是設為error;另外appender.console.follow設為true,讓Log4j可以反應system.out或system.err的變更,這主要和我們測試時會去攔截console有關: | ||
+ | <code> | ||
+ | rootLogger.level = info | ||
+ | rootLogger.appenderRef.stdout.ref = STDOUT | ||
+ | |||
+ | status = error | ||
+ | dest = err | ||
+ | name = PropertiesConfig | ||
+ | |||
+ | filter.threshold.type = ThresholdFilter | ||
+ | filter.threshold.level = debug | ||
+ | |||
+ | appender.console.type = Console | ||
+ | appender.console.name = STDOUT | ||
+ | appender.console.follow = true | ||
+ | appender.console.layout.type = PatternLayout | ||
+ | appender.console.layout.pattern = %d %p %C{1.} [%t] %m%n | ||
+ | appender.console.filter.threshold.type = ThresholdFilter | ||
+ | appender.console.filter.threshold.level = trace | ||
+ | |||
+ | logger.console.name = org.tonylin.practice.log4j2.example1 | ||
+ | logger.console.level = error | ||
+ | logger.console.additivity = false | ||
+ | logger.console.appenderRef.rolling.ref = STDOUT | ||
+ | </code> | ||
+ | ==== Unit Test ==== | ||
+ | 測試程式我使用了[[https://github.com/Hakky54/console-captor|console-captor]] library讓我可以很容易去捕捉console內容;測試後我會透過Configurator.reconfigure去重置設置內容: | ||
+ | <code java> | ||
+ | private ConsoleCaptor captor; | ||
+ | |||
+ | @Before | ||
+ | public void setup() { | ||
+ | captor = new ConsoleCaptor(); | ||
+ | Configurator.reconfigure(); | ||
+ | } | ||
+ | |||
+ | @After | ||
+ | public void teardown() { | ||
+ | captor.close(); | ||
+ | } | ||
+ | </code> | ||
+ | 首先讓我們先測試debug level不會有console,而error level會有console且內容符合預期: | ||
+ | <code java> | ||
+ | @Test | ||
+ | public void Should_NotSystemOutToConsole_When_LogDebugWithDefaultConfiguration() { | ||
+ | TestLogger.debug("test debug"); | ||
+ | assertEquals(0, captor.getStandardOutput().size()); | ||
+ | } | ||
+ | |||
+ | @Test | ||
+ | public void Should_SystemOutToConsole_When_LogErrorWithDefaultConfiguration() { | ||
+ | TestLogger.error("test error"); | ||
+ | assertEquals(1, captor.getStandardOutput().size()); | ||
+ | assertTrue(captor.getStandardOutput().get(0).contains("test error")); | ||
+ | } | ||
+ | </code> | ||
+ | 接著就是本篇主角了,第一個方法是直接用Configurator去設定,雖然簡單,但這不是一個[[https://logging.apache.org/log4j/2.x/faq.html#reconfig_level_from_code|public的API]],不建議在production code使用: | ||
+ | <code java> | ||
+ | @Test | ||
+ | public void Should_SystemOutToConsole_When_LogDebugAfterChangingLogLevelWithConfigurator() { | ||
+ | Configurator.setLevel(TestLogger.class.getName(), Level.DEBUG); | ||
+ | | ||
+ | TestLogger.debug("test debug"); | ||
+ | assertEquals(1, captor.getStandardOutput().size()); | ||
+ | assertTrue(captor.getStandardOutput().get(0).contains("test debug")); | ||
+ | } | ||
+ | </code> | ||
+ | 另外一個方法參考自[[https://stackoverflow.com/questions/23434252/programmatically-change-log-level-in-log4j2|這裡]],其實就是Configurator實作的方法(Configurator像是一個Utility的Class): | ||
+ | <code java> | ||
+ | @Test | ||
+ | public void Should_SystemOutToConsole_When_LogDebugAfterChangingLogLevel() { | ||
+ | LoggerContext ctx = (LoggerContext) LogManager.getContext(false); | ||
+ | Configuration config = ctx.getConfiguration(); | ||
+ | LoggerConfig loggerConfig = config.getLoggerConfig(TestLogger.class.getName()); | ||
+ | loggerConfig.setLevel(Level.DEBUG); | ||
+ | ctx.updateLoggers(); | ||
+ | | ||
+ | TestLogger.debug("test debug"); | ||
+ | assertEquals(1, captor.getStandardOutput().size()); | ||
+ | assertTrue(captor.getStandardOutput().get(0).contains("test debug")); | ||
+ | } | ||
+ | </code> | ||
+ | 註: LogManager.getContext(true)的真正作用情境還不曉得為何,有弄清楚後再分享。 | ||
+ | ===== Reference ===== | ||
+ | * [[https://stackoverflow.com/questions/23434252/programmatically-change-log-level-in-log4j2|Programmatically change log level in Log4j2]] | ||
===== ===== | ===== ===== |