Log4j问题排查-log4j,logback到底用了哪个?

提要:

1..在某此编译后,日志莫名其妙的乱了。本来应该打印到locationservice.log下的,但是打印到了jboss_stdout.log下

2. slf4j,log4j,logback之间的关系式什么?

 

============== 解答==================================================

 

1.因为代码没有变过,怀疑是系统在在使用日志系统的时候出现问题,打印mvn tree,发现同时依赖了log4j、logback,那系统使用的日志系统到底是哪一个呢?

 

2.查看log相关代码,原来slf4j只是日志系统的API,只是接口,称之为日志框架,类似于JDBCDriver,具体实现由各个厂家提供,而slf4j日志框架的实现目前有两个,一个是LOG4J,一个是SLF4J.

 

3.那么如果系统里有两套日志系统时,会选择哪个系统呢?

    在代码里我们通常会使用    Logger logger = LoggerFactory.getLogger(this.getClass());

    来获取Logger,LoggerFactory是slf4j-api里的一个单例工厂类,最底层调用StaticLoggerBinder.getSingleton().getLoggerFactory()来获取实现类。

而StaticLoggerBinder则在各自的厂商中提供。

那么到底使用的是哪个StaticLoggerBinder呢,

  private final static void bind() {
    try {
      Set staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
      reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
      // the next line does the binding
      StaticLoggerBinder.getSingleton();
      INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
      reportActualBinding(staticLoggerBinderPathSet);
      emitSubstituteLoggerWarning();
    } catch (NoClassDefFoundError ncde) {
}
....
}

        从bind的源代码可以看到 其实是随机加载的。

        回到我们的系统,到底是不是这个Binder作怪呢,搜索下StaticLoggerBinder类,发现在classpath下确实有两套。

        
Log4j问题排查-log4j,logback到底用了哪个?
 

          于是问题就清晰了

           在classpath下存在两个StaticLoggerBinder,应用启动后加载到logback的StaticLoggerBinder,于是使用了logback的Logger,但是由于我们默认配置的是Log4j,所以找不到logback的配置,于是默认打印到了STDOUT里。

        

 4.简单理了下调用的顺序图

 
Log4j问题排查-log4j,logback到底用了哪个?
 

5.最后的解决方法

   MAVEN:tree找到是依赖里有建议依赖了logback-classic的包,使用mvn排除, 部署后解决

ps:
启动日志里有这么一段

Log4j问题排查-log4j,logback到底用了哪个?
 
其实就是因为系统存在两个日志系统,slf4j不知道比较迷茫给出的警告
代码出自
  private static void reportMultipleBindingAmbiguity(Set staticLoggerBinderPathSet) {
    if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) {
      Util.report("Class path contains multiple SLF4J bindings.");
      Iterator iterator = staticLoggerBinderPathSet.iterator();
      while (iterator.hasNext()) {
        URL path = (URL) iterator.next();
        Util.report("Found binding in [" + path + "]");
      }
      Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
    }
  }
 
当系统检查到有多个Binder时就出在日志里打印警告了。
 
WEBX 写道
另,webx的教程里对日志系统有比较详细的解释
请移步http://openwebx.org/docs/logging.html
 
 
不过还有个问题,为啥以前好的呢?费解!
FINISH