如何自定义log4j输出

时间:2014-03-05 15:18:55

标签: java logging log4j slf4j

我希望log4j在打印日志时吐出自定义模式。这是场景:

log4j.properties中的当前log4j配置:

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

和log语句看起来像这样..

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

但是,我想添加自定义模式(或任何让我自定义的模式),包括say,loginId,account,用于打印的每个日志语句。

期望的输出:

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

我正在使用带有log4j绑定的slf4j。

我怎样才能做到这一点?请帮忙。

2 个答案:

答案 0 :(得分:1)

可以实现自己的PatterLayout并定义新的字符来映射帐户,登录等...

您可以找到教程here

答案 1 :(得分: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结构的重要性与在remove变量上调用ThreadLocal方法的重要性相同。如果你没有调用clear,那么变量会保持附加到你的线程,如果你使用的是线程池,那么你最终可能会从之前的线程使用中获得无效的MDC值。因此,理想情况下,您可以在代码中注册变量以进行日志记录,并在代码中找到您不再需要的位置,然后您可以删除它或清除整个结构。

另外,根据您放入结构中的内容,如果不清除它,可能会阻止垃圾收集不必要的对象。所以,最重要的是,最好清除它,或者在你知道不再需要的时候删除你不需要的东西。

理想情况下,你应该只在这里放置非常简单的对象,比如字符串或原始值,这样就避免了这样的麻烦。