Spring Boot(十)Logback和Log4j2集成與日志發(fā)展史

一、簡(jiǎn)介

Java知名的日志有很多,比如:JUL、Log4j、JCL、SLF4J、Logback、Log4j2,那么這些日志框架之間有著怎樣的關(guān)系?誕生的原因又是解決什么問題?下面一起來看。

1.1 JUL

Java有自己的日志框架JUL(Java Util Logging)在java.util.logging下,因?yàn)閷?duì)開發(fā)者不友好,使用成本太高和日志級(jí)別分類不清晰的問題,所有很少有開發(fā)者用。

1.2 Log4j

因?yàn)镴UL的缺陷問題,這就給了Log4j機(jī)會(huì),所有Log4j一經(jīng)推出就迅速風(fēng)靡全球。

1.3 JCL

JCL是Jakarta Commons-Logging的縮寫,Jakarta在這里指的是一個(gè)組織,而不是印度的首都雅加達(dá),Jakarta,一個(gè)早期的Apache開源項(xiàng)目,用于管理各個(gè)Java子項(xiàng)目,諸如Tomcat, Ant, Maven, Struts, JMeter, Velocity, JMeter, Commons等。2011年12月,在所有子項(xiàng)目都被遷移為獨(dú)立項(xiàng)目后,Jakarta名稱就不再使用了。

JCL誕生的初衷是因?yàn)镴ava自身的一些包用了JUL,而Log4j用戶使用的有很多,那么JCL就是提供一套API來實(shí)現(xiàn)不同Logger之間的切換。

1.4 SLF4J

SLF4J(Simple Logging Facade For Java)簡(jiǎn)單日志門面,和JCL功能類似,但JCL有一個(gè)致命的缺點(diǎn)就是算法復(fù)雜,出現(xiàn)問題難以排除,而SLF4J的誕生就是為了解決JCL的缺點(diǎn)。

值得一提的是SLF4J的作者就是Log4j的作者。

1.5 Logback

Logback是Log4j的作者的另一個(gè)開源日志組件,與Log4j相比,Logback重新了內(nèi)核,使它的性能提升了很多,大約是Log4j的10倍,同時(shí)占用更小的內(nèi)存,并且完整的實(shí)現(xiàn)了SLF4J API是你可以很方便的切換日志框架。

1.6 Log4j2

Log4j2有著和Logback相同的功能,但又有自己?jiǎn)斡玫墓δ?,比如:插件式結(jié)構(gòu)、配置文件優(yōu)化、異步日志等。

Log4j2是Log4j的升級(jí),它比其前身Log4j 1.x提供了重大改進(jìn),并提供了Logback中可用的許多改進(jìn),同時(shí)修復(fù)了Logback架構(gòu)中的一些固有問題。

從GitHub的更新日志來看,Logback已經(jīng)有半年沒有更新了,而作為知名組織的Apache下的Log4j2的更新卻是非?;钴S的,Log4j 1.x 于2015年8月停止維護(hù)更新了。

GitHub地址

Logback:https://github.com/qos-ch/logback

log4j2:https://github.com/apache/logging-log4j2

本文分別來看Logback和Log4j2在Spring Boot中的實(shí)現(xiàn)。

二、Logback使用

開發(fā)環(huán)境

  • JDK 8
  • Spring Boot 2.0.4 RELEASE
  • Maven
  • Windows 10
  • IDEA 2018.2

2.1 Logback的使用

Spring Boot默認(rèn)集成了Logback,可以開箱即用,非常方便。因?yàn)閟pring-boot-starter-logging是Logback的日志實(shí)現(xiàn),而Spring Boot啟動(dòng)項(xiàng)spring-boot-starter又依賴了spring-boot-starter-logging,所以Spring Boot就默認(rèn)集成了Logback,包依賴如下圖:

日志是默認(rèn)控制臺(tái)輸出的,我們程序啟動(dòng)的時(shí)候就使用Logback,如下圖所示:

日志組成解讀:

  • 日期和時(shí)間:毫秒精度,易于排序

  • 日志級(jí)別:trace、debug、info、warn、error(日志級(jí)別依次從低到高)

  • 進(jìn)程ID

  • ---分隔符

  • 線程名稱:括在方括號(hào)中(可以截?cái)嗫刂婆_(tái)輸出)

  • 記錄器名稱:這通常是源類名(通??s寫)

  • 日志具體信息

