Log4j2自定义包装器

时间:2016-07-12 14:23:11

标签: java logging log4j log4j2

我基于这个主题为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行。

如何解决?

2 个答案:

答案 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手册中的说明。