一篇文章帶你徹底搞懂Java日志與Logback
一、為什么需要日志?
在開(kāi)發(fā)和運(yùn)維一個(gè)系統(tǒng)時(shí),我們經(jīng)常會(huì)有這樣的需求:
- 想清楚地知道系統(tǒng)運(yùn)行了哪些步驟
- 某個(gè)時(shí)間點(diǎn)系統(tǒng)發(fā)生了什么錯(cuò)誤
- 用戶(hù)反饋“系統(tǒng)卡了/掛了”,希望能還原當(dāng)時(shí)的現(xiàn)場(chǎng)
這時(shí)候就離不開(kāi):日志(Log)。
很多初學(xué)者一開(kāi)始就是在代碼里到處寫(xiě) System.out.println(...) 來(lái)“打日志”。 這種方式雖然簡(jiǎn)單,但有幾個(gè)明顯弊端:
1. 輸出語(yǔ)句的弊端
- 信息只能顯示在控制臺(tái),關(guān)掉控制臺(tái)就什么都沒(méi)了
- 無(wú)法方便地記錄到文件、數(shù)據(jù)庫(kù)等其他位置
- 想“停用日志”或者“少打印點(diǎn)日志”,就得改代碼、重新打包、重新上線(xiàn)
對(duì)于一個(gè)真正的線(xiàn)上系統(tǒng),這些都是難以接受的。
2. 日志技術(shù)的優(yōu)勢(shì)
專(zhuān)業(yè)的日志框架能幫我們解決上述問(wèn)題,它具備這些能力:
- 可以將系統(tǒng)執(zhí)行信息選擇性地記錄到:
- 控制臺(tái)
- 文件
- 數(shù)據(jù)庫(kù)(一般不推薦大量打到 DB,中間件會(huì)偶爾這么做)
- 可以通過(guò)配置文件來(lái)控制:
- 哪些日志記錄
- 記錄到哪里
- 以什么格式記錄
- 用什么級(jí)別(debug/info/warn/error)
- 可以通過(guò)“開(kāi)關(guān)(級(jí)別設(shè)置)”來(lái)決定是否記錄日志,而無(wú)需修改源代碼
一句話(huà):日志框架讓“日志”變成一種可配置、可控制的基礎(chǔ)設(shè)施。
二、日志體系:接口與實(shí)現(xiàn)
Java 生態(tài)中的日志并不是一個(gè)單一庫(kù),而是一個(gè)分層體系,大致可以理解為兩類(lèi):
- 日志規(guī)范接口(Facade,門(mén)面)
- 日志實(shí)現(xiàn)框架(具體干活的)
1. 日志規(guī)范接口
常見(jiàn)的日志接口:
- Commons Logging (簡(jiǎn)稱(chēng):JCL)
- Simple Logging Facade for Java (簡(jiǎn)稱(chēng):slf4j)
它們本質(zhì)上是一組接口,定義了像 info()、debug()、error() 等方法。 這些接口并不關(guān)心日志具體如何輸出、存在哪里,而是提供給各類(lèi)日志實(shí)現(xiàn)框架一個(gè)統(tǒng)一的規(guī)范。
2. 日志實(shí)現(xiàn)框架
一些典型的日志實(shí)現(xiàn)框架:
- Log4j
- Logback
- Log4j2 等
這些框架才是真正干活的,負(fù)責(zé)把日志按要求寫(xiě)到控制臺(tái)、文件、網(wǎng)絡(luò)等地方。
因?yàn)閷?duì) Commons Logging 的接口不滿(mǎn)意,有人搞了 SLF4J;
因?yàn)閷?duì) Log4j 的性能不滿(mǎn)意,有人搞了 Logback。
Java 日志體系就是這樣一步步演進(jìn)出來(lái)的。
在現(xiàn)代項(xiàng)目中,常見(jiàn)組合是:
- 代碼依賴(lài) SLF4J 接口
- 底層使用 Logback 作為實(shí)現(xiàn)
這樣你寫(xiě)的代碼只依賴(lài)接口,以后如果要更換日志實(shí)現(xiàn)(從 Logback 換成 Log4j2 等),只要改依賴(lài)和配置,而不用改業(yè)務(wù)代碼。
三、Logback 概述
1. 什么是 Logback?
Logback是一個(gè)高性能的日志框架:
- 由 Log4j 作者開(kāi)發(fā),是 Log4j 的“進(jìn)化版”
- 基于 SLF4J 日志規(guī)范實(shí)現(xiàn)
- 性能和功能上普遍優(yōu)于傳統(tǒng)的 Log4j
很多現(xiàn)代框架(例如 Spring Boot)默認(rèn)都使用 Logback 作為日志實(shí)現(xiàn)。
2. Logback
Logback 主要分為三個(gè)模塊:
logback-core- 核心模塊
- 為其他模塊提供基礎(chǔ)功能
- 使用 Logback 必須有它
logback-classic- 完整實(shí)現(xiàn)了 SLF4J API 的模塊
- 一般我們?nèi)粘J褂玫木褪沁@個(gè)模塊配合
logback-core
logback-access- 與 Tomcat、Jetty 等 Servlet 容器集成
- 用于記錄 HTTP 訪(fǎng)問(wèn)日志
一般 Java 應(yīng)用最常用的是:logback-core + logback-classic。
四、Logback 快速入門(mén)
1. 引入依賴(lài)
以 Maven 項(xiàng)目為例,只要引入 SLF4J 接口和 Logback 實(shí)現(xiàn)(很多場(chǎng)景 Spring Boot 已經(jīng)幫你引好了):
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>最新穩(wěn)定版</version>
</dependency>logback-classic 會(huì)自動(dòng)依賴(lài) logback-core 和 slf4j-api,通常不用你再額外引。
2. 基本使用方式
在代碼中使用時(shí),永遠(yuǎn)面向 SLF4J 接口編程:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Demo {
// 獲取日志對(duì)象
private static final Logger log = LoggerFactory.getLogger(Demo.class);
public static void main(String[] args) {
log.trace("這是 trace 級(jí)別日志");
log.debug("這是 debug 級(jí)別日志");
log.info("這是 info 級(jí)別日志");
log.warn("這是 warn 級(jí)別日志");
log.error("這是 error 級(jí)別日志");
}
}看起來(lái)和 System.out.println() 很像,但本質(zhì)完全不同:
- 輸出位置可以是:控制臺(tái) / 文件 / 甚至遠(yuǎn)程日志收集系統(tǒng)
- 輸出格式、是否輸出、輸出多少,全由配置文件控制
- 不需要改業(yè)務(wù)代碼就可以調(diào)整日志策略
五、Logback 配置:輸出位置與格式
Logback 的配置通常通過(guò)一個(gè) XML 文件完成,默認(rèn)文件名為:
logback.xml(最常見(jiàn))- 或
logback-spring.xml
1. 配置大體結(jié)構(gòu)
典型結(jié)構(gòu)包含:
<appender>:定義“輸出到哪里、以什么格式輸出”<logger>:定義某個(gè)包/類(lèi)的日志級(jí)別與使用哪些 appender<root>:根日志器,所有日志最終都會(huì)歸到這里
2. 輸出位置(Appender)
常見(jiàn)的輸出目的地:
- 控制臺(tái):
ConsoleAppender - 文件:
FileAppender - 滾動(dòng)文件(按大小/日期拆分日志文件):
RollingFileAppender
舉個(gè)簡(jiǎn)單示例:
<configuration>
<!-- 控制臺(tái)輸出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-5level [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 文件輸出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<!-- 這里可以配置按日期/大小滾動(dòng)等 -->
<encoder>
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 根日志器,設(shè)置級(jí)別和使用的 appender -->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>你在筆記中提到:
“logback可以存在文件中,具體文件可以存在哪里,xml文件里面可以設(shè)置。”
就是通過(guò) <file>、滾動(dòng)策略等配置來(lái)確定日志保存路徑和拆分策略。
六、日志級(jí)別詳解
項(xiàng)目上線(xiàn)后,常見(jiàn)的兩種需求:
- 線(xiàn)上環(huán)境只記錄重要的錯(cuò)誤信息,不要太多無(wú)用日志
- 某個(gè)問(wèn)題需要排查時(shí),暫時(shí)想多打一點(diǎn)日志看看細(xì)節(jié)
這就要靠日志級(jí)別來(lái)精細(xì)控制輸出。
1. 常見(jiàn)日志級(jí)別(從低到高)
一般從低到高是:
TRACE:最詳細(xì)的日志,一般只在調(diào)試極其復(fù)雜問(wèn)題時(shí)使用DEBUG:調(diào)試信息,開(kāi)發(fā)環(huán)境常用INFO:常規(guī)業(yè)務(wù)運(yùn)行信息,如重要步驟、關(guān)鍵結(jié)果WARN:警告信息,可能有問(wèn)題但不影響系統(tǒng)繼續(xù)跑ERROR:錯(cuò)誤信息,功能失敗或系統(tǒng)異常
在配置中給某個(gè) logger 設(shè)定了某個(gè)級(jí)別之后,只會(huì)輸出該級(jí)別及以上的日志。
例如:
<root level="INFO">
...
</root>表示:
TRACE、DEBUG級(jí)別日志不會(huì)輸出INFO、、 會(huì)輸出WARNERROR
2. 通過(guò)級(jí)別控制日志開(kāi)關(guān)
“可以通過(guò)設(shè)置日志的輸出級(jí)別來(lái)控制哪些日志信息輸出或者不輸出。”
好處是顯而易見(jiàn)的:
- 開(kāi)發(fā)環(huán)境:可以把級(jí)別設(shè)為
DEBUG或TRACE,看到更多細(xì)節(jié) - 測(cè)試環(huán)境:設(shè)為
INFO,既能看業(yè)務(wù)流程又不會(huì)太吵 - 生產(chǎn)環(huán)境:通常設(shè)為
WARN或ERROR,只關(guān)注潛在問(wèn)題和錯(cuò)誤
最重要的是,這一切都是通過(guò)配置文件修改完成,無(wú)需改任何業(yè)務(wù)代碼。
總結(jié)
到此這篇關(guān)于Java日志與Logback的文章就介紹到這了,更多相關(guān)Java日志與Logback內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
網(wǎng)關(guān)Gateway過(guò)濾器的使用詳解
Gateway網(wǎng)關(guān)的過(guò)濾器分為兩種,一種是局部過(guò)濾器,一種是全局過(guò)濾器,過(guò)濾器就是過(guò)濾一些請(qǐng)求,在這里,全局過(guò)濾器的作用是處理一切進(jìn)入網(wǎng)關(guān)的請(qǐng)求和微服務(wù)響應(yīng),與GatewayFilter的作用一樣,本文給大家介紹網(wǎng)關(guān)Gateway過(guò)濾器的使用,感興趣的朋友一起看看吧2022-07-07
Java之ThreadPoolExecutor類(lèi)詳解
這篇文章主要介紹了Java之ThreadPoolExecutor類(lèi)詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
Apache Commons fileUpload實(shí)現(xiàn)文件上傳之一
這篇文章主要介紹了Apache Commons fileUpload實(shí)現(xiàn)文件上傳之一的相關(guān)資料,需要的朋友可以參考下2016-03-03
Springboot之如何統(tǒng)計(jì)代碼執(zhí)行耗時(shí)時(shí)間
這篇文章主要介紹了Springboot之如何統(tǒng)計(jì)代碼執(zhí)行耗時(shí)時(shí)間問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
java 非對(duì)稱(chēng)加密算法RSA實(shí)現(xiàn)詳解
這篇文章主要介紹了java 非對(duì)稱(chēng)加密算法RSA實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
JAVA JDK8 List分組的實(shí)現(xiàn)和用法
今天小編就為大家分享一篇關(guān)于JAVA JDK8 List分組的實(shí)現(xiàn)和用法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12

