前言
隨著互聯(lián)網(wǎng)和大數(shù)據(jù)的迅猛發(fā)展,分布式日志系統(tǒng)和日志分析系統(tǒng)已廣泛應(yīng)用,幾乎所有應(yīng)用程序都使用各種日志框架記錄程序運行信息。因此,作為工程師,了解主流的日志記錄框架非常重要。雖然應(yīng)用程序的運行結(jié)果不受日志的有無影響,但沒有日志的應(yīng)用程序是不完整的,甚至可以說是有缺陷的。優(yōu)秀的日志系統(tǒng)可以記錄操作軌跡、監(jiān)控系統(tǒng)運行狀態(tài)和解決系統(tǒng)故障。
Java 日志框架進(jìn)化史
早期 Java 日志框架沒有制定統(tǒng)一的標(biāo)準(zhǔn),使得很多應(yīng)用程序會同時使用多種日志框架。Java 日志框架的發(fā)展歷程大致可分為以下幾個階段:
1.Log4j:Apache Log4j是一種基于Java的日志記錄工具。該項目由Ceki Gülcü于1999年創(chuàng)建,并幾乎成為了Java日志框架的實際標(biāo)準(zhǔn)。
2.JUL:Apache 希望將 Log4j 引入 jdk,不過被 sun 公司拒絕了。隨后,sun 模仿 Log4j,在 jdk1.4 中引入了 JUL(java.util.logging)。
3.Commons Logging:為了解耦日志接口與實現(xiàn),Apache在2002年推出了JCL(Jakarta Commons Logging)。JCL定義了一套日志接口,具體的實現(xiàn)由Log4j或JUL完成。Commons Logging使用動態(tài)綁定來實現(xiàn)日志記錄,編碼時只需要使用它定義的接口即可,程序運行時會使用ClassLoader來查找和加載底層的日志庫,因此可以靈活選擇Log4j或JUL來實現(xiàn)日志功能。
4.Slf4j&Logback:Ceki Gülcü與Apache基金會在Commons-Logging標(biāo)準(zhǔn)上存在分歧。后來,Ceki Gülcü離開了Apache,并創(chuàng)建了Slf4j和Logback兩個項目。Slf4j是一個日志門面,僅提供接口,可以支持Logback、JUL、log4j等日志實現(xiàn)。而Logback則提供了具體的實現(xiàn)。相比于log4j,Logback具有更快的執(zhí)行速度和更完善的功能。
5.Log4j 2:為了保持在Java日志領(lǐng)域的地位,防止JCL和Log4j被Slf4j和Logback取代,Apache在2014年推出了Log4j 2。Log4j 2與log4j不兼容,經(jīng)過大量深度優(yōu)化,其性能得到顯著提升。
日志框架介紹
在上文中已經(jīng)提及,目前常用的日志框架有 Log4j,Log4j 2,Commons Logging,Slf4j,Logback,JUL。這些日志框架可以分為兩種類型:門面日志和日志系統(tǒng)。
日志門面
日志門面(Logging Facade)是一種設(shè)計模式,用于在應(yīng)用程序中實現(xiàn)日志記錄的抽象層。它提供了一組統(tǒng)一的接口和方法,即相應(yīng)的 API,而不提供具體的接口實現(xiàn)。日志門面在使用時,可以動態(tài)或者靜態(tài)地指定具體的日志框架實現(xiàn),解除了接口和實現(xiàn)的耦合,使用戶可以靈活地選擇日志的具體實現(xiàn)框架。
日志系統(tǒng)
日志系統(tǒng)(Logging System)是指用于記錄和管理應(yīng)用程序運行時產(chǎn)生的日志信息的軟件工具或框架。與日志門面相對,它提供了具體的日志接口實現(xiàn),應(yīng)用程序通過它執(zhí)行日志打印的功能,如日志級別管理、日志格式化、日志輸出目標(biāo)設(shè)置等。常見的日志系統(tǒng)包括Log4j、Logback、Java Util Logging等。
通過使用日志門面,我們可以在應(yīng)用程序中使用統(tǒng)一的API進(jìn)行日志記錄,而具體的日志實現(xiàn)可以根據(jù)需要選擇和配置。這樣,我們可以根據(jù)項目需求和團隊喜好來靈活選擇、切換和配置日志系統(tǒng),而不會對應(yīng)用程序代碼造成太大影響。
避免環(huán)形依賴
Slf4j 的作者 Ceki Gülcü 當(dāng)年因為覺得 Commons-Logging 的 API 設(shè)計的不好,性能也不夠高,因而設(shè)計了 Slf4j。而他為了 Slf4j 能夠兼容各種類型的日志系統(tǒng)實現(xiàn),還設(shè)計了相當(dāng)多的 adapter 和 bridge 來連接,如下圖所示:
鑒于此,在引入日志框架依賴的時候要盡力避免,比如以下組合就不能同時出現(xiàn):
?jcl-over-slf4j 和 slf4j-jcl
?log4j-over-slf4j 和 slf4j-log4j12
?jul-to-slf4j 和 slf4j-jdk14
日志框架的使用選擇
常用的組合使用方式是 Slf4j & Logback 組合使用,Commons Logging & Log4j 組合使用。
推薦:
Slf4j & Logback
原因:
1. Slf4j 實現(xiàn)機制決定 Slf4j 限制較少,使用范圍更廣。相較于 Commons-Logging,Slf4j 在編譯期間便靜態(tài)綁定本地的 Log 庫,其通用性要好得多;
2. Logback 擁有更好的性能。Logback 聲稱:某些關(guān)鍵操作,比如判定是否記錄一條日志語句的操作,其性能得到了顯著的提高,這個操作在 Logback 中只需 3 ns,而在 Log4j 則需要 30 ns;
3. Slf4j 支持參數(shù)化,使用占位符號,代碼更為簡潔,如下例子:
// 在使用 Commons-Logging 時,通常的做法是 if(log.isDebugEnabled()){ log.debug("User name: " + user.getName() + " buy goods id :" + good.getId()); } // 在 Slf4j 陣營,你只需這么做: log.debug("User name:{} ,buy goods id :{}", user.getName(),good.getId());
4. Logback 的所有文檔是免費提供的,Log4j 只提供部分免費文檔而需要用戶去購買付費文檔;
5. MDC (Mapped Diagnostic Contexts) 用 Filter,將當(dāng)前用戶名等業(yè)務(wù)信息放入 MDC 中,在日志 format 定義中即可使用該變量。具體而言,在診斷問題時,通常需要打出日志。如果使用 Log4j,則只能降低日志級別,但是這樣會打出大量的日志,影響應(yīng)用性能;如果使用 Logback,保持原定日志級別而過濾某種特殊情況,如 Alice 這個用戶登錄,日志將打在 DEBUG 級別而其它用戶可以繼續(xù)打在 WARN 級別。實現(xiàn)這個功能只需加 4 行 XML 配置;
6. 自動壓縮日志。RollingFileAppender 在產(chǎn)生新文件的時候,會自動壓縮已經(jīng)打出來的日志文件。壓縮過程是異步的,因此在壓縮過程中應(yīng)用幾乎不會受影響。
Slf4j+Logback入門實踐
maven依賴
pom.xml
!--日志框架接口--?> org.slf4j/groupId?> slf4j-api/artifactId?> /dependency?> !--日志框架接口實現(xiàn)--?> ch.qos.logback/groupId?> logback-classic/artifactId?> /dependency?> !--日志框架核心組件--?> ch.qos.logback/groupId?> logback-core/artifactId?> /dependency?> !--自動化注解工具--?> org.projectlombok/groupId?> lombok/artifactId?> 1.18.16/version?> /dependency?>
配置文件
logback.xml
?xml version="1.0" encoding="UTF-8"??> !--默認(rèn)日志配置--?> !-- 控制臺日志 --?> ${CONSOLE_LOG_PATTERN}/pattern?> /encoder?> /appender?> !-- Info日志 --?> ${LOG_PATH}/${LOG_FILE}-info.log/file?> true/append?> INFO/level?> ACCEPT/onMatch?> NEUTRAL/onMismatch?> /filter?> ${LOG_PATH}/${LOG_FILE}-info-%d{yyyy-MM-dd}.%i.log/fileNamePattern?> !-- 日志文件的路徑和名稱 --?> 200MB/maxFileSize?> !-- 單個日志文件的最大大小 --?> /timeBasedFileNamingAndTriggeringPolicy?> 15/maxHistory?> !-- 保留的歷史日志文件數(shù)量 --?> 2GB/totalSizeCap?> !-- 所有日志文件的總大小上限 --?> true/cleanHistoryOnStart?> !-- 在啟動時清除歷史日志文件 --?> /rollingPolicy?> ${FILE_LOG_PATTERN}/pattern?> /encoder?> /appender?> !-- Warn日志 --?> ${LOG_PATH}/${LOG_FILE}-warn.log/file?> true/append?> WARN/level?> ACCEPT/onMatch?> DENY/onMismatch?> /filter?> ${LOG_PATH}/${LOG_FILE}-warn-%d{yyyy-MM-dd}.%i.log/fileNamePattern?> !-- 日志文件的路徑和名稱 --?> 200MB/maxFileSize?> !-- 單個日志文件的最大大小 --?> /timeBasedFileNamingAndTriggeringPolicy?> 15/maxHistory?> !-- 保留的歷史日志文件數(shù)量 --?> 2GB/totalSizeCap?> !-- 所有日志文件的總大小上限 --?> true/cleanHistoryOnStart?> !-- 在啟動時清除歷史日志文件 --?> /rollingPolicy?> ${FILE_LOG_PATTERN}/pattern?> /encoder?> /appender?> !-- Error日志 --?> ${LOG_PATH}/${LOG_FILE}-error.log/file?> true/append?> ERROR/level?> ACCEPT/onMatch?> DENY/onMismatch?> /filter?> ${LOG_PATH}/${LOG_FILE}-error-%d{yyyy-MM-dd}.%i.log/fileNamePattern?> 200MB/maxFileSize?> /timeBasedFileNamingAndTriggeringPolicy?> 15/maxHistory?> 2GB/totalSizeCap?> true/cleanHistoryOnStart?> /rollingPolicy?> ${FILE_LOG_PATTERN}/pattern?> /encoder?> /appender?> !-- 異步輸出 --?> 512/queueSize?> !-- 異步隊列的大小 --?> /appender?> 512/queueSize?> !-- 異步隊列的大小 --?> /appender?> 512/queueSize?> /appender?> !-- 應(yīng)用日志 --?> /logger?> !-- 總?cè)罩境隹?--?> /root?> /configuration?>
applicantion.properties
logging.file=fuqige-bronze logging.path=XXXXXX/Logs/XXXXXX logging.level.root=info logging.level.com.improve.fuqige.bronze=info logging.pattern.console=%cyan(%d{yyyy-MM-dd HH:mm:ss.SSS}) %yellow([%thread]) %highlight(%-5level) %boldGreen(%logger{80}[LineNumber:%L]): %highlight(%msg%n) logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{requestId}] %-5level --- [%thread] %logger{80}[LineNumber:%L]: %msg%n
測試用例
@Slf4j @RestController @RequestMapping("/test") public class TestController { @GetMapping("/hello") public String hello() { log.info("進(jìn)來了!"); log.warn("進(jìn)來了!"); log.error("進(jìn)來了!"); return "hello, world! requestId=" + MDC.get("requestId"); } }
Java 日志框架:
https://zhuanlan.zhihu.com/p/365154773
SLF4J框架常見的用法和最佳實踐:
https://juejin.cn/post/7215569601161166906
審核編輯 黃宇
-
框架
+關(guān)注
關(guān)注
0文章
403瀏覽量
17475 -
logback
+關(guān)注
關(guān)注
0文章
2瀏覽量
896
發(fā)布評論請先 登錄
相關(guān)推薦
評論