忽視日志吃大虧,手把手教你玩轉(zhuǎn) SpringBoot 日志!
程序中的日志重要嗎?
在回答這個問題前,筆者先說個事例:
筆者印象尤深的就是去年某個同事,收到了客戶反饋的緊急bug。盡管申請到了日志文件,但因為很多關(guān)鍵步驟沒有打印日志,導(dǎo)致排查進度很慢,數(shù)個小時都沒能排查到問題,也無法給出解決對策。導(dǎo)致了客戶程序一直阻斷,最終產(chǎn)生了不少損失。事后,經(jīng)過仔細推敲,成功復(fù)現(xiàn)了這個bug,其實是一個很不起眼的數(shù)據(jù)轉(zhuǎn)換導(dǎo)致的。可因為日志內(nèi)容的匱乏,排查起來難度很大。其實只要在數(shù)據(jù)轉(zhuǎn)換前后進行日志輸出,這個問題就是一眼的事。但可惜沒如果,故事的最后,開發(fā)部門還是遭到了客戶的投訴,影響到了部門績效。
對于剛學習編程的同學,很多人都對日志滿不在乎,我們在做code review的時候,經(jīng)常發(fā)現(xiàn)一些新同學喜歡一個方法寫得很長,然后中間的注釋和日志都少的可憐。
坦白的說,這是很不好的習慣,這意味著日后方法出了bug,或者需要迭代,要花費大量時間來理清方法的思路。千萬別迷信什么“方法名、字段名起的見明知意,就可以不寫注釋與日志”,那是他們的業(yè)務(wù)場景不夠復(fù)雜。以筆者為例,復(fù)雜的場景涉及很多公式、奇特的規(guī)定,不寫注釋與日志,后續(xù)沒人能維護得了
所以請務(wù)必記住,日志在開發(fā)過程中非常重要。它可以幫助開發(fā)人員了解程序中發(fā)生了什么,以及在某些情況下為什么會發(fā)生錯誤或異常。通過查看日志,開發(fā)人員可以輕松地定位并解決問題,并且可以更好地監(jiān)控和調(diào)整應(yīng)用程序的性能,在必要時進行故障排除和安全檢查
日志分級
最開始的日志分級是由Syslog的開發(fā)者Eric Allman在1981年提出的。之后,這個級別分級系統(tǒng)被廣泛應(yīng)用于各種領(lǐng)域的日志記錄和信息處理中。下面我們就來介紹下常用的日志等級
-
TRACE
是最低級別的日志記錄,用于輸出最詳細的調(diào)試信息,通常用于開發(fā)調(diào)試目的。在生產(chǎn)環(huán)境中,應(yīng)該關(guān)閉 TRACE 級別的日志記錄,以避免輸出過多無用信息。
-
DEBUG
是用于輸出程序中的一些調(diào)試信息,通常用于開發(fā)過程中。像 TRACE 一樣,在生產(chǎn)環(huán)境中應(yīng)該關(guān)閉 DEBUG 級別的日志記錄。
-
INFO
用于輸出程序正常運行時的一些關(guān)鍵信息,比如程序的啟動、運行日志等。通常在生產(chǎn)環(huán)境中開啟 INFO 級別的日志記錄。
-
WARN
是用于輸出一些警告信息,提示程序可能會出現(xiàn)一些異常或者錯誤。在應(yīng)用程序中,WARN 級別的日志記錄通常用于記錄一些非致命性異常信息,以便能夠及時發(fā)現(xiàn)并處理這些問題。
-
ERROR
是用于輸出程序運行時的一些錯誤信息,通常表示程序出現(xiàn)了一些不可預(yù)料的錯誤。在應(yīng)用程序中,ERROR 級別的日志記錄通常用于記錄一些致命性的異常信息,以便能夠及時發(fā)現(xiàn)并處理這些問題。
當然,除了這五種級別以外,還有一些日志框架定義了其他級別,例如 Python 中的 CRITICAL、PHP 中的 FATAL 等。CRITICAL 和 FATAL 都是用于表示程序出現(xiàn)了致命性錯誤或者異常,即不可恢復(fù)的錯誤。當然,對于我們今天要說的內(nèi)容,知道上述五種日志等級就夠了。
常用日志插件
-
Log4j(1999年誕生)
Log4j 是Java領(lǐng)域中最早的流行日志框架之一。它由Ceki Gülcü開發(fā),并后來由Apache軟件基金會接管。Log4j 提供了靈活的配置選項、多種輸出目的地、日志級別和分層日志體系。盡管Log4j 1在其時代取得了巨大的成功,但在性能和某些功能方面存在限制,因此后來演化為Log4j 2。
-
SLF4J(2004年誕生)
嚴格來說,SLF4J(Simple Logging Facade for Java)并不算一個插件,而是Ceki Gülcü開發(fā)的一個日志門面接口。它為Java應(yīng)用程序提供了統(tǒng)一的日志抽象,使開發(fā)人員可以使用一致的API進行日志記錄,而不需要直接依賴于特定的日志實現(xiàn)。SLF4J 可以與多種底層日志框架(如Logback、Log4j 2、java.util.logging等)結(jié)合使用。
-
Logback(2009年誕生)
Logback 是Ceki Gülcü開發(fā)的日志框架,他也是Log4j的作者。Logback 是Log4j 1的后續(xù)版本,旨在提供更高性能、更靈活的配置和現(xiàn)代化的日志解決方案。Logback 支持異步日志記錄、多種輸出格式、靈活的配置以及與SLF4J緊密集成。
-
Log4j 2(2014年誕生)
Log4j 2 是Apache軟件基金會開發(fā)的Log4j的下一代版本。它引入了許多新特性,如異步日志記錄、插件支持、豐富的過濾器等,旨在提供更好的性能和靈活性。Log4j 2 在設(shè)計上考慮了Log4j 1的局限性,并且支持多種配置方式。
-
小故事
不難注意到,一個有意思的小故事是,前三款日志插件都是Ceki Gülcü開發(fā)的,但 Log4j 2 并不是,雖然現(xiàn)在有很多人以為log4j2也是他寫的,但我們在github上可以看到其個人說明 “Unaffiliated with log4j 2.x.” (與 log4j 2.x 無關(guān)),所以log4j2 和 logback 都自稱是log4j 的后續(xù)版本,到底誰才算正統(tǒng)續(xù)作呢?這就留給各位讀者自己玩味了
外觀模式與SLF4J
在講解更多插件詳情之前,我們先來看看使用最多的SLF4J ,我們前面說了 SLF4J(Simple Logging Facade for Java)是Ceki Gülcü開發(fā)的一個日志門面接口,那么很顯然這里就用到了門面模式(即Facade 或 外觀模式),筆者比較習慣說成是外觀模式,后續(xù)就稱為外觀模式。
1. 外觀模式
定義:外觀模式是一種結(jié)構(gòu)型設(shè)計模式,它提供了一個簡單的接口,封裝了底層復(fù)雜的子系統(tǒng),使得客戶端可以更方便地使用這個子系統(tǒng)
目的:外觀模式的目的是隱藏底層系統(tǒng)的復(fù)雜性,降低訪問成本。
如果說看定義有些抽象,那我們可以以生活中的例子來說,我們都知道現(xiàn)在越來越流行智能家居,也就是家庭內(nèi)裝了很多智能家電,從電視、空調(diào)、到廊燈甚至窗簾都是智能的。這類家庭往往會有一個控制中心,我們不需要手動去開電視,只需要對著控制中心說:“小A小A,幫我打開電視,音量調(diào)到30%”,電視就會應(yīng)聲打開并調(diào)節(jié)音量
那么這樣的話,我們不需要知道怎么開電視,怎么調(diào)音量。通通都能用最簡單的話語來調(diào)節(jié)。同理,現(xiàn)在手機上的拍照功能:感光度,對焦,白平衡這些細節(jié)都給你自動完成了,所以這些復(fù)雜的內(nèi)容你現(xiàn)在根本不用管,只需要猛按拍照鍵即可。
這就是外觀模式的意義,外觀模式就是為了隱藏系統(tǒng)的復(fù)雜性而設(shè)計出來的,讓客戶端只對接觸到一個外觀類,而不會接觸到系統(tǒng)內(nèi)部的復(fù)雜邏輯
2. SLF4J 的誕生
在早期使用日志框架時,應(yīng)用程序通常需要直接與具體的日志框架進行耦合,這就導(dǎo)致了以下幾個問題:
-
代碼依賴性
應(yīng)用程序需要直接引用具體的日志框架,從而導(dǎo)致代碼與日志框架強耦合,難以滿足應(yīng)用程序?qū)θ罩究蚣艿撵`活配置。
-
日志框架不統(tǒng)一
在使用不同的日志框架時,應(yīng)用程序需要根據(jù)具體的日志框架來編寫代碼,這不僅會增加開發(fā)難度,而且在多種日志框架中切換時需要進行大量的代碼改動。
-
性能問題
在日志輸出頻繁的情況下,由于日志框架的實現(xiàn)方式和API設(shè)計不同,可能會導(dǎo)致性能問題。
為了解決這些問題,SLF4J提供了一套通用的日志門面接口,讓應(yīng)用程序可以通過這些接口來記錄日志信息,而不需要直接引用具體的日志框架。這樣,應(yīng)用程序就可以在不同的日志框架之間進行靈活配置和切換,同時還可以獲得更好的性能表現(xiàn)。所以,我強烈建議各位使用SLF4J, 而不是直接對接某個具體的日志框架。
3. SLF4J 的使用
首先,我們需要在工程內(nèi)引入包,但是如果你用了springboot,各種 spring-boot-starter 啟動器已經(jīng)引用過了,所以引用前最好確認下:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
然后在我們要打印日志的類里加上一行 ;private static final Logger logger = LoggerFactory.getLogger(XXXX.class); 即可使用,如下:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass {
private static final Logger log = LoggerFactory.getLogger(MyClass.class);
//...
public static void main(String[] args) {
log.info("This is an info message.");
}
}
如果我們引用了lombok的話,也可以使用lombok的注解@Slf4j 代替上面那句話來使用 SLF4J ,如下:
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MyClass {
public static void main(String[] args) {
log.info("This is an info message.");
}
}
但是,我們都知道SLF4J僅僅是個門面,換句話說,僅有接口而沒有實現(xiàn),如果此刻我們直接運行,打印日志是沒有用處的
所以,我們?nèi)绻\行,我們必須要給 SLF4J 安排上實現(xiàn),而目前最常用的就是 logback 和 log4j2 了,就讓我們接著往下看
雙雄之爭
其實關(guān)于 Logback 和 Log4j 2,網(wǎng)絡(luò)上有很多評測,就不需贅述了,主要是圍繞性能方面的,從目前大家的反饋看,Log4j 2 晚出現(xiàn)好幾年,還是有后發(fā)優(yōu)勢的,性能會比 Logback 好。當然, Logback 本身性能也很強,對于大多數(shù)場景,完全是夠用的,而且配置比較直觀,是spring-boot 默認使用的日志插件。
所以,選誰都可以,如果不想費神,可以直接使用spring-boot自帶的Logback,如果對日志性能要求很高,使用log4j2更保險,我們接下來分別介紹兩者。
1. Logback
1. 引用
由于 Logback 為 spring-boot 默認日志框架,所以無需再引用,但對于非spring - boot 項目,可以做如下引用
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.12</version>
</dependency>
Logback 的核心模塊為 logback-classic,它提供了一個 SLF4J 的實現(xiàn),兼容 Log4j API,可以無縫地替換 Log4j。它自身已經(jīng)包含了 logback-core 模塊,而 logback-core,顧名思義就是 logback 的核心功能,包括日志記錄器、Appender、Layout 等。其他 logback 模塊都依賴于該模塊
2. 配置
logback 可以通過 XML 或者 Groovy 配置。下面以 XML 配置為例。logback 的 XML 配置文件名稱通常為 logback.xml 或者 logback-spring.xml(在 Spring Boot 中),需要放置在 classpath 的根目錄下,
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--定義日志文件的存儲地址,使用Spring的屬性文件配置方式-->
<springProperty scope="context" name="log.home" source="log.home" defaultValue="logs"/>
<!--定義日志文件的路徑-->
<property name="LOG_PATH" value="${log.home}"/>
<!--定義控制臺輸出-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<!--定義 INFO 及以上級別信息輸出到控制臺-->
<root level="INFO">
<appender-ref ref="console"/>
</root>
<!--定義所有組件的日志級別,如所有 DEBUG-->
<logger name="com.example" level="DEBUG"/>
<!-- date 格式定義 -->
<property name="LOG_DATEFORMAT" value="yyyy-MM-dd"/>
<!-- 定義日志歸檔文件名稱格式,每天生成一個日志文件 -->
<property name="ARCHIVE_PATTERN" value="${LOG_PATH}/%d{${LOG_DATEFORMAT}}/app-%d{${LOG_DATEFORMAT}}-%i.log.gz"/>
<!--定義文件輸出,會根據(jù)定義的閾值進行切割,支持自動歸檔壓縮過期日志-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--定義日志文件切割的閾值,本例是 50MB-->
<maxFileSize>50MB</maxFileSize>
<!--定義日志文件保留時間,本例是每天生成一個日志文件-->
<fileNamePattern>${ARCHIVE_PATTERN}</fileNamePattern>
<maxHistory>30</maxHistory>
<!-- zip 壓縮生成的歸檔文件 -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 刪除過期文件 -->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<!--定義 ERROR 級別以上信息輸出到文件-->
<logger name="com.example.demo" level="ERROR" additivity="false">
<appender-ref ref="file"/>
</logger>
<!--異步輸出日志信息-->
<appender name="asyncFile" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>256</queueSize>
<appender-ref ref="file"/>
</appender>
<!--定義INFO及以上級別信息異步輸出到文件-->
<logger name="com.example" level="INFO" additivity="false">
<appender-ref ref="asyncFile"/>
</logger>
</configuration>
其中,主要包括以下配置:
-
springProperty 定義了 log 文件的存儲路徑,可以通過 Spring 的屬性文件配置方式進行設(shè)置,如果沒有配置則默認存儲在 logs 目錄下。 -
appender 定義了日志輸出的目標,這里包括了控制臺輸出和文件輸出兩種,具體可以根據(jù)需求進行配置。 -
root 定義了默認的日志級別和輸出目標,默認情況下,INFO 級別以上的日志信息會輸出到控制臺,可以根據(jù)實際需求進行修改。 -
logger 定義了不同組件的日志級別和輸出目標,例如,這里定義了 com.example 這個組件的日志級別為 DEBUG,而 com.example.demo 這個組件的日志級別為 ERROR,并將其輸出到文件中。 -
rollingPolicy 定義了日志文件的切割規(guī)則和歸檔策略,此處定義了日志文件每個 50MB 進行切割,每天生成一個日志文件,并且壓縮和刪除過期文件,最多保留 30 天的日志文件。 -
encoder 定義了日志信息的輸出格式,具體的格式可以自行定義。 -
asyncAppender 定義了異步輸出日志的方式,對于高并發(fā)時,可以使用異步輸出來提高系統(tǒng)的性能。 -
discardingThreshold 定義了異步輸出隊列的閾值,當隊列中的數(shù)據(jù)量超過此值時,會丟棄最早放入的數(shù)據(jù),此處設(shè)置為 0 表示隊列不會丟棄任何數(shù)據(jù)。 -
queueSize 定義了異步輸出隊列的大小,當隊列滿時,會等待隊列中的數(shù)據(jù)被消費后再將數(shù)據(jù)放入隊列中,此處設(shè)置為 256。
3. 演示
我們新建一個普通工程(非spring工程),引用Logback后,把上述配置文件復(fù)制進logback.xml,然后將工程結(jié)構(gòu)設(shè)置成如下模式
其中兩個類的代碼如下:
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.trace("This is a Main trace message.");
log.debug("This is a Main debug message.");
log.info("This is a Main info message.");
log.warn("This is a Main warn message.");
log.error("This is a Main error message.");
Slave.main(args);
}
}
public class Slave {
private static final Logger log = LoggerFactory.getLogger(Slave.class);
public static void main(String[] args) {
log.trace("This is a Slave trace message.");
log.debug("This is a Slave debug message.");
log.info("This is a Slave info message.");
log.warn("This is a Slave warn message.");
log.error("This is a Slave error message.");
}
}
我們想實現(xiàn)這樣的效果,首先日志要同時 輸出到控制臺 及 日志文件,且不同層級的代碼,輸出的日志層級也不同。那么我們可以對上述的xml做出一些調(diào)整:
因為是非Spring項目,所以 springProperty 這樣的標簽就不要用了,我們直接寫死一個日志文件地址即可。
<!--定義日志文件的路徑-->
<property name="LOG_PATH" value="D://logs/log"/>
去掉原有的那些root、logger標簽,我們自己新建兩個logger,用于兩個不同的層級。我們想里層輸出 debug 級別,外層輸出info 級別,我們可以這么設(shè)置。并且同時輸出到控制臺及日志文件
<logger name="com.zhanfu" level="INFO">
<appender-ref ref="file" />
<appender-ref ref="console"/>
</logger>
<logger name="com.zhanfu.child" level="DEBUG" additivity="false">
<appender-ref ref="file" />
<appender-ref ref="console"/>
</logger>
當我們運行Main.main的時候,就可以得到以下日志,slave 能輸出debug級別,Main 只能輸出 info及以上級別
4. 細節(jié)點
其實我們上面的演示,有兩個細節(jié)點,需要注意一下。一個就是我們的
<logger name="com.zhanfu.child" level="DEBUG" additivity="false">
使用了一個 additivity="false" 的屬性,這其實是因為 logger 這個標簽在鎖定某個目錄時,可能會發(fā)生層級關(guān)系。比如我們的兩個 logger, 一個針對的目錄是 com.zhanfu 另一個是 com.zhanfu.child ,后者就會被前者包含。
當我們的 com.zhanfu.child.Slave 打印日志時,當然會使用后者(更精確)的設(shè)置,但前者的設(shè)置還使用嗎?就依賴于 additivity=“false”,此處如果我們把 additivity="false" (該屬性默認值為true)去掉,再來打印日志
就會發(fā)現(xiàn),Slave 的日志打了兩遍,而且連 debug 級別的都打了兩遍,我們可以把這種邏輯理解為繼承,子類執(zhí)行一遍,父類還能在執(zhí)行一遍,但 leve 屬性還是會采用子類而非父類的。
另一點就是我們把 root 標簽刪除了,root 其實是一個頂級的 logger , 其他的logger都可以視為它的子類,如果那些logger存在沒涵蓋的地方,或其沒有指定 additivity="false" ,那最后root的設(shè)置就會被使用。比如我們將設(shè)置改為如下:
<logger name="com.zhanfu" level="INFO">
<appender-ref ref="file" />
<appender-ref ref="console"/>
</logger>
<logger name="com.zhanfu.child" level="DEBUG">
<appender-ref ref="file" />
<appender-ref ref="console"/>
</logger>
<root level="WARN">
<appender-ref ref="console"/>
</root>
結(jié)果控制臺的輸出日志,Main會重復(fù)兩次,Slave 會重復(fù)三次,如下
但是因為我們的 root 只配置了控制臺輸出,所以日志文件里還是不會變的
2. Log4j 2
1. 引用
對于spring-boot項目,除了引用 Log4j 2 我們還需要先剔除 Logback 的引用,對于普通項目,我們只需直接引用即可。但注意我們的原則,通過 SLF4J 來使用 Log4j2,所以引用下面這個包
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.13.3</version>
</dependency>
其內(nèi)包含 Log4j2 的實現(xiàn),和 SLF4J 的 API,如下:
2. 配置
Log4j2 的配置邏輯和 logback 是類似的,只有些細節(jié)不同,比如Logger 的首字母大寫等等,最后我們寫下這樣一個 log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" monitorInterval="30">
<Properties>
<Property name="logPath">logs</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{ISO8601} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<RollingFile name="File" fileName="${logPath}/example.log"
filePattern="${logPath}/example-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="%d{ISO8601} [%t] %-5level %logger{36} - %msg%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
<DefaultRolloverStrategy max="4"/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="com.zhanfu.child" level="DEBUG">
<AppenderRef ref="File"/>
<AppenderRef ref="Console"/>
</Logger>
<Logger name="com.zhanfu" level="INFO">
<AppenderRef ref="File"/>
<AppenderRef ref="Console"/>
</Logger>
<Root level="WARN">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
-
Properties
部分定義了一個 logPath 屬性,方便在其他地方引用。
-
Appenders
定義了兩個 Appender:Console 和 RollingFile,分別將日志輸出到控制臺和文件中。RollingFile 使用了 RollingFileAppender,并設(shè)置了日志滾動策略和默認的備份文件數(shù)量。
-
Loggers
定義了三個 Logger:com.zhanfu.child 的日志級別為 DEBUG,com.zhanfu 的日志級別為INFO,Root Logger 的日志級別為 WARN。并指定了兩個 Appender:Console 和 File。
3. 演示
由于我們的配置邏輯沒變,所以日志的結(jié)果還是一樣的:
3. 對比
Log4j2和Logback都是Java應(yīng)用程序中最流行的日志框架之一。它們均具備高度的可配置性和使用靈活性,并提供了一系列有用的功能,例如異步日志記錄和日志過濾等。下面從配置遍歷性、功能性、性能等方面進行比較和總結(jié)。
配置遍歷性
Logback的配置文件格式相對簡單,易于閱讀和修改。它支持符號來引用變量、屬性和環(huán)境變量等。此外,它還支持條件日志記錄(根據(jù)日志級別、日志記錄器名稱或時間等),以及滾動文件的大小或日期等。
Log4j2的配置文件格式較復(fù)雜,但它在配置文件中提供了大量的選項來控制日志記錄。它支持在配置文件中直接聲明上下文參數(shù)、過濾器、輸出器和Appender等,這使得它的配置更加靈活。此外,Log4j2還支持異步日志記錄、日志事件序列化和性能優(yōu)化等。
微信搜索公眾號:架構(gòu)師指南,回復(fù):架構(gòu)師 領(lǐng)取資料 。
總體來說,兩者都很好地支持了配置遍歷性,但Log4j2提供了更多的選項和更高的靈活性。
功能性
Logback提供了一系列基本的日志記錄功能,例如異步Appender、滾動文件和GZIP壓縮等。它還支持與SLF4J一起使用,可以很容易地與其他日志框架集成。
Log4j2提供了更多的高級功能,例如異步日志記錄、性能優(yōu)化和日志事件序列化等。它還支持Lambda表達式,可以使日志記錄器更加簡潔和易讀。此外,Log4j2還支持Flume和Kafka等大數(shù)據(jù)處理框架,可以方便地將日志記錄發(fā)送到這些框架中。
總體來說,Log4j2提供了更多的高級功能,并且可以更好地與大數(shù)據(jù)處理框架集成。
性能
Logback的性能很好,可以處理高吞吐量的日志記錄。它采用了異步記錄器,利用了多線程來提高性能。
Log4j2在性能方面更加強大。它使用了異步記錄器和多線程,還引入了RingBuffer數(shù)據(jù)結(jié)構(gòu)和Disruptor庫來加速日志事件的傳遞和處理。這使得它比Logback具有更高的吞吐量和更低的延遲。
綜上所述,Log4j2在配置靈活性、功能性和性能方面都比Logback更為強大。但如果需要輕量級的日志框架或者只需要基本的日志記錄功能,Logback也是一個不錯的選擇
但如果我們同時引用了這兩者,會報錯嗎?還是會使用其中的某一個?
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.13.3</version>
</dependency>
可以看到,SLF4J 發(fā)現(xiàn)了系統(tǒng)中同時存在兩個插件框架,并最終選擇了使用 Logback
總結(jié)
學習完本文,你應(yīng)當對現(xiàn)在這幾個常用框架的有所了解,并能基礎(chǔ)應(yīng)用了。此次我們沒有講源碼,也沒有深入的講其配置及進階使用,這些我們會在后面慢慢學習。但現(xiàn)在我希望你能知道的是。一定要寫好日志,一定要寫好日志,一定要寫好日志。重要的事情說三遍!這是區(qū)別新人和老鳥的一個重要依據(jù),也是讓自己排查問題更輕松的不二法門!
另外,現(xiàn)在很多中間件都自己引用了日志插件,我們作為一個整體工程在使用中間件時,要及時發(fā)現(xiàn)并解決插件沖突,避免我們自己的日志配置失效,這也是一個程序員該注意的點。
來源:blog.csdn.net/u011709538/
article/details/132363370
關(guān)注公眾號:Java后端編程,回復(fù)下面關(guān)鍵字
要Java學習完整路線,回復(fù) 路線
缺Java入門視頻,回復(fù): 視頻
要Java面試經(jīng)驗,回復(fù) 面試
缺Java項目,回復(fù): 項目
進Java粉絲群: 加群
PS:如果覺得我的分享不錯,歡迎大家隨手點贊、在看。
(完)
加我"微信" 獲取一份 最新Java面試題資料 請備注:666,不然不通過~
最近好文
3、Spring Boot + Gzip 壓縮超大 JSON 對象,傳輸大小減少一半!
最近面試BAT,整理一份面試資料《Java面試BAT通關(guān)手冊》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。 獲取方式:關(guān)注公眾號并回復(fù) java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。 明天見(??ω??)??
