2014-03-05 67 views
0

我希望log4j在打印日誌時吐出自定義模式。下面是這種情況:如何自定義log4j輸出

當前log4j的配置在log4j.properties:

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} - %p <%t> - %m%n 

和日誌聲明看起來是這樣的..

08:48:03,092 - INFO <main> - some message 

不過,我想添加自定義模式(或無論那個讓我定製這個)包括說,loginId,帳戶爲每個日誌語句打印。

所需的輸出:

08:48:03,092 - INFO <main> <abcuser:12345> - some message 

我使用SLF4J與log4j的綁定。

我該如何做到這一點?請幫忙。

回答

1

一種替代方法是爲使用MDCNDC

例如,您可以將您的用戶信息到MDC地圖:

public class Controller { 
    public void someControllerMethod(){ 
     MDC.put("user", SecurityContext.getCurrentUser().getName()); 
     try{ 
     //do your work here 
     }finally{ 
     MDC.clear(); 
     } 
    } 
} 

然後在你PatternLayout可以配置使用MDC值:

%d{ABSOLUTE} - %p <%t> %X{user} - %m%n 

,這將保證您將在日誌輸出中看到用戶名:

08:48:03,092 - INFO <main> <obiwan> - some message 

- 編輯 -

爲了解決你的問題:

好,MDC是地圖狀結構,你會得到它的每個線程的實例。所以,最有可能在幕後使用ThreadLocal變量。

服務器中的線程數量有限,所以我懷疑這在內存方面會花費很多。由於它是每線程結構,因此只有在首次使用線程時纔會假定創建對象的成本。但無論如何,這可能是微不足道的。我想你應該小心,不要在這個結構中放置很大的物體,並且確保在不再需要時清除它。

清除MDC結構的重要性與調用ThreadLocal變量的remove方法的重要性相同。如果你沒有調用清除,那麼變量保持與你的線程相關聯,如果你正在使用線程池,那麼你最終可能會從上一次線程使用中獲得無效的MDC值。因此,理想情況下,您可以在代碼中註冊變量以便記錄目的,並在代碼中註明您不再需要的地方,您可以像我一樣刪除它或清除整個結構。

此外,根據您在結構中放置的內容,如果您不清除它,它可能會阻止垃圾收集不必要的對象。所以,底線,最好是清除它或刪除你不需要的東西,當你知道你不再需要它的時候。理想情況下,你應該只在這裏放置真正簡單的對象,比如字符串或者原始值,並且由此避免這樣的問題。

+0

我也試過MDC的方式..它的工作。這個選項似乎更簡單!謝謝。但是,我很想知道 - MDC是多麼昂貴/昂貴?我的意思是..一般來說,設置自定義日誌屬性是不是一件壞事?另外,是否必須調用MDC.clear()? –

+0

@AravindDatta我已經擴展我的答案來解決您的問題。 –

0

有可能實現自己的PatterLayout和定義新的字符映射帳戶,登錄等等

你可以找到一個教程here

+0

太棒了!這樣可行! –

+0

好的,有一個問題。我測試了這個東西作爲一個示例項目,它的工作原理..但在我真正的應用程序..在應用程序啓動(或啓動),log4j屬性被讀取..它是拋出一個ClassNotFoundException'客戶MyPatternLayout尚未創建。我們如何處理這種情況? –

+0

可能是一個類加載器問題。如果將MyPatternLayout編譯類放在應用程序服務器的公共類加載器目錄中,它會更好嗎? – Julien