1. 程式人生 > >springboot 日誌問題記錄

springboot 日誌問題記錄

原文連結

摘要: 問題:新建工程busr,採用pandora boot,引入了需要的包,簡單寫了點程式碼釋出,spring-boot啟動報錯: Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath.

問題:新建工程busr,採用pandora boot,引入了需要的包,簡單寫了點程式碼釋出,
spring-boot啟動報錯:

Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. 
Either remove Logback or the competing implementation (class org.apache.logging.slf4j.Log4jLoggerFactory loaded from 
jar:file:/opt/*

*.jar!/BOOT-INF/lib/log4j-slf4j-impl-2.6.2.jar!/). If you are using WebLogic you will need to add 'org.slf4j' 
to prefer-application-packages in WEB-INF/weblogic.xml Object of class [org.apache.logging.slf4j.Log4jLoggerFactory] 
must be an instance of class ch.qos.logback.classic.LoggerContext
at org.springframework.util.Assert.isInstanceOf(Assert.java:346)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:231)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:97)
at org.springframework.boot.logging.LoggingApplicationListener.onApplicationStartedEvent(LoggingApplicationListener.java:226)
at org.springframework.boot.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:205)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:166)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:121)
at org.springframework.boot.context.event.EventPublishingRunListener.started(EventPublishingRunListener.java:63)
at org.springframework.boot.SpringApplicationRunListeners.started(SpringApplicationRunListeners.java:48)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:304)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1186)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1175)

看到錯誤 "LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. 
Either remove Logback"
大概意思是 可以remove掉logback 解決問題。 當時直接Google了下 Stack Overflow上有篇文章也說
排掉logback的包即可。

釋出啟動 一切貌似正常。 正當高興之餘,突然發現不列印日誌了。很明顯與我剛才的操作有關係,看來剛才解決問題的辦法似乎不正確。靜下來分析問題的根本原因:
看看spring boot 是怎麼載入日誌的:
原始碼中 onApplicationStartedEvent方法,在系統啟動時會被呼叫,LoggingSystem獲取當然的日誌系統

private void onApplicationStartedEvent(ApplicationStartedEvent event) {
this.loggingSystem = LoggingSystem
.get(event.getSpringApplication().getClassLoader());
this.loggingSystem.beforeInitialize();
}

預設的會引入下面3個日誌系統 如果沒有任何配置的化 其預設的是LogbackLoggingSystem
static {
Map systems = new LinkedHashMap();
systems.put("ch.qos.logback.core.Appender",
"org.springframework.boot.logging.logback.LogbackLoggingSystem");
systems.put("org.apache.logging.log4j.core.impl.Log4jContextFactory",
"org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");
systems.put("java.util.logging.LogManager",
"org.springframework.boot.logging.java.JavaLoggingSystem");
SYSTEMS = Collections.unmodifiableMap(systems);
}

逐步跟蹤到第一次系統報錯的地方
private LoggerContext getLoggerContext() {
ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory();
Assert.isInstanceOf(LoggerContext.class, factory,
String.format(
"LoggerFactory is not a Logback LoggerContext but Logback is on "

  • "the classpath. Either remove Logback or the competing "
  • "implementation (%s loaded from %s). If you are using "
  • "WebLogic you will need to add 'org.slf4j' to "
  • "prefer-application-packages in WEB-INF/weblogic.xml",
    factory.getClass(), getLocation(factory)));

return (LoggerContext) factory;
}

說明返回的factory不是logback的例項, StaticLoggerBinder.getSingleton().getLoggerFactory() 沒有找到logback,
所以這個時候開始懷疑StaticLoggerBinder 是否是因為包衝突,果然 如下圖
http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/a9fbe3063e81267c31ec925c4b5e8c35.pngimage

預設用了slf4j-log4j12 裡面的StaticLoggerBinder 類,而沒有用logback的 所以才會報上面的啟動錯誤。

來至 
com.alibaba.trip.tripspider:tripspider-httpclient:jar:1.0.0-SNAPSHOT:compile
排掉即可

org.slf4j
slf4j-log4j12

啟動一切正常,久違的日誌又有了。

思考:遇到問題 google一下找解決辦法或許是最快的,但是有時候往往解決方案因人而異,可能並不完全正確,明白問題出現的根本原因找解決辦法才是最靠譜的。