2.2 輸入文件

如果需要輸出日志到文件,只需要在application.properties配置文件設(shè)置:logging.file或logging.path,示例如下:

logging.level.root=info
logging.file=D:\\log\\my.log

可以通過設(shè)置日志的級(jí)別,忽略更低級(jí)別的日志輸出。

注意: logging.file和logging.path設(shè)置一個(gè)屬性即可,如果兩個(gè)都設(shè)置,則以logging.file為主,logging.path無效。

日志文件容量設(shè)置:使用“l(fā)ogging.file.max-history”屬性為日志最大容量設(shè)置,默認(rèn)10M超過則分割為多個(gè)文件。

2.3 自定義日志配置

日志服務(wù)在ApplicationContext創(chuàng)建前就初始化了,所以通過設(shè)置屬性和傳統(tǒng)的配置XML文件,可以對(duì)日志進(jìn)行管理和控制。

只需要在src/main/resources下,創(chuàng)建好約定名稱的XML文件,即可完成對(duì)日志系統(tǒng)的設(shè)置,不同的日志系統(tǒng)有不同的約定名稱,如下列表:

日志 名稱
logback logback-spring.xml, logback-spring.groovy, logback.xml, 或者 logback.groovy
log4j2 log4j2-spring.xml 或者 log4j2.xml

Spring Boot官方建議使用“-spring”的命名規(guī)則,進(jìn)行日志配置,如:logback-spring.xml而不是logback.xml。

當(dāng)然你也可以自定義日志名稱,只需要在application.properties配置即可,代碼如下:

logging.config=classpath:logging-config.xml

