差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

java:log4j2:changeloglevelatruntime [2022/02/04 22:01]
tony
java:log4j2:changeloglevelatruntime [2023/06/25 09:48]
行 1: 行 1:
-{{tag>​log4j2}} 
-====== Log4j2 - Change log level at runtime ====== 
-===== Problem ===== 
-為了能夠在系統執行期間蒐集發生問題的資訊,有時我們會在執行功能之前,去動態調整log level,儘可能最大化地去蒐集必要資訊。在Log4j 1.x時,我們採用了以下寫法去做到動態切換log level: 
-<code java> 
-Logger logger = LogManager.getLogger(packName);​ 
-logger.setLevel(Level.TRACE);​ 
-</​code>​ 
-本篇文章主要分享在Log4j2可行的做法。範例程式可參考:​ [[https://​github.com/​frank007love/​Log4j2Practice/​tree/​master/​src/​test/​java/​org/​tonylin/​practice/​log4j2/​example1|link]]。 
-===== 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.rolling.name = org.tonylin.practice.log4j2.example1 
-logger.rolling.level = error 
-logger.rolling.additivity = false 
-logger.rolling.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]] 
- 
-=====    ===== 
----- 
-\\ 
-~~DISQUS~~