我們一起聊聊日志怎么都喜歡用SLF4J
SLF4J,即Simple Logging Facade for Java,是Java日志框架的一個抽象層。它本身并不提供日志的實現(xiàn),而是為各種日志框架(如log4j、logback、java.util.logging等) 提供統(tǒng)一的接口,使開發(fā)者可以更方便地更換日志框架而無需修改代碼。
使用示例
使用slf4j時我們需要優(yōu)先引入其依賴
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
前面說到,Slf4j只是一個日志門面,那么真實使用時我們還需要添加一個該日志的具體的實現(xiàn),比如slf4j-simple、logback,這里選擇slf4j-simple做示例
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.36</version>
</dependency>
然后,通過以下步驟使用SLF4J進行日志記錄:
- 導入SLF4J的Logger和LoggerFactory類:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
- 在類中創(chuàng)建一個Logger對象:
private static final Logger logger=LoggerFactory.getLogger(Printer.class);
- 使用Logger對象記錄日志:
logger.info("This is an info message");
logger.warn("This is an warn message");
logger.error("This is an error message",e);
這里可以通過在classpath中添加simplelogger.properties配置對日志打印級別與內(nèi)容進行調(diào)整
# 全局日志默認級別
org.slf4j.simpleLogger.defaultLogLevel=INFO
# 按包配置日志打印級別
org.slf4j.simpleLogger.log.com.sucl.blog.log.slf4j=WARN
# 顯示時間
org.slf4j.simpleLogger.showDateTime=true
# 時間格式
org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss
# 線程名
org.slf4j.simpleLogger.showThreadName=true
# 包路徑
org.slf4j.simpleLogger.showLogName=true
# 短的包路徑
#org.slf4j.simpleLogger.showShortLogName=false
SLF4J的配置
slf4j-simple只是一個簡單的實現(xiàn),其提供的功能有一定的局限性,并且無法對日志進行持久化,一般生成環(huán)境我們可以選擇logback,只需要將上面的配置進行調(diào)整
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
SLF4J本身不需要配置,因為它只是一個抽象層。配置是針對所選的日志實現(xiàn)框架進行的。例如,如果使用logback作為實現(xiàn)框架,那么需要創(chuàng)建一個logback.xml配置文件,并放置在項目的類路徑下。
logback.xml配置文件的示例:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
Logback是一種Java日志框架,它提供了多種Appender用于將日志輸出到不同的目的地。以下是Logback中常見的幾種Appender及其說明:
- ch.qos.logback.core.ConsoleAppender:
- 說明:將日志輸出到控制臺。
- 用途:通常用于開發(fā)和調(diào)試階段,因為可以直接在控制臺上看到日志輸出。
- ch.qos.logback.core.FileAppender:
- 說明:將日志輸出到指定的文件。
- 用途:適用于將日志持久化到磁盤,方便后續(xù)查看和分析。
- ch.qos.logback.core.rolling.RollingFileAppender:
- 說明:將日志輸出到文件,當文件達到一定大小時,會自動滾動(即創(chuàng)建新的日志文件)。
- 用途:適用于需要長時間運行的應用,可以避免單一日志文件過大導致的問題。
- ch.qos.logback.classic.db.DBAppender:
- 說明:將日志寫入到數(shù)據(jù)庫中。
- 用途:適用于需要將日志長期保存或進行復雜查詢的場景。
- ch.qos.logback.classic.net.SocketAppender:
- 說明:將日志發(fā)送到指定的socket服務器。
- 用途:適用于需要將日志發(fā)送到遠程服務器或進行集中管理的場景。
- ch.qos.logback.classic.net.SMTPAppender:
- 說明:將日志以電子郵件的形式發(fā)送。
- 用途:適用于需要將重要日志或錯誤日志及時通知給相關(guān)人員的場景。
- ch.qos.logback.classic.net.SyslogAppender:
- 說明:將日志發(fā)送到syslog服務器。
- 用途:適用于需要將日志與系統(tǒng)的其他日志進行統(tǒng)一管理的場景。
除了上述常見的Appender外,Logback還支持自定義Appender,可以根據(jù)具體需求擴展日志輸出的目的地。每種Appender都有其特定的用途和適用場景,可以根據(jù)實際需求選擇合適的Appender進行配置。
日志的統(tǒng)一
SLF4J可以與多種日志框架結(jié)合使用,如Logback、Log4j和JDK自帶的日志框架。只需將SLF4J的依賴和所選日志框架的依賴添加到項目中,并在配置文件中進行相應的配置即可。
- 與Log4j結(jié)合使用
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
- 與JDK自帶的日志框架結(jié)合使用
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.30</version>
</dependency>
實際項目中我們會引用很對外部jar,然而每個jar中使用的日志框架不可能完全相同,我們不可能為每一種日志提供專門的配置,而且日志的輸出形式也很難統(tǒng)一,所以需要一種方式將所有第三方框架 的日志信息統(tǒng)一管理起來,前面說到的日志橋接就起到了作用。
比如我們當前系統(tǒng)使用的是slf4j+logback作為日志框架,現(xiàn)在引用了一個jar,它的日志框架選擇了log4j2,示例如下:
依賴的log4j2:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
日志配置classpath:log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN" monitorInterval="30">
<appenders>
<console name="Console">
<!--輸出日志的格式-->
<PatternLayout pattern="log4j2-> [%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
</console>
</appenders>
<loggers>
<root level="debug">
<appender-ref ref="Console"/>
</root>
</loggers>
</configuration>
內(nèi)部會這樣使用
public class Log4j2Printer {
private static final Logger LOGGER = LogManager.getLogger(Log4j2Printer.class);
public void doPrint(String info){
LOGGER.debug("調(diào)試打?。簕}", info);
LOGGER.info("打?。簕}", info);
LOGGER.warn("警告打?。簕}", info);
LOGGER.error("錯誤打印:{}", info);
}
}
日志的輸出:
slf4j-> 22:21:44.212 [main] INFO c.s.b.l.slf4j.logback.LogbackPrinter - 打?。何沂莑ogback的日志
slf4j-> 22:21:44.216 [main] WARN c.s.b.l.slf4j.logback.LogbackPrinter - 警告打?。何沂莑ogback的日志
slf4j-> 22:21:44.216 [main] ERROR c.s.b.l.slf4j.logback.LogbackPrinter - 錯誤打?。何沂莑ogback的日志
log4j2-> [22:21:44:605] [INFO] - com.sucl.blog.log.slf4j.log4j2.Log4j2Printer.doPrint(Log4j2Printer.java:17) - 打印:我是log4j2的日志
log4j2-> [22:21:44:606] [WARN] - com.sucl.blog.log.slf4j.log4j2.Log4j2Printer.doPrint(Log4j2Printer.java:18) - 警告打?。何沂莑og4j2的日志
log4j2-> [22:21:44:608] [ERROR] - com.sucl.blog.log.slf4j.log4j2.Log4j2Printer.doPrint(Log4j2Printer.java:19) - 錯誤打?。何沂莑og4j2的日志
這時只需要引入一個橋架包,這樣我們只需要配置項目中的logback.xml,第三方的所有l(wèi)og4j2打印的日志則會按照我們的配置統(tǒng)一輸出
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</dependency>
日志橋接允許應用程序在不更改代碼的情況下,靈活地切換或同時使用不同的日志框架實現(xiàn)。具體來說,日志橋接包的意義體現(xiàn)在以下幾個方面:
- 接口標準化:日志橋接包如SLF4J提供了一套標準的日志API,這意味著無論底層使用哪種日志實現(xiàn)(如Logback、Log4j等),開發(fā)者都可以使用相同的API進行日志記錄。
- 實現(xiàn)靈活切換:通過使用橋接包,項目可以輕松切換到不同的日志框架。例如,如果項目最初使用的是Log4j,但后來想要切換到Logback,只需添加相應的橋接包依賴即可,無需修改代碼。
- 維護兼容性:對于遺留系統(tǒng)或者第三方庫中使用的特定日志框架,橋接包可以保證這些系統(tǒng)或庫的日志調(diào)用能夠被當前項目中使用的日志框架正確處理。
- 減少依賴沖突:在使用多個第三方庫時,這些庫可能依賴于不同的日志框架。橋接包可以解決這些庫之間的日志框架沖突問題,確保它們能夠和平共處。
- 提高可移植性:由于橋接包的存在,項目的日志系統(tǒng)不再是與特定日志框架強綁定的,這使得項目在不同的運行環(huán)境或部署環(huán)境中更容易移植和配置。
- 簡化依賴管理:使用橋接包可以減少項目中直接引入的日志框架實現(xiàn)數(shù)量,從而簡化了依賴管理,避免了潛在的版本沖突和依賴混亂的問題。
框架實現(xiàn)原理
SLF4J的實現(xiàn)原理主要基于Java的接口和抽象類。它定義了一套統(tǒng)一的日志記錄接口,并提供了一個LoggerFactory類用于創(chuàng)建Logger對象。Logger對象負責實際的日志記錄操作,但具體的實現(xiàn)細節(jié)則委托給了所選的日志框架。
接口層:定義了日志記錄的接口,如Logger、LoggerFactory等。實現(xiàn)層:各種日志框架的具體實現(xiàn),如Logback、Log4j等。橋接層:將接口層與實現(xiàn)層連接起來,使得應用程序可以在不同的日志框架之間輕松切換。
日志打印中的問題
在使用SLF4J進行日志記錄時,可能會遇到一些問題,如日志不打印、日志級別不正確等。這些問題通常與所選日志框架的配置有關(guān),需要檢查配置文件和代碼中的日志記錄語句。
另外,還需要注意以下幾點:
- 確保項目中只包含一個SLF4J的實現(xiàn)框架,避免產(chǎn)生沖突。
- 檢查日志級別設(shè)置,確保所需的日志級別沒有被禁用。
- 檢查Logger對象的創(chuàng)建方式是否正確,確保Logger對象與當前類關(guān)聯(lián)。
- 檢查日志記錄語句是否正確,確保日志消息和參數(shù)都正確傳遞給了Logger對象。
- 日志級別不清晰:不同級別的日志應該有明顯的區(qū)分,以便于查找和定位問題。
- 日志信息不足:日志應該包含足夠的信息,以便于分析問題。
- 日志輸出格式不統(tǒng)一:為了方便查看和管理,日志的輸出格式應該統(tǒng)一。
- 日志性能問題:在高并發(fā)場景下,日志的性能可能會受到影響,需要選擇合適的日志框架和配置。
總結(jié)
SLF4J是一個強大的日志框架,它簡化了日志記錄的過程,并提供了與多種日志框架的兼容性。通過深入了解SLF4J的使用和配置, 我們可以更好地利用它進行Java應用的日志記錄和管理。希望本文能夠幫助讀者更好地理解和使用SLF4J日志框架。