我希望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。
我怎样才能做到这一点?请帮忙。
答案 0 :(得分:1)
可以实现自己的PatterLayout并定义新的字符来映射帐户,登录等...
您可以找到教程here
答案 1 :(得分:1)
例如,您可以将用户的信息添加到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值。因此,理想情况下,您可以在代码中注册变量以进行日志记录,并在代码中找到您不再需要的位置,然后您可以删除它或清除整个结构。
另外,根据您放入结构中的内容,如果不清除它,可能会阻止垃圾收集不必要的对象。所以,最重要的是,最好清除它,或者在你知道不再需要的时候删除你不需要的东西。
理想情况下,你应该只在这里放置非常简单的对象,比如字符串或原始值,这样就避免了这样的麻烦。