差異處

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

連向這個比對檢視

下次修改
前次修改
java:log4j2:mdc [2022/04/10 12:13]
tony 建立
java:log4j2:mdc [2023/06/25 09:48] (目前版本)
行 4: 行 4:
 MDC(Mapped Diagnostic Context)的使用情境,主要用來解決在多執行緒時,不容易區分不同請求的識別問題。舉例來說,使用者A與使用者B操作了你的系統,在不使用MDC的情況下,你可能會需要把sessionId或者是userName傳遞給所有你操作的程式碼,並在操作程式碼中確實的進行log。本篇文章分享MDC怎麼解決這個問題。 MDC(Mapped Diagnostic Context)的使用情境,主要用來解決在多執行緒時,不容易區分不同請求的識別問題。舉例來說,使用者A與使用者B操作了你的系統,在不使用MDC的情況下,你可能會需要把sessionId或者是userName傳遞給所有你操作的程式碼,並在操作程式碼中確實的進行log。本篇文章分享MDC怎麼解決這個問題。
 ===== How to? ===== ===== How to? =====
-在你接收request的程式碼中,你必定可以獲得sessionId或者是userName,這時後可以直接使用+在你接收request的程式碼中,你必定可以獲得sessionId或者是userName,這時候可以直接使用:​ 
 +<code java> 
 +ThreadContext.put("​sessionId",​ sessionId);​ 
 +// invoke sub operations 
 +ThreadContext.clearMap();​ 
 +</​code>​ 
 +設定檔的部分則需要使用%X{key}來宣告於layout.pattern,如下面的範例:​ 
 +<code properties>​ 
 +appender.console.layout.pattern = %d{yyyy/​MM/​dd HH:​mm:​ss.SSS} %5p[%t] %X{sessionId}(%F:​%M:​%L) - %m%n 
 +</​code>​ 
 +輸出就會長這個樣子:​ 
 +<​code>​ 
 +2022/04/10 12:​58:​26.738 DEBUG[thread_name] testSessionId(className.java:​methodName:​320) - this is test message 
 +</​code>​ 
 +假如你的sub operations會發生在不同thread,這時候就需要使用到這個property去啟用sub-thread共享相同MDC變數的功能:​ 
 +<code java> 
 +System.setProperty("​log4j2.isThreadContextMapInheritable","​true"​);​ 
 +</​code>​ 
 +要再提醒各位,用完MDC要記得清除放進去的資料,否則是會造成memory leak的。 
 +===== Migrate from log4j1 ===== 
 +設定檔格式的部分沒有差別,可以沿用,source code部分則是用ThreadContext取代MDC,可以參考log4j2的[[https://​github.com/​apache/​logging-log4j2/​blob/​f72100df0decc9bda96b4d769822c4e48b2848fc/​log4j-1.2-api/​src/​main/​java/​org/​apache/​log4j/​MDC.java|source code]]做對應的替換。\\ 
 +另外一個選擇是直接使用slf4j的MDC:​ [[https://​codertw.com/​%E4%BC%BA%E6%9C%8D%E5%99%A8/​133627/​|link]],讓它由binding決定實做,避免了實做相依。 
 +===== Refernece ===== 
 +  * [[https://​stackoverflow.com/​questions/​49188105/​log4j2-isthreadcontextmapinheritable-property-usage|log4j2 isThreadContextMapInheritable property usage]]