slf4j装饰器正在记录装饰器FQCN,而不是调用FQCN

时间:2015-03-17 07:04:54

标签: java slf4j

我已经从slf4j Logger类创建了一个装饰器类,因为我需要在infodebug等方法中执行某项检查。我正在使用log4j12绑定。

除了记录的FQCN之外它工作正常:它不是调用类的FQCN,而是装饰器类的FQCN。

package foo.bar;

import org.slf4j.Logger;

public class MyLogger implements Logger {

private final Logger logger;
private final boolean traceAndExit;

public MyLogger(Logger logger, boolean traceAndExit) {
    this.logger = logger;
    this.traceAndExit = traceAndExit;
} // MyLogger

@Override
public void info(String message) {
    try {
        logger.info(message);
    } catch (Exception e) {
        if (traceAndExit) {
            traceAndExit(e);
        } // if
    } // catch
} // info

...

如果在任何其他班级foo.bar.OtherClass我这样做:

MyLogger myLogger = new MyLogger(LoggerFactory.getLogger(OtherClass.class), true);
myLogger.info("this is a message");

然后我获取的日志打印foo.bar.MyLogger而不是foo.bar.OtherClass%C转换字符)。

有关如何正确执行此操作的任何想法?我必须打印FQCN。

1 个答案:

答案 0 :(得分:3)

不幸的是,您没有提到您使用的日志记录实现。 slf4j只是各种日志记录实现共享的通用API。

幸运的是,至少Logback,Log4j和Log4j 2(应该是野外大多数日志记录实现)都以相同的方式解释%C格式说明符。

Logback documentationLog4j 2 documentation%C定义为“发出日志记录请求的调用方的完全限定类名”。这种情况分别发生在ch.qos.logback.classic.spi.CallerDataorg.apache.logging.log4j.util.ReflectionUtil中。基本上,框架检查堆栈跟踪,直到它们确实已经离开了自己的代码库,然后使用它们在堆栈上遇到的“下一个”类。  在您的情况下,这是MyLogger类。

避免这种情况的最简单方法是完全放弃%C格式说明符。虽然在debuggíng中很有用,但堆栈内部对性能有严重影响,无法干净地处理你的情况。

%c格式说明符会插入记录器的名称。如果您正确初始化记录器:

// static logger
private static final Logger STATIC_LOG = LoggerFactory.getLogger(OtherClass.class);

// instance logger
private final Logger log = LoggerFactory.getLogger(getClass());

%c产生预期的输出。这也允许高级记录解决方案,例如每类多个记录器,例如,审计记录。

如果您必须使用%C说明符,Logback提供了一个选项来设置调用者扫描忽略的框架包:

// during application startup
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
lc.getFrameworkPackages().add("foo.bar.logging")

请注意,这将有效禁用整个%C包的foo.bar.logging输出。 Log4j 2似乎没有提供类似的配置选项。