我已经从slf4j Logger
类创建了一个装饰器类,因为我需要在info
,debug
等方法中执行某项检查。我正在使用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。
答案 0 :(得分:3)
不幸的是,您没有提到您使用的日志记录实现。 slf4j只是各种日志记录实现共享的通用API。
幸运的是,至少Logback,Log4j和Log4j 2(应该是野外大多数日志记录实现)都以相同的方式解释%C
格式说明符。
Logback documentation和Log4j 2 documentation将%C
定义为“发出日志记录请求的调用方的完全限定类名”。这种情况分别发生在ch.qos.logback.classic.spi.CallerData
和org.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似乎没有提供类似的配置选项。