開發中,日志記錄是不可或缺的一部分,應用日志的記錄主要用于:記錄操作軌跡數據、監控系統運行情況、系統故障定位問題,日志的重要性不言而喻,想要快速定位問題,日志分析是個重要的手段,Java也提供了多種日志框架來進行有效的日志管理。本文將探討Java常用的日志框架以及使用案例。
一、發展歷史
- 1996: Log4j 1.x 由瑞士程序員CeKi Gülcü 發布
- 2002: JDK 1.4 發布,包含 JUL(java.util.logging,位于java.logging模塊下),是 JDK 官方自帶的日志框架。JUL 性能很差,使用比較少。
- 2002: Apache推出了Jakarta Commons Logging(簡稱JCL)日志接口
- 2010: Slf4j 發布
- 2009: Logback 發布
- 2014: Log4j2 發布
二、日志框架
現有的一些日志框架:
- 日志實現:JUL(java.util.logging)、logback、log4j、log4j2
- 日志門面:JCL(Jakarta Commons Logging)、Slf4j(Simple Logging Facade for Java)
1.Log4j
官方網站: http://logging.apache.org/log4j/1.2
Log4j 是 Apache 的一個開源項目,創始人 Ceki Gulcu。是 Java 領域資格最老,應用最廣的日志工具。Log4j 中有三個主要組件:
- loggers(記錄器) - 負責接收并記錄日志信息。
- appenders(輸出器) - 負責發布日志信息,定義了日志信息的目的地(如控制臺、文件、數據庫等)。
- layouts(布局) -負責定義日志輸出的格式。
這種解耦的設計使得Log4j非常靈活,可以很容易地根據項目的需求進行定制。
1.1 log4j使用:
1).添加maven依賴
<!-- log4j -->
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>
2).resources目錄下創建log4j.properties文件(log4j支持兩種配置文件格式:一種是XML格式的文件,一種是properties屬性文件)
log4j.rootLogger=INFO,M,C,E
log4j.additivity.monitorLogger=false
# INFO級別文件輸出配置
log4j.appender.M=org.apache.log4j.DailyRollingFileAppender
log4j.appender.M.File=/logs/info.log
log4j.appender.M.ImmediateFlush=false
log4j.appender.M.BufferedIO=true
log4j.appender.M.BufferSize=16384
log4j.appender.M.Append=true
log4j.appender.M.Threshold=INFO
log4j.appender.M.DatePattern='.'yyyy-MM-dd
log4j.appender.M.layout=org.apache.log4j.PatternLayout
log4j.appender.M.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n
# ERROR級別文件輸出配置
log4j.appender.E=org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File=/logs/error.log
log4j.appender.E.ImmediateFlush=true
log4j.appender.E.Append=true
log4j.appender.E.Threshold=ERROR
log4j.appender.E.DatePattern='.'yyyy-MM-dd
log4j.appender.E.layout=org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n
# 控制臺輸出配置
log4j.appender.C=org.apache.log4j.ConsoleAppender
log4j.appender.C.Threshold=INFO
log4j.appender.C.layout=org.apache.log4j.PatternLayout
log4j.appender.C.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %l %m %n
appender配置常使用的類如下:
org.apache.log4j.ConsoleAppender(控制臺)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天產生一個日志文件)
org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生一個新的文件)
org.apache.log4j.WriterAppender(將日志信息以流格式發送到任意指定的地方)
layouts常用配置類:
org.apache.log4j.HTMLLayout(以HTML表格形式布局)
org.apache.log4j.PatternLayout(可以靈活地指定布局模式)
org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串)
org.apache.log4j.TTCCLayout(包含日志產生的時間、線程、類別等信息)
layout格式化打印參數:
* log4j 采用類似 C 語言的 printf 函數的打印格式格式化日志信息,具體的占位符及其含義如下:
%m 輸出代碼中指定的日志信息
%p 輸出優先級,及 DEBUG、INFO 等
%n 換行符(Windows平臺的換行符為 "\n",Unix 平臺為 "\n")
%r 輸出自應用啟動到輸出該 log 信息耗費的毫秒數
%c 輸出打印語句所屬的類的全名
%t 輸出產生該日志的線程全名
%d 輸出服務器當前時間,默認為 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日
HH:mm:ss}
%l 輸出日志時間發生的位置,包括類名、線程、及在代碼中的行數。如:
Test.main(Test.java:10)
%F 輸出日志消息產生時所在的文件名稱
%L 輸出代碼中的行號
%% 輸出一個 "%" 字符* 可以在 % 與字符之間加上修飾符來控制最小寬度、最大寬度和文本的對其方式。如:
%5c 輸出category名稱,最小寬度是5,category<5,默認的情況下右對齊
%-5c 輸出category名稱,最小寬度是5,category<5,"-"號指定左對齊,會有空格
%.5c 輸出category名稱,最大寬度是5,category>5,就會將左邊多出的字符截掉,<5不
會有空格
%20.30c category名稱<20補空格,并且右對齊,>30字符,就從左邊交遠銷出的字符截掉
xml文件格式如下:
<?xml version="1.0" encoding="UTF-8"?><Configuration><Appenders><Appender><Filters><LevelRangeFilter minLevel="..." maxLevel="..." onMatch="..." onMismatch="..."/></Filters><PatternLayout pattern="..." charset="..."/><Policies><CronTriggeringPolicy schedule="..."/><SizeBasedTriggeringPolicy size="..."/><TimeBasedTriggeringPolicy /></Policies></Appender><Appender>...</Appender></Appenders><Loggers><Logger><AppenderRef ref="..."></Logger><Root><AppenderRef ref="..."></Root></Loggers></Configuration>
3) log4j日志打印測試
import org.apache.log4j.Logger;
public class Log4jTest {@Testpublic void testLog4j(){// 1.創建日志記錄器對象,使用靜態方法創建Logger logger = Logger.getLogger("com.example.logtest.Log4jTest");// 記錄debug級別的信息logger.debug("This is debug message.");// 記錄info級別的信息logger.info("This is info message.");// 記錄error級別的信息logger.error("This is error message.");}
}
2.JUL
JUL全稱Java util Logging是Java原生的日志框架,使用時不需要另外引用第三方類庫,JUL主要用于小型應用程序中,其設計原理基于幾個核心組件:
- Logger:記錄器,是應用程序訪問日志系統的入口點。應用程序通過獲取Logger對象,并調用其API來發布日志信息。Logger對象通常與特定的類或代碼塊相關聯,以便能夠精確地跟蹤和記錄日志。
- Handler:也被稱為Appenders,每個Logger都會關聯一個或多個Handler。Handler負責處理Logger傳遞過來的日志信息,并將其發送到指定的目的地,如控制臺、文件、網絡上的其他日志服務或操作系統日志等。Handler的具體實現決定了日志記錄的位置和方式。
- Filter:過濾器,用于根據特定條件篩選日志信息。開發者可以根據需要定制哪些信息會被記錄,哪些信息會被忽略,從而實現對日志信息的精細控制。
- Level:日志的輸出級別。每條日志消息都有一個關聯的級別,如DEBUG、INFO、WARN、ERROR等。這些級別粗略地指導了日志消息的重要性和緊迫性。
JUL的配置相對簡單,配置文件通常使用.properties或XML格式,雖然是JDK自帶的日志庫,JUL使用的并不廣泛,原因是因為JUL早期存在性能問題,到JDK1.5上才有了不錯的進步,但現在和Logback/Log4j2相比還是有所不如
2.1 測試案例
import java.util.logging.Level;
import java.util.logging.Logger;
public class JULTest {@Testpublic void testQuick(){// 1.創建日志記錄器對象,使用靜態方法創建Logger logger = Logger.getLogger("com.example.logtest.JULTest");// 2.日志記錄輸出logger.info("hello JUL");// 通用方法輸出logger.log(Level.INFO, "info msg");// 通過占位符輸出logger.log(Level.INFO, "name: {0},age: {1}", new Object[]{"zhangsan",20});}
}
2.2 日志級別
java.util.logging.Level中定義了7個日志的級別
// 關閉日志記錄
public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);
// 錯誤--最高的日志級別
public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);
// 警告
public static final Level WARNING = new Level("WARNING", 900, defaultBundle);
// 消息(默認級別)
public static final Level INFO = new Level("INFO", 800, defaultBundle);
// 配置
public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);
// 詳細信息(少)
public static final Level FINE = new Level("FINE", 500, defaultBundle);
// 詳細信息(中)
public static final Level FINER = new Level("FINER", 400, defaultBundle);
// 詳細信息(多)-- 最低級的日志級別
public static final Level FINEST = new Level("FINEST", 300, defaultBundle);
// 啟用所有消息日志
public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);
2.3 日志配置
如果我們沒有添加配置,JUL默認的配置文件:JAVA_HOME/jre/lib/logging.properties
############################################################
# Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property.
# For example java -Djava.util.logging.config.file=myfile
########################################################################################################################
# Global properties
############################################################# "handlers" specifies a comma separated list of log Handler
# classes. These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
## RootLogger使用的處理器
handlers= java.util.logging.ConsoleHandler# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers. For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
# RootLogger日志等級
.level= INFO############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
## 文件處理器
# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
## 控制臺處理器
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter# Example to customize the SimpleFormatter output format
# to print one-line log message like this:
# <level>: <log message> [<date/time>]
#
# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE
自定義日志級別及配置
@Test
public void test2() throws IOException {
// 1.獲取日志記錄器對象
Logger logger = Logger.getLogger("com.example.logtest.JULTest");// 關閉系統默認配置
logger.setUseParentHandlers(false);
// 一、自定義配置日志級別// 創建ConsoleHandler 控制臺輸出
ConsoleHandler consoleHandler = new ConsoleHandler();
// 創建簡單格式轉換對象
SimpleFormatter simpleFormatter = new SimpleFormatter();
// 進行關聯
consoleHandler.setFormatter(simpleFormatter);
logger.addHandler(consoleHandler);
// 配置日志具體級別
logger.setLevel(Level.ALL);
consoleHandler.setLevel(Level.ALL);// 二、輸出到日志文件
FileHandler fileHandler = new FileHandler("d:/jul.log");
// 進行關聯
fileHandler.setFormatter(simpleFormatter);
logger.addHandler(fileHandler);// 日志記錄輸出
logger.severe("severe");
logger.warning("warning");
logger.info("info"); // 默認日志輸出級別
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
}
2.4 日志對象Logger的父子關系
JUL中Logger對象存在父子關系,也就是父親Logger的設置,同時能夠作用于兒子,這種父子關系是通過樹狀結構包路徑進行存儲,如下:logger1的日志設置,對logger2也能生效。
@Testpublic void test3() throws Exception {// 日志記錄器對象父子關系Logger logger1 = Logger.getLogger("com.fang");Logger logger2 = Logger.getLogger("com.fang.log");System.out.println(logger2.getParent() == logger1);// 所有日志記錄器對象的頂級父元素 class為java.util.logging.LogManagerSystem.out.println("logger2 parent:" + logger2.getParent() + ",name:" + logger2.getParent().getName());// 一、自定義日志級別// a.關閉系統默認配置logger1.setUseParentHandlers(false);// b.創建handler對象ConsoleHandler consoleHandler = new ConsoleHandler();// c.創建formatter對象SimpleFormatter simpleFormatter = new SimpleFormatter();// d.進行關聯consoleHandler.setFormatter(simpleFormatter);logger1.addHandler(consoleHandler);// e.設置日志級別logger1.setLevel(Level.ALL);consoleHandler.setLevel(Level.ALL);// 測試日志記錄器對象父子關系logger2.severe("severe");logger2.warning("warning");logger2.info("info");logger2.config("config");logger2.fine("fine");logger2.finer("finer");logger2.finest("finest");}
測試結果:
true
logger2 parent:java.util.logging.Logger@6ec8211c,name:com.fang
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
嚴重: severe
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
警告: warning
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
信息: info
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
配置: config
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
詳細: fine
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
較詳細: finer
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
非常詳細: finest
3.Slf4j
Slf4J(Simple Logging Facade for Java)是一個用于Java的簡單日志門面(Facade)主要是為了給Java日志訪問提供一套標準、規范的API框架,它本身并不提供具體的日志實現,具體的實現可以交由其他日志框架,例如 log4j 、 logback、java.util.logging等。當然 Slf4J 自己也提供了功能較為簡單的實現 slf4j-simple,但是一般很少用到。SLF4J 的作者就是 log4j 的作者 Ceki Gülcü,他宣稱 SLF4J 比 log4j 更有效率,而且比 Apache Commons Logging (JCL) 簡單、穩定。
官網:https://www.slf4j.org
3.1 Slf4j的官網架構圖
上面架構圖中可以看到,第一層是應用層,第二層即為slf4j提供的抽象接口:slf4j-api.jar,第三層的話藍色的(2列5列6列)是日志的實現,而且是直接實現slf4j-api.jar相關接口,湖藍色(3列4列)是適配層,與上面的slf4j-api接口以及第4層具體日志框架(log4j、jul)的適配。從上圖也可以看到logback是直接實現了slf4j的接口的,而log4j在被slf4j調用的時候需要一個適配層。
reload4j:reload4j是Apache log4j版本1.x的一個分支,由于log4j存在一些安全漏洞,Apache社區和其他開發者開始尋求解決方案,reload4j就是其中之一。通過使用slf4j-reload4j,開發者可以在不修改太多代碼的情況下,將他們的應用程序從log4j 1.x遷移到reload4j,從而提高應用程序的安全性和穩定性。
slf4j的主要搭配如下:
- Slf4j+logback slf4j-api.jar+logback-classic.jar+logback-core.jar
- Slf4j+log4j slf4j-api.jar+slf4j-log4j12.jar+log4j.jar
- Slf4j+jul slf4j-api.jar+slf4j-jdk14.jar
- Slf4j無日志實現 slf4j-api.jar+slf4j-nop.jar
官網第二張圖(橋接策略)
可以看到,上面含義是如果我們已經使用了其他日志框架的api,想轉到另一種日志框架api,該如何使用橋接的jar包,如從logback到log4j,JUL到log4j等,本質是通過將一種框架日志交給slf4j,slf4j再通過橋接包到轉給另一種框架日志輸出,總的來說為以下情況:
- 在使用JCL,則可以通過:jcl-over-slf4j.jar
- 在使用log4j,則可以通過:log4j-over-slf4j.jar
- 在使用JUL,則可通過jul-to-slf4j.jar
注意: 雖然使用 log4j-over-slf4j 可以實現 Log4j 橋接到 SLF4J,也可以使用 slf4j-log4j12 實現 SLF4J 適配到 Log4j,但是它不能同時使用它們,否則就會產生死循環。jcl 和 jul 也是同樣的道理,jcl-over-slf4j.jar和slf4j-jcl.jar不能同時出現,jul-over-slf4j.jar和slf4j-log4j12.jar不能同時出現。
4.Logback
官網:https://logback.qos.ch/
Logback是由Ceki Gülcü(同時也是SLF4J的作者)創建的新一代日志框架,旨在解決Log4J的部分性能瓶頸和設計局限。Logback不僅實現了SLF4J API,還具有高度優化的性能、豐富的配置選項和強大的擴展能力。SpringBoot底層也是使用slf4j+logback的方式進行日志記錄。
Logback主要分為三個模塊:
- logback-core :其它兩個模塊的基礎模塊
- logback-classic :它是log4j的一個改良版本,同時它完整實現了slf4j API
- logback-access :訪問模塊與Servlet容器集成提供通過Http來訪問日志的功能
4.1 Logback 使用示例
1)添加依賴
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.25</version>
</dependency>
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version>
</dependency>
實際開發中我們可以直接引入spring-boot-starter-web
依賴,因為spring-boot-starter-web
包含了spring-boot-starter 而spring-boot-starter包含了spring-boot-starter-logging
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>
2)配置文件
logback會依次讀取以下類型配置文件:
- logback.groovy
- logback-test.xml
- logback.xml
如果均不存在會采用默認配置
logback-spring.yml
<?xml version="1.0" encoding="utf-8"?>
<!--配置文件說明:
共有一個父標簽、兩種屬性、三個節點:
1.一個父標簽:configuration
2. 兩種屬性:contextName和property
3. 三個節點:appender、root、logger主要就是appender追加到哪里:控制臺/文件,然后采用哪種pattern(在property定義了pattern格式)
然后就是logger和root配置,指定日志輸出級別,以及引用哪種appender
-->
<configuration><!--根節點<configuration>包含的屬性:scan:當此屬性設置為true時,配置文件如果發生改變,將會被重新加載,默認值為true。scanPeriod:設置監測配置文件是否有修改的時間間隔,如果沒有給出時間單位,默認單位是毫秒。當scan為true時,此屬性生效。默認的時間間隔為1分鐘。debug:當此屬性設置為true時,將打印出logback內部日志信息,實時查看logback運行狀態。默認值為false。--><contextName>logback-spring-demo-dev</contextName><property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n"/><property name="pattern-color"value="%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %green(%logger{50}) - %highlight(%msg) %n"/><!--文件路徑輸出說明,會自動生成文件夾及log文件,但是由于我這個是多模塊,默認生成在父目錄下的logs文件夾下面,所以要在子模塊下生成要再加一個路徑--><property name="LOG_HOME" value="./springboot_log/logs"/><!-- 控制臺輸出 --><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><!--ThresholdFilter為系統定義的攔截器,例如我們用ThresholdFilter來過濾掉ERROR級別以下的日志不輸出到文件中。如果不用記得注釋掉,不然你控制臺會發現沒日志~--><!--<filter class="ch.qos.logback.classic.filter.ThresholdFilter">--><!--<level>ERROR</level>--><!--</filter>--><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!-- 控制臺輸出-帶顏色 --><appender name="CONSOLE-WITH-COLOR" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern-color}</pattern></encoder></appender><!-- 文件輸出 --><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${LOG_HOME}/%d.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>10MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><maxHistory>30</maxHistory></rollingPolicy><encoder><pattern>${pattern}</pattern></encoder></appender><!--相當于全局的配置--><root level="INFO"><appender-ref ref="CONSOLE-WITH-COLOR"/><appender-ref ref="FILE"/></root><!--1. root和logger是父子的關系。Logger的appender根據參數additivity決定是否要疊加root的appender,logger的級別是其自身定義的級別,和root的級別沒什么關系。2. logger對單個包或類添加配置,相當于局部配置,root相當于全局配置如果logger里面配置了additivity="false",就會覆蓋root的,只打印一遍;但是additivity="true",就會向上層再次傳遞,不會覆蓋,而是打印兩遍!--><!--相當于局部配置:配置特定類/包使用不同的日志輸出器appender:TestControoler2的會輸出兩遍,additivity="true"--><logger name="com.apple.controller.TestController2" level="INFO" additivity="true"><appender-ref ref="CONSOLE"/></logger></configuration>
3)測試
@Slf4j
@RestController
public class TestController {@RequestMapping("/index")public String index(){log.info("==========hello logback=============");return "hello logback";}
}
5.JCL(Jakarta Commons Logging)
官網:https://commons.apache.org/proper/commons-logging/
JCL是Apache基金會所屬的項目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名為Commons Logging, 它本身并不提供日志的具體實現,(當然,commons-logging內部有一個SimpleLog但是功能非常常弱 ,所以一般不會單獨使用它),而是在運行時綁定具體的日志組件來工作(如Log4j、JUL )。
JCL兩個基本抽象類:
- Log:日志記錄器
- LogFactory:日志工廠(負責創建Log實例)
5.1 JCL例子
maven依賴:
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId><version>1.2</version>
</dependency>
測試
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;public class JCLTest {@Testpublic void testJCL(){// 創建日志對象Log log = LogFactory.getLog(JCLTest.class);// 記錄debug級別的信息log.debug("This is debug message.");// 記錄info級別的信息log.info("This is info message.");// 記錄error級別的信息log.error("This is error message.");}
}
6.log4j2
官網:https://logging.apache.org/log4j/2.x/
Apache Log4J曾一度是Java世界中最流行的日志框架之一,以其靈活性和模塊化設計著稱。然而,隨著時間推移,原版Log4J暴露出了一些性能和功能上的短板。于是,Apache基金會推出了Log4J2,這是一個經過徹底重構并優化的新版本,引入了許多新特性,主要有:
- 異常處理,在 logback中,Appender中的異常不會被應用感知到,但是在log4j2中,提供了一些異 常處理機制。
- 性能提升, log4j2相較于log4j 和logback都具有很明顯的性能提升,后面會有官方測試的數據。
- 自動重載配置,參考了 logback的設計,當然會提供自動刷新參數配置,最實用的就是我們在生產 上可以動態的修改日志的級別而不需要重啟應用。
- 無垃圾機制, log4j2在大部分情況下,都可以使用其設計的一套無垃圾機制,避免頻繁的日志收集導致的jvm gc
6.1案例實現:
1)引入依賴:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId><version>2.6.13</version>
</dependency>
2) log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="5"><properties><property name="LOG_HOME">D:/logs</property></properties><Appenders><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n" /></Console><File name="file" fileName="${LOG_HOME}/myfile.log"><PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %m%n" /></File><RandomAccessFile name="accessFile" fileName="${LOG_HOME}/myAcclog.log"><PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %m%n" /></RandomAccessFile><RollingFile name="rollingFile" fileName="${LOG_HOME}/myrollog.log"filePattern="D:/logs/$${date:yyyy-MM-dd}/myrollog-%d{yyyyMM-dd-HH-mm}-%i.log"><ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" /><PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %msg%n" /><Policies><OnStartupTriggeringPolicy /><SizeBasedTriggeringPolicy size="10 MB" /><TimeBasedTriggeringPolicy /></Policies><DefaultRolloverStrategy max="30" /></RollingFile></Appenders><Loggers><Root level="trace"><AppenderRef ref="Console" /></Root></Loggers>
</Configuration>
3)JAVA代碼測試
import org.slf4j.LoggerFactory;public class LogTest {static org.slf4j.Logger logger = LoggerFactory.getLogger(LogTest.class);public static void main(String[] args) {logger.trace("trace level");logger.debug("debug level");logger.info("info level");logger.warn("warn level");logger.error("error level");}
}
參考:
- http://t.csdnimg.cn/lW60J
- https://time.geekbang.org/column/article/220307
- https://www.cnblogs.com/cxyyh/p/10633581.html