作者:追夢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);
}
}
最後,啟動專案,可以看到對應的日誌和日誌檔案。
總結
日誌框架適用很廣泛,而且涉及的內容內多,本章只做了日誌介紹和適用的闡述。後續還涉及很多的內容,比如如何進行日誌檢索、如何進行日誌清洗等。由於篇幅所限,本章不做過多的介紹。