作者:追夢1819
原文:https://www.cnblogs.com/yanfei1819/p/10973583.html
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
## 引言
日志是軟件系統的“基礎設施”,它可以幫助我們了解系統的運行軌跡,查找系統的運行異常等。很多人都沒有引起對日志的重視。
下面我們先來設定幾個實際項目項目的場景:
1、xxx物流雲系統,公司在給貨車司機打款的時候,司機沒收到賬款。司機在線等,沒收到賬款,就不繼續跑了;
2、xxx商城小程序,給用戶進行退款的時候,用戶沒有收到錢,然后要舉報公司。。。;
3、線上系統掛了,待找原因,待上線等。
這些都屬於很嚴重的生產事故了,直接影響公司的運營。然而,這些問題的解決,通常在要日志中查找原因(當然,日志的作用不限於此),然后解決。
我們見過最多的日志相關的代碼莫過於System.out.println("");
,log4j
這兩種了。下面我們來說說 SpringBoot 中日志框架的使用。
## 日志框架介紹
目前市面上的日志框架有:
JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....
log4j
log4j 是 Apache 的一個開放源代碼項目,通過使用Log4j,我們可以控制日志信息輸送的目的地是控制台、文件、數據庫等;我們也可以控制每一條日志的輸出格式;通過定義每一條日志信息的級別,我們能夠更加細致地控制日志的生成過程。
Log4j有7種不同的log級別,按照等級從低到高依次為:TRACE<DEBUG<INFO<WARN<ERROR<FATAL<OFF。如果配置為OFF級別,表示關閉 log。
Log4j支持兩種格式的配置文件:properties和xml。
包含三個主要的組件:Logger、appender、Layout。
slf4j
slf4j,即簡單日志門面(Simple Logging Facade for Java),不是具體的日志解決方案,而是通過Facade Pattern提供一些Java logging API,它只服務於各種各樣的日志系統。按照官方的說法,SLF4J是一個用於日志系統的簡單Facade,允許最終用戶在部署其應用時使用其所希望的日志系統。作者創建SLF4J的目的是為了替代Jakarta Commons-Logging。
實際上,slf4j 所提供的核心API是一些接口以及一個 LoggerFactory 的工廠類。在使用 slf4j 的時候,不需要在代碼中或配置文件中指定你打算使用那個具體的日志系統。slf4j 提供了統一的記錄日志的接口,只要按照其提供的方法記錄即可,最終日志的格式、記錄級別、輸出方式等通過具體日志系統的配置來實現,因此可以在應用中靈活切換日志系統。
適用場景:
如果你開發的是類庫或者嵌入式組件,那么就應該考慮采用 slf4j,因為不可能影響最終用戶選擇哪種日志系統。在另一方面,如果是一個簡單或者獨立的應用,確定只有一種日志系統,那么就沒有使用 slf4j 的必要。假設你打算將你使用 log4j 的產品賣給要求使用 JDK 1.4 Logging 的用戶時,面對成千上萬的 log4j 調用的修改,相信這絕對不是一件輕松的事情。但是如果開始便使用slf4j,那么這種轉換將是非常輕松的事情。
logback
Logback,一個“可靠、通用、快速而又靈活的Java日志框架”。
logback當前分成三個模塊:logback-core,logback- classic和logback-access。logback-core 是其它兩個模塊的基礎模塊。logback-classic 是 log4j 的一個改良版本。此外logback-classic 完整實現 SLF4J API 使你可以很方便地更換成其它日志系統如log4j或JDK14 Logging。logback-access 訪問模塊與 Servlet 容器集成提供通過Http來訪問日志的功能。
Java提供了自己的日志框架,類似於 slf4j,但是API並不完善,對開發者不是很友好,而且對於日志的級別分類也不是很清晰,比如:SEVERE, WARNING, INFO, CONFIG, FINE,FINER, FINEST。所以不推薦使用這種方式輸出日志。
JCL
Jakarta Commons Logging 和 slf4j 非常類似,也是提供的一套API來掩蓋了真正的 logger 實現。便於不同的 logger 的實現的替換,而不需要重新編譯代碼。缺點在於它的查找 logger 的實現者的算法比較復雜,而且當出現了一些class loader之類的異常時,無法去修復它。
Log4j 2
已經有很多其他的日志框架對 slf4j 進行了改良,比如說 slf4j、logback 等。而且 log4j2 在各個方面都與 logback 非常相似,那么為什么我們還需要 log4j2 呢?
- 插件式結構。log4j2 支持插件式結構。我們可以根據自己的需要自行擴展 log4j2 , 我們可以實現自己的 appender、logger、filter;
- 配置文件優化。在配置文件中可以引用屬性,還可以直接替代或傳遞到組件。而且支持json格式的配置文件。不像其他的日志框架,它在重新配置的時候不會丟失之前的日志文件;
- Java 5 的並發性。log4j2 利用Java 5中的並發特性支持,盡可能地執行最低層次的加鎖。解決了在 log4j1.x 中存留的死鎖的問題。如果你的程序仍然在飽受內存泄露的折磨,請毫不猶豫地試一下 log4j2 吧;
- 異步 logger。log4j2 是基於 LMAX Disruptor庫的。在多線程的場景下,和已有的日志框架相比,異步的 logger 擁有10左右的效率提升。
SpringBoot默認日志框架
默認配置
SpringBoot 默認使用的是 logback 日志系統,需要引入 maven 依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
下面我們看看底層的依賴關系:
由上圖可以得到幾個結論:
- SpringBoot 底層也是使用 slf4j+logback 的方式進行日志記錄;
- SpringBoot也把其他的日志都替換成了slf4j;
我們在啟動類做一個簡單的測試,觀察效果:
@SpringBootApplication
public class LogDemoApplication {
private static final Logger logger = LoggerFactory.getLogger(LogDemoApplication.class);
public static void main(String[] args) {
logger.info("hello,logback!");
SpringApplication.run(LogDemoApplication.class, args);
}
}
以上代碼關於 LoggerFactory.getLogger()
方法中的參數 Clazz.class,主要是准確編寫class信息能夠提供快速定位日志的效率。即可以在日志中款速定位到要查找的內容。
啟動程序,能夠看到打印的日志:
自定義配置
以上的示例中,都是用的 SpringBoot 默認的日志屬性,當然,這些屬性可修改,下圖是屬性列表,可以根據自己的需求進行自定義。
針對屬性中關於日志格式的符號定義,此處也做一個簡單的說明:
%d{HH:mm:ss.SSS}——日志輸出時間
%thread——輸出日志的進程名字,這在Web應用以及異步任務處理中很有用
%-5level——日志級別,並且使用5個字符靠左對齊
%logger- ——日志輸出者的名字
%msg——日志消息
%n——平台的換行符
日志持久化
以上示例是將日志打印到控制台。在實際項目中,日志通常是進行持久化,存儲在文件中或者數據庫中。
一、存儲在文件中
只要在 application.properties 或者 application.yml 中配置以下屬性:
# 日志路徑
logging.path=
# 日志名稱
logging.file=SpringBoot.log
二、存入數據庫
這種方式就是醒目中的添加業務了。通常用的不多。
## SpringBoot與其他日志框架
SpringBoot 默認使用的日志框架是 logback + slf4j ,如果想與其它的日志框架整合,則必須將默認的日志框架排除:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
與 log4j2 整合:
首先,引入 maven 依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
其次,log4j2.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<property name="LOG_PATH">../logs/</property>
<property name="LOG_FILE">testlog4j2</property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout>
<pattern>%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] - %m%n</pattern>
</PatternLayout>
</Console>
<RollingFile name="errorlogfile" fileName="${LOG_PATH}/${LOG_FILE}.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/${LOG_FILE}-%d{yyyy-MM-dd HH-mm}-%i.log">
<PatternLayout>
<pattern>%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] - %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="50 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
</Appenders>
<Loggers>
<root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="errorlogfile" />
</root>
</Loggers>
</Configuration>
第三步,在 application.properties 中指定配置文件的位置:
logging.config= classpath:log4j2.xml
第四步,在啟動類中測試:
@SpringBootApplication
public class LogOtherDemoApplication {
private static Logger logger = LogManager.getLogger(LogOtherDemoApplication.class);
public static void main(String[] args) {
logger.info("這里是整合其他日志框架");
SpringApplication.run(LogOtherDemoApplication.class, args);
}
}
最后,啟動項目,可以看到對應的日志和日志文件。
總結
日志框架適用很廣泛,而且涉及的內容內多,本章只做了日志介紹和適用的闡述。后續還涉及很多的內容,比如如何進行日志檢索、如何進行日志清洗等。由於篇幅所限,本章不做過多的介紹。
源碼:我的GitHub