log4j 压缩日志_Spring Boot 日志各种使用姿势,是时候捋清楚了!
來(lái)自公眾號(hào):江南一點(diǎn)雨
1. Java 日志概覽
1.1 總體概覽
1.2 日志級(jí)別
1.3 綜合對(duì)比
1.4 最佳實(shí)踐
2. Spring Boot 日志實(shí)現(xiàn)
2.1 Spring Boot 日志配置
2.2 Logback 配置
2.3 Log4j 配置
3.小結(jié)
通過(guò)一篇文章來(lái)和大家捋一捋 Java 中的日志問(wèn)題,順便我們把 Spring Boot 中的日志問(wèn)題也說(shuō)清楚。
1. Java 日志概覽
說(shuō)到 Java 日志,很多初學(xué)者可能都比較懵,因?yàn)檫@里涉及到太多東西了:Apache Commons Logging、Slf4j、Log4j、Log4j2、Logback、Java Util Logging?等等,這些框架各自有什么作用?他們之間有什么區(qū)別?
1.1 總體概覽
下面這張圖很好的展示了 Java 中的日志體系:
可以看到,Java 中的日志框架主要分為兩大類(lèi):日志門(mén)面和日志實(shí)現(xiàn)。
日志門(mén)面
日志門(mén)面定義了一組日志的接口規(guī)范,它并不提供底層具體的實(shí)現(xiàn)邏輯。Apache Commons Logging?和?Slf4j?就屬于這一類(lèi)。
日志實(shí)現(xiàn)
日志實(shí)現(xiàn)則是日志具體的實(shí)現(xiàn),包括日志級(jí)別控制、日志打印格式、日志輸出形式(輸出到數(shù)據(jù)庫(kù)、輸出到文件、輸出到控制臺(tái)等)。Log4j、Log4j2、Logback?以及?Java Util Logging?則屬于這一類(lèi)。
將日志門(mén)面和日志實(shí)現(xiàn)分離其實(shí)是一種典型的門(mén)面模式,這種方式可以讓具體業(yè)務(wù)在不同的日志實(shí)現(xiàn)框架之間自由切換,而不需要改動(dòng)任何代碼,開(kāi)發(fā)者只需要掌握日志門(mén)面的 API 即可。
日志門(mén)面是不能單獨(dú)使用的,它必須和一種具體的日志實(shí)現(xiàn)框架相結(jié)合使用。
那么日志框架是否可以單獨(dú)使用呢?
技術(shù)上來(lái)說(shuō)當(dāng)然沒(méi)問(wèn)題,但是我們一般不會(huì)這樣做,因?yàn)檫@樣做可維護(hù)性很差,而且后期擴(kuò)展不易。例如 A 開(kāi)發(fā)了一個(gè)工具包使用 Log4j 打印日志,B 引用了這個(gè)工具包,但是 B 喜歡使用 Logback 打印日志,此時(shí)就會(huì)出現(xiàn)一個(gè)業(yè)務(wù)使用兩個(gè)甚至多個(gè)日志框架,開(kāi)發(fā)者也需要維護(hù)多個(gè)日志的配置文件。因此我們都是用日志門(mén)面打印日志。
1.2 日志級(jí)別
使用日志級(jí)別的好處在于,調(diào)整級(jí)別,就可以屏蔽掉很多調(diào)試相關(guān)的日志輸出。不同的日志實(shí)現(xiàn)定義的日志級(jí)別不太一樣,不過(guò)也都大同小異。
Java Util Logging
Java Util Logging?定義了 7 個(gè)日志級(jí)別,從嚴(yán)重到普通依次是:
- SEVERE
- WARNING
- INFO
- CONFIG
- FINE
- FINER
- FINEST
因?yàn)槟J(rèn)級(jí)別是 INFO,因此 INFO 級(jí)別以下的日志,不會(huì)被打印出來(lái)。
Log4j
Log4j?定義了 8 個(gè)日志級(jí)別(除去 OFF 和 ALL,可以說(shuō)分為 6 個(gè)級(jí)別),從嚴(yán)重到普通依次是:
- OFF:最高等級(jí)的,用于關(guān)閉所有日志記錄。
- FATAL:重大錯(cuò)誤,這種級(jí)別可以直接停止程序了。
- ERROR:打印錯(cuò)誤和異常信息,如果不想輸出太多的日志,可以使用這個(gè)級(jí)別。
- WARN:警告提示。
- INFO:用于生產(chǎn)環(huán)境中輸出程序運(yùn)行的一些重要信息,不能濫用。
- DEBUG:用于開(kāi)發(fā)過(guò)程中打印一些運(yùn)行信息。
- TRACE
- ALL 最低等級(jí)的,用于打開(kāi)所有日志記錄。
Logback
Logback?日志級(jí)別比較簡(jiǎn)單,從嚴(yán)重到普通依次是:
- ERROR
- WARN
- INFO
- DEBUG
- TRACE
1.3 綜合對(duì)比
Java Util Logging?系統(tǒng)在?JVM?啟動(dòng)時(shí)讀取配置文件并完成初始化,一旦應(yīng)用程序開(kāi)始運(yùn)行,就無(wú)法修改配置。另外,這種日志實(shí)現(xiàn)配置也不太方便,只能在?JVM?啟動(dòng)時(shí)傳遞參數(shù),像下面這樣:
-Djava.util.logging.config.file=。由于這些局限性,導(dǎo)致?Java Util Logging?并未廣泛使用。
Log4j?雖然配置繁瑣,但是一旦配置完成,使用起來(lái)就非常方便,只需要將相關(guān)的配置文件放到?classpath?下即可。在很多情況下,Log4j?的配置文件我們可以在不同的項(xiàng)目中反復(fù)使用。
Log4j?可以和?Apache Commons Logging?搭配使用,Apache Commons Logging?會(huì)自動(dòng)搜索并使用?Log4j,如果沒(méi)有找到?Log4j,再使用?Java Util Logging。
比?Log4j?+?Apache Commons Logging?組合更得人心的是?Slf4j?+?Logback?組合。
Logback?是?Slf4j?的原生實(shí)現(xiàn)框架,它也出自?Log4j?作者(Ceki Gülcü)之手,但是相比?Log4j,它擁有更多的優(yōu)點(diǎn)、特性以及更強(qiáng)的性能。
1.4 最佳實(shí)踐
- 如果不想添加任何依賴(lài),使用?
Java Util Logging?或框架容器已經(jīng)提供的日志接口。 - 如果比較在意性能,推薦:
Slf4j?+?Logback。 - 如果項(xiàng)目中已經(jīng)使用了?
Log4j?且沒(méi)有發(fā)現(xiàn)性能問(wèn)題,推薦組合為:Slf4j?+?Log4j2。
2. Spring Boot 日志實(shí)現(xiàn)
Spring Boot 使用?Apache Commons Logging?作為內(nèi)部的日志框架門(mén)面,它只是一個(gè)日志接口,在實(shí)際應(yīng)用中需要為該接口來(lái)指定相應(yīng)的日志實(shí)現(xiàn)。
Spring Boot 默認(rèn)的日志實(shí)現(xiàn)是?Logback。這個(gè)很好查看:隨便啟動(dòng)一個(gè) Spring Boot 項(xiàng)目,從控制臺(tái)找一行日志,例如下面這樣:
考慮到最后的 prod 是一個(gè)可以變化的字符,我們?cè)陧?xiàng)目中全局搜索:The following profiles are active,結(jié)果如下:
在日志輸出的那一行 debug。然后再次啟動(dòng)項(xiàng)目,如下圖:
此時(shí)我們就可以看到真正的日志實(shí)現(xiàn)是?Logback。
其他的諸如?Java Util Logging、Log4j?等框架,Spring Boot 也有很好的支持。
在 Spring Boot 項(xiàng)目中,只要添加了如下 web 依賴(lài),日志依賴(lài)就自動(dòng)添加進(jìn)來(lái)了:
<dependency>
????<groupId>org.springframework.bootgroupId>
????<artifactId>spring-boot-starter-webartifactId>
dependency>
2.1 Spring Boot 日志配置
Spring Boot 的日志系統(tǒng)會(huì)自動(dòng)根據(jù) classpath 下的內(nèi)容選擇合適的日志配置,在這個(gè)過(guò)程中首選 Logback。
如果開(kāi)發(fā)者需要修改日志級(jí)別,只需要在 application.properties 文件中通過(guò)?logging.level 前綴+包名?的形式進(jìn)行配置即可,例如下面這樣:
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
如果你想將日志輸出到文件,可以通過(guò)如下配置指定日志文件名:
logging.file.name=javaboy.log
logging.file.name 可以只指定日志文件名,也可以指定日志文件全路徑,例如下面這樣:
logging.file.name=/Users/sang/Documents/javaboy/javaboy.log
如果你只是想重新定義輸出日志文件的路徑,也可以使用?logging.file.path?屬性,如下:
logging.file.path=/Users/sang/Documents/javaboy
如果想對(duì)輸出到文件中的日志進(jìn)行精細(xì)化管理,還有如下一些屬性可以配置:
- logging.logback.rollingpolicy.file-name-pattern:日志歸檔的文件名,日志文件達(dá)到一定大小之后,自動(dòng)進(jìn)行壓縮歸檔。
- logging.logback.rollingpolicy.clean-history-on-start:是否在應(yīng)用啟動(dòng)時(shí)進(jìn)行歸檔管理。
- logging.logback.rollingpolicy.max-file-size:日志文件大小上限,達(dá)到該上限后,會(huì)自動(dòng)壓縮。
- logging.logback.rollingpolicy.total-size-cap:日志文件被刪除之前,可以容納的最大大小。
- logging.logback.rollingpolicy.max-history:日志文件保存的天數(shù)。
日志文件歸檔這塊,小伙伴們感興趣可以自己試下,可以首先將 max-file-size 屬性調(diào)小,這樣方便看到效果:
logging.logback.rollingpolicy.max-file-size=1MB
然后添加如下接口:
@RestController
public?class?HelloController?{
????private?static?final?Logger?logger?=?getLogger(HelloController.class);
????@GetMapping("/hello")
????public?void?hello()?{
????????for?(int?i?=?0;?i?100000;?i++)?{
????????????logger.info("hello?javaboy");
????????}
????}
}
訪問(wèn)該接口,可以看到最終生成的日志文件被自動(dòng)壓縮了:
application.properties 中還可以配置日志分組。
日志分組能夠把相關(guān)的 logger 放到一個(gè)組統(tǒng)一管理。
例如我們可以定義一個(gè) tomcat 組:
logging.group.tomcat=org.apache.catalina,org.apache.coyote, org.apache.tomcat
然后統(tǒng)一管理 tomcat 組中的所有 logger:
logging.level.tomcat=TRACE
Spring Boot 中還預(yù)定義了兩個(gè)日志分組 web 和 sql,如下:
不過(guò)在 application.properties 中只能實(shí)現(xiàn)對(duì)日志一些非常簡(jiǎn)單的配置,如果想實(shí)現(xiàn)更加細(xì)粒度的日志配置,那就需要使用日志實(shí)現(xiàn)的原生配置,例如?Logback?的?classpath:logback.xml,Log4j?的?classpath:log4j.xml?等。如果這些日志配置文件存在于 classpath 下,那么默認(rèn)情況下,Spring Boot 就會(huì)自動(dòng)加載這些配置文件。
2.2 Logback 配置
2.2.1 基本配置
默認(rèn)的?Logback?配置文件名有兩種:
logback.xml:這種配置文件會(huì)直接被日志框架加載。logback-spring.xml:這種配置文件不會(huì)被日志框架直接加載,而是由 Spring Boot 去解析日志配置,可以使用 Spring Boot 的高級(jí) Profile 功能。
Spring Boot 中為?Logback?提供了四個(gè)默認(rèn)的配置文件,位置在?org/springframework/boot/logging/logback/,分別是:
- defaults.xml:提供了公共的日志配置,日志輸出規(guī)則等。
- console-appender.xml:使用 CONSOLE_LOG_PATTERN 添加一個(gè)ConsoleAppender。
- file-appender.xml:添加一個(gè) RollingFileAppender。
- base.xml:為了兼容舊版 Spring Boot 而提供的。
如果需要自定義?logback.xml?文件,可以在自定義時(shí)使用這些默認(rèn)的配置文件,也可以不使用。一個(gè)典型的?logback.xml?文件如下(resources/logback.xml):
<?xml ?version="1.0"?encoding="UTF-8"?>
<configuration>
????<include?resource="org/springframework/boot/logging/logback/defaults.xml"/>
????<include?resource="org/springframework/boot/logging/logback/console-appender.xml"?/>
????<root?level="INFO">
????????<appender-ref?ref="CONSOLE"?/>
????root>
????<logger?name="org.springframework.web"?level="DEBUG"/>
configuration>
可以通過(guò) include 引入 Spring Boot 已經(jīng)提供的配置文件,也可以自定義。
2.2.2 輸出到文件
如果想禁止控制臺(tái)的日志輸出,轉(zhuǎn)而將日志內(nèi)容輸出到一個(gè)文件,我們可以自定義一個(gè)?logback-spring.xml?文件,并引入前面所說(shuō)的?file-appender.xml?文件。
像下面這樣(resources/logback-spring.xml):
<?xml ?version="1.0"?encoding="UTF-8"?>
<configuration>
????<include?resource="org/springframework/boot/logging/logback/defaults.xml"?/>
????<property?name="LOG_FILE"?value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
????<include?resource="org/springframework/boot/logging/logback/file-appender.xml"?/>
????<root?level="INFO">
????????<appender-ref?ref="FILE"?/>
????root>
configuration>
2.3 Log4j 配置
如果 classpath 下存在?Log4j2?的依賴(lài),Spring Boot 會(huì)自動(dòng)進(jìn)行配置。
默認(rèn)情況下 classpath 下當(dāng)然不存在?Log4j2?的依賴(lài),如果想使用?Log4j2,可以排除已有的?Logback,然后再引入?Log4j2,如下:
<dependency>
????<groupId>org.springframework.bootgroupId>
????<artifactId>spring-boot-starter-webartifactId>
????<exclusions>
????????<exclusion>
????????????<groupId>org.springframework.bootgroupId>
????????????<artifactId>spring-boot-starter-loggingartifactId>
????????exclusion>
????exclusions>
dependency>
<dependency>
????<groupId>org.springframework.bootgroupId>
????<artifactId>spring-boot-starter-log4j2artifactId>
dependency>
Log4j2?的配置就比較容易了,在 reources 目錄下新建 log4j2.xml 文件,內(nèi)容如下:
<?xml ?version="1.0"?encoding="UTF-8"?>
<configuration?status="warn">
????<properties>
????????<Property?name="app_name">loggingProperty>
????????<Property?name="log_path">logs/${app_name}Property>
????properties>
????<appenders>
????????<console?name="Console"?target="SYSTEM_OUT">
????????????<PatternLayout?pattern="[%d][%t][%p][%l]?%m%n"?/>
????????console>
????????<RollingFile?name="RollingFileInfo"?fileName="${log_path}/info.log"filePattern="${log_path}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
????????????<Filters>
????????????????<ThresholdFilter?level="INFO"?/>
????????????????<ThresholdFilter?level="WARN"?onMatch="DENY"onMismatch="NEUTRAL"?/>
????????????Filters>
????????????<PatternLayout?pattern="[%d][%t][%p][%c:%L]?%m%n"?/>
????????????<Policies>
????????????????<TimeBasedTriggeringPolicy?interval="1"?modulate="true"?/>
????????????????<SizeBasedTriggeringPolicy?size="2?MB"?/>
????????????Policies>
????????????<DefaultRolloverStrategy?compressionLevel="0"?max="10"/>
????????RollingFile>
????????<RollingFile?name="RollingFileWarn"?fileName="${log_path}/warn.log"filePattern="${log_path}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
????????????<Filters>
????????????????<ThresholdFilter?level="WARN"?/>
????????????????<ThresholdFilter?level="ERROR"?onMatch="DENY"onMismatch="NEUTRAL"?/>
????????????Filters>
????????????<PatternLayout?pattern="[%d][%t][%p][%c:%L]?%m%n"?/>
????????????<Policies>
????????????????<TimeBasedTriggeringPolicy?interval="1"?modulate="true"?/>
????????????????<SizeBasedTriggeringPolicy?size="2?MB"?/>
????????????Policies>
????????????<DefaultRolloverStrategy?compressionLevel="0"?max="10"/>
????????RollingFile>
????????<RollingFile?name="RollingFileError"?fileName="${log_path}/error.log"filePattern="${log_path}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
????????????<ThresholdFilter?level="ERROR"?/>
????????????<PatternLayout?pattern="[%d][%t][%p][%c:%L]?%m%n"?/>
????????????<Policies>
????????????????<TimeBasedTriggeringPolicy?interval="1"?modulate="true"?/>
????????????????<SizeBasedTriggeringPolicy?size="2?MB"?/>
????????????Policies>
????????????<DefaultRolloverStrategy?compressionLevel="0"?max="10"/>
????????RollingFile>
????appenders>
????<loggers>
????????<root?level="info">
????????????<appender-ref?ref="Console"?/>
????????????<appender-ref?ref="RollingFileInfo"?/>
????????????<appender-ref?ref="RollingFileWarn"?/>
????????????<appender-ref?ref="RollingFileError"?/>
????????root>
????loggers>
configuration>
首先在 properties 節(jié)點(diǎn)中指定了應(yīng)用名稱(chēng)以及日志文件位置。
然后通過(guò)幾個(gè)不同的 RollingFile 對(duì)不同級(jí)別的日志分別處理,不同級(jí)別的日志將輸出到不同的文件,并按照各自的命名方式進(jìn)行壓縮。
這段配置比較程式化,小伙伴們可以保存下來(lái)做成 IntelliJ IDEA 模版以便日常使用。
推薦:程序員求職面試分享程序員找工作經(jīng)驗(yàn)
程序員筆試、面試題
總結(jié)
以上是生活随笔為你收集整理的log4j 压缩日志_Spring Boot 日志各种使用姿势,是时候捋清楚了!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 求一个关于龙的微信网名
- 下一篇: jmeter异步请求测试怎么测试_JMe