自定义SLF4J Wrapper未在日志文件中打印正确的方法名称

时间:2015-10-09 11:22:55

标签: java slf4j log4j2

我有一个自定义SLF4J包装器,如下所示:

Logger.java

public final class Logger {
  private final org.slf4j.Logger slf4jLogger;

  public Logger() {
    this.slf4jLogger = com.demo.LoggerFactory.DEFAULT_LOGGER;
  }

  public Logger(final org.slf4j.Logger slf4jLogger) {
    this.slf4jLogger = slf4jLogger;
  }

  public void debug(final String message, final Object... args) {
    if (isDebugEnabled()) {
      slf4jLogger.debug(message, args);
    }
  }
  // ... other logger methdods
}

LoggerFactory.java

public class LoggerFactory {
  public static final org.slf4j.Logger DEFAULT_LOGGER = org.slf4j.LoggerFactory.getLogger(AppSupportConstants.DEFAULT_LOGGER);

  public static Logger getLogger(final Class<?> clazz) {
    if (clazz != null) {
      return new Logger(org.slf4j.LoggerFactory.getLogger(clazz));
    }

    return new Logger(DEFAULT_LOGGER);
  }
}

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
  <Properties>
    <Property name="logFilePath">logs</Property>
  </Properties>
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [Thread: %t] %level{length=1} %c{1.}.%M - %msg%n" />
    </Console>
    <RollingRandomAccessFile name="APP_LOG_APPENDER" fileName="${catalina.base}/logs/demo.log"
            filePattern="logs/$${date:yyyy-MM}/demo-%d{yyyy-MM-dd}-%i.log.gz" immediateFlush="false">
      <PatternLayout>
        <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [Thread: %t] %level{length=1} %c{1.}#%M - %msg%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="1 MB" />
      </Policies>
      <DefaultRolloverStrategy max="20"/>
    </RollingRandomAccessFile>
  </Appenders>
  <Loggers>
    <Logger name="DEFAULT_LOGGER" level="debug" additivity="false">
      <AppenderRef ref="APP_LOG_APPENDER" />
    </Logger>
    <Root level="debug">
      <AppenderRef ref="Console" />
      <AppenderRef ref="APP_LOG_APPENDER" />
    </Root>
  </Loggers>
</Configuration>

LogDemo.java

public class LogDemo {
  // SLF4J Logger
  private final static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(LogDemo.class);

  // Custom Logger
  private static final Logger customLogger = LoggerFactory.getLogger(LogDemo.class);

  public static void main(final String[] args) {
    new LogDemo().demo();
  }

  public void demo() {
    logger.debug("[Direct] Debug...");
    logger.info("[Direct] Info...");
    logger.warn("[Direct] Warn...");
    logger.error("[Direct] Error...");

    customLogger.debug("[CustomLogger] Debug...");
    customLogger.info("[CustomLogger] Info...");
    customLogger.warn("[CustomLogger] Warn...");
    customLogger.error("[CustomLogger] Error...");
  }
}

输出上述代码

2015-10-09 16:45:07.642 [Thread: main] D c.d.LogDemo#demo - [Direct] Debug...
2015-10-09 16:45:07.644 [Thread: main] I c.d.LogDemo#demo - [Direct] Info...
2015-10-09 16:45:07.644 [Thread: main] W c.d.LogDemo#demo - [Direct] Warn...
2015-10-09 16:45:07.644 [Thread: main] E c.d.LogDemo#demo - [Direct] Error...
2015-10-09 16:45:07.645 [Thread: main] D c.d.LogDemo#debug - [CustomLogger] Debug...
2015-10-09 16:45:07.646 [Thread: main] I c.d.LogDemo#info - [CustomLogger] Info...
2015-10-09 16:45:07.646 [Thread: main] W c.d.LogDemo#warn - [CustomLogger] Warn...
2015-10-09 16:45:07.646 [Thread: main] E c.d.LogDemo#error - [CustomLogger] Error...

如果您注意到,customLogger打印的记录器语句显示的方法名称为debuginfo等。我想这是因为自定义记录器在该类中使用了包装器方法,但为什么这样的行为,有没有办法解决这个问题。

包装记录器是设计使然,由于某些内部原因我们无法避免它。

1 个答案:

答案 0 :(得分:0)

Log4j使用在堆栈跟踪中查找固定数量的步骤来查找调用类。

Log4j包含一个用于生成Logger包装器的工具:http://logging.apache.org/log4j/2.x/manual/customloglevels.html#CustomLoggers

请查看此工具(source code here),因为它解决了同样的问题。诀窍是将正确的FQCN(完全限定类名)传递给ExtendedLoggerWrapper.logIfEnabled方法。