來看一個(gè)logback-spring.xml示例文件:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!-- 日志根目錄-->
    <springProperty scope="context" name="LOG_HOME" source="logging.path" defaultValue="/data/logs/spring-boot-logback"/>

    <!-- 日志級(jí)別 -->
    <springProperty scope="context" name="LOG_ROOT_LEVEL" source="logging.level.root" defaultValue="DEBUG"/>

    <!--  標(biāo)識(shí)這個(gè)"STDOUT" 將會(huì)添加到這個(gè)logger -->
    <springProperty scope="context" name="STDOUT" source="log.stdout" defaultValue="STDOUT"/>

    <!-- 日志文件名稱-->
    <property name="LOG_PREFIX" value="spring-boot-logback" />

    <!-- 日志文件編碼-->
    <property name="LOG_CHARSET" value="UTF-8" />

    <!-- 日志文件路徑+日期-->
    <property name="LOG_DIR" value="${LOG_HOME}/%d{yyyyMMdd}" />

    <!--對(duì)日志進(jìn)行格式化-->
    <property name="LOG_MSG" value="- | [%X{requestUUID}] | [%d{yyyyMMdd HH:mm:ss.SSS}] | [%level] | [${HOSTNAME}] | [%thread] | [%logger{36}] | --> %msg|%n "/>

    <!--文件大小,默認(rèn)10MB-->
    <property name="MAX_FILE_SIZE" value="50MB" />

    <!-- 配置日志的滾動(dòng)時(shí)間 ,表示只保留最近 10 天的日志-->
    <property name="MAX_HISTORY" value="10"/>

    <!--輸出到控制臺(tái)-->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 輸出的日志內(nèi)容格式化-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>${LOG_MSG}</pattern>
        </layout>
    </appender>

    <!--輸出到文件-->
    <appender name="0" class="ch.qos.logback.core.rolling.RollingFileAppender">
    </appender>

    <!-- 定義 ALL 日志的輸出方式:-->
    <appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--日志文件路徑,日志文件名稱-->
        <File>${LOG_HOME}/all_${LOG_PREFIX}.log</File>

        <!-- 設(shè)置滾動(dòng)策略,當(dāng)天的日志大小超過 ${MAX_FILE_SIZE} 文件大小時(shí)候,新的內(nèi)容寫入新的文件, 默認(rèn)10MB -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

            <!--日志文件路徑,新的 ALL 日志文件名稱,“ i ” 是個(gè)變量 -->
            <FileNamePattern>${LOG_DIR}/all_${LOG_PREFIX}%i.log</FileNamePattern>

            <!-- 配置日志的滾動(dòng)時(shí)間 ,表示只保留最近 10 天的日志-->
            <MaxHistory>${MAX_HISTORY}</MaxHistory>

            <!--當(dāng)天的日志大小超過 ${MAX_FILE_SIZE} 文件大小時(shí)候,新的內(nèi)容寫入新的文件, 默認(rèn)10MB-->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>

        </rollingPolicy>

        <!-- 輸出的日志內(nèi)容格式化-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>${LOG_MSG}</pattern>
        </layout>
    </appender>

    <!-- 定義 ERROR 日志的輸出方式:-->
    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 下面為配置只輸出error級(jí)別的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <OnMismatch>DENY</OnMismatch>
            <OnMatch>ACCEPT</OnMatch>
        </filter>
        <!--日志文件路徑,日志文件名稱-->
        <File>${LOG_HOME}/err_${LOG_PREFIX}.log</File>

        <!-- 設(shè)置滾動(dòng)策略,當(dāng)天的日志大小超過 ${MAX_FILE_SIZE} 文件大小時(shí)候,新的內(nèi)容寫入新的文件, 默認(rèn)10MB -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

            <!--日志文件路徑,新的 ERR 日志文件名稱,“ i ” 是個(gè)變量 -->
            <FileNamePattern>${LOG_DIR}/err_${LOG_PREFIX}%i.log</FileNamePattern>

            <!-- 配置日志的滾動(dòng)時(shí)間 ,表示只保留最近 10 天的日志-->
            <MaxHistory>${MAX_HISTORY}</MaxHistory>

            <!--當(dāng)天的日志大小超過 ${MAX_FILE_SIZE} 文件大小時(shí)候,新的內(nèi)容寫入新的文件, 默認(rèn)10MB-->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>

        <!-- 輸出的日志內(nèi)容格式化-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>${LOG_MSG}</Pattern>
        </layout>
    </appender>

    <!-- additivity 設(shè)為false,則logger內(nèi)容不附加至root ,配置以配置包下的所有類的日志的打印,級(jí)別是 ERROR-->

    <logger name="org.springframework"     level="ERROR" />
    <logger name="org.apache.commons"      level="ERROR" />
    <logger name="org.apache.zookeeper"    level="ERROR"  />
    <logger name="com.alibaba.dubbo.monitor" level="ERROR"/>
    <logger name="com.alibaba.dubbo.remoting" level="ERROR" />

    <!-- ${LOG_ROOT_LEVEL} 日志級(jí)別 -->
    <root level="${LOG_ROOT_LEVEL}">

        <!-- 標(biāo)識(shí)這個(gè)"${STDOUT}"將會(huì)添加到這個(gè)logger -->
        <appender-ref ref="${STDOUT}"/>

        <!-- FILE_ALL 日志輸出添加到 logger -->
        <appender-ref ref="FILE_ALL"/>

        <!-- FILE_ERROR 日志輸出添加到 logger -->
        <appender-ref ref="FILE_ERROR"/>
    </root>

</configuration>

2.4 代碼中使用日志

在代碼中使用日志,只需要使用如下代碼:

private Logger logger = LoggerFactory.getLogger(this.getClass());
//...
logger.debug("this is debug");
logger.info("this is info");

三、Log4j2集成

3.1 配置依賴組件

Spring Boot添加Log4j2依賴的同時(shí),需要排除Logback依賴,配置pom.xml代碼如下:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions><!-- 去掉logback配置 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <dependency> <!-- 引入log4j2依賴 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
</dependencies>

3.2 自定義日志配置

添加log4j2-spring.xml文件在src/main/resources文件下,配置文件代碼如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <Appenders>
        <Console name="CONSOLE" target="SYSTEM_OUT">
            <PatternLayout charset="UTF-8" pattern="[%-5p] %d %c - %m%n" />
        </Console>

        <File name="File" fileName="D:\\mylog.log">
            <PatternLayout pattern="%m%n" />
        </File>
    </Appenders>

    <Loggers>
        <root level="info">
            <AppenderRef ref="CONSOLE" />
            <AppenderRef ref="File" />
        </root>
    </Loggers>
</configuration>

輸入日志到控制臺(tái)和D盤mylog.log文件中。

到此為止,已經(jīng)完成了log4j2的集成,運(yùn)行項(xiàng)目,查看日志。

示例源碼:https://github.com/vipstone/springboot-example/tree/master/springboot-logging

參考資料

JAVA日志的前世今生:https://www.cnblogs.com/xiexj/p/9417128.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容