我基于这个主题为log4j2记录器做了一个包装器: How do I add a prefix to log4j messages (at the object level)
这是我有:
import org.apache.log4j.Logger;
public class LogWrapper
{
private Logger log;
private String prefix;
public LogWrapper(Logger log, String prefix) {
this.log = log;
this.prefix = prefix;
}
public void info(String msg)
{
log.error(prefix + "| " + msg);
}
public void error(String msg)
{
log.error(prefix + "| " + msg);
}
}
用法:
public class MyClass {
private final LogWrapper logger;
public MyClass(String username) {
logger = new LogWrapper(Logger.getLogger(MyClass.class.getName()), username);
}
}
问题:
由于输出我有LogWrapper
类
2016-07-12 21:15:17,543 ERROR [pool-3-thread-1] global.LogWrapper (LogWrapper.java:17) - blab bla bla
'LogWrapper.java:17'
它没有指向调用记录器的MyClass
行。
如何解决?
答案 0 :(得分:2)
Log4j提供的用于在日志输出中添加前缀的内置机制是ThreadContext映射。怎么做:
代码:
// usually at some entry point from where these values won't change
ThreadContext.put("user.ip", ipAdr);
ThreadContext.put("user.account", userAccount);
配置:
<PatternLayout pattern="%d %p %c{1.} [%t] %X{user.ip} %X{user.account} %m%n"/>
现在,任何记录值都已放入ThreadContext后,将显示所需的前缀。
自定义记录器包装器可用于实现类似的功能,但工作量却要大得多。
Log4j会记住记录器的完全限定类名(FQCN),并在配置为打印位置时使用它来遍历每个日志事件的堆栈跟踪。 (请注意,使用位置进行日志记录的速度很慢,可能会影响应用程序的性能。)
自定义记录器包装器的问题在于它具有与实际记录器不同的FQCN,因此Log4j无法找到调用自定义记录器的位置。
解决方案是提供正确的FQCN。最简单的方法是让Log4j为您生成记录器包装器。 Log4j附带一个Logger包装器生成器工具。此工具最初旨在支持自定义日志级别,并在此处记录:https://logging.apache.org/log4j/2.x/manual/customloglevels.html#CustomLoggers
生成的记录器代码将处理FQCN,您可以将其用作进一步增强功能的基础。
答案 1 :(得分:2)
实际上,问题是位置信息不是您想要的。当您创建包装器时会发生这种情况。要修复它,Log4j需要Logger类的完全限定类名(FQCN)。手动创建这样做的类并不难,但简单的方法是遵循http://logging.apache.org/log4j/2.x/manual/customloglevels.html#CustomLoggers
中Log4j手册中的说明。