自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

全網(wǎng)最全Log配置教程及框架性能比較,看這篇就夠了!

開(kāi)發(fā) 開(kāi)發(fā)工具
Log4j 有三個(gè)主要的組件:Loggers(記錄器),Appenders?(輸出源)和Layouts(布局)。這里可簡(jiǎn)單理解為日志類(lèi)別、日志要輸出的地方和日志以何種形式輸出。

一、背景介紹

不管是使用何種編程語(yǔ)言,何種框架,日志輸出幾乎無(wú)處不再,也是任何商業(yè)軟件中必不可少的一部分。

總結(jié)起來(lái),日志的用途大致可以歸納成以下三種:

  • 問(wèn)題追蹤:通過(guò)日志不僅僅包括我們程序的一些bug,也可以在安裝配置時(shí),通過(guò)日志可以發(fā)現(xiàn)問(wèn)題。
  • 狀態(tài)監(jiān)控:通過(guò)實(shí)時(shí)分析日志,可以監(jiān)控系統(tǒng)的運(yùn)行狀態(tài),做到早發(fā)現(xiàn)問(wèn)題、早處理問(wèn)題。
  • 安全審計(jì):審計(jì)主要體現(xiàn)在安全上,通過(guò)對(duì)日志進(jìn)行分析,可以發(fā)現(xiàn)是否存在非授權(quán)的操作。

以 Java 編程語(yǔ)言為例,打印日志的方式有很多,例如通過(guò)System.out.print()方法將關(guān)鍵信息輸出到控制臺(tái),也可以通過(guò) JDK 自帶的日志Logger類(lèi)輸出,雖然 JDK 從1.4開(kāi)始支持日志輸出,但是功能單一,無(wú)法更好的滿(mǎn)足商業(yè)要求,于是誕生了很多第三方日志庫(kù),像我們所熟悉的主流框架log4j、log4j2、logback等,提供的 API 功能都遠(yuǎn)勝 JDK 提供的Logger。

二、Log4j

2.1、介紹

Log4j 是一種非常流行的日志框架,由Ceki Gülcü首創(chuàng),之后將其開(kāi)源貢獻(xiàn)給 Apache 軟件基金會(huì)。

Log4j 有三個(gè)主要的組件:Loggers(記錄器),Appenders (輸出源)和Layouts(布局)。這里可簡(jiǎn)單理解為日志類(lèi)別、日志要輸出的地方和日志以何種形式輸出。

綜合使用這三個(gè)組件可以輕松地記錄信息的類(lèi)型和級(jí)別,并可以在運(yùn)行時(shí)控制日志輸出的樣式和位置。

Log4j 的架構(gòu)大致如下:

圖片圖片

當(dāng)我們使用 Log4j 輸出一條日志時(shí),Log4j 自動(dòng)通過(guò)不同的Appender(輸出源)把同一條日志輸出到不同的目的地。例如:

  • console:輸出到屏幕;
  • file:輸出到文件;
  • socket:通過(guò)網(wǎng)絡(luò)輸出到遠(yuǎn)程計(jì)算機(jī);
  • jdbc:輸出到數(shù)據(jù)庫(kù)

在輸出日志的過(guò)程中,通過(guò)Filter來(lái)過(guò)濾哪些log需要被輸出,哪些log不需要被輸出。

在Loggers(記錄器)組件中,級(jí)別分五種:DEBUG、INFO、WARN、ERROR和FATAL。

這五個(gè)級(jí)別是有順序的,DEBUG < INFO < WARN < ERROR < FATAL,分別用來(lái)指定這條日志信息的重要程度,明白這一點(diǎn)很重要,Log4j有一個(gè)規(guī)則:只輸出級(jí)別不低于設(shè)定級(jí)別的日志信息。

假設(shè)Loggers級(jí)別設(shè)定為INFO,則INFO、WARN、ERROR和FATAL級(jí)別的日志信息都會(huì)輸出,而級(jí)別比INFO低的DEBUG則不會(huì)輸出。

最后,通過(guò)Layout來(lái)格式化日志信息,例如,自動(dòng)添加日期、時(shí)間、方法名稱(chēng)等信息。

具體輸出樣式配置,可以參考如下內(nèi)容Log4j2 - Layouts布局介紹

2.2、項(xiàng)目應(yīng)用

以 Java 項(xiàng)目為例,在 Maven 的pom.xml中添加如下依賴(lài)!

2.2.1、添加 maven 依賴(lài)

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.6.6</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.6.6</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
</dependencies>

2.2.2、創(chuàng)建log4j配置

在實(shí)際應(yīng)用中,要使Log4j在系統(tǒng)中運(yùn)行須事先設(shè)定配置文件。

配置文件實(shí)際上也就是對(duì)Logger、Appender及Layout進(jìn)行相應(yīng)設(shè)定。

Log4j支持兩種配置文件格式,一種是XML格式的文件,一種是properties屬性文件,二選一。

創(chuàng)建一個(gè)log4j.xml或者log4j.properties,將其放入項(xiàng)目根目錄下。

  • XML格式
<?xml versinotallow="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <!-- 控制臺(tái)輸出配置 -->
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <!-- 目標(biāo)為控制臺(tái) -->
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <!-- 輸出格式 -->
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %l %m%n" />
        </layout>
    </appender>
    <!-- 文件輸出配置 -->
    <appender name="log_file" class="org.apache.log4j.DailyRollingFileAppender">
        <!-- 目標(biāo)為文件 -->
        <param name="File" value="/logs/log/file.log" />
        <!-- 向文件追加輸出 -->
        <param name="Append" value="true" />
        <!-- 每個(gè)小時(shí)生成一個(gè)log -->
        <param name="DatePattern" value="'.'yyyy-MM-dd-HH" />
        <layout class="org.apache.log4j.PatternLayout">
            <!-- 輸出格式 -->
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %l %m%n" />
        </layout>
    </appender>
    <!-- Application Loggers -->
    <logger name="org.example">
        <level value="info" />
    </logger>
    <!-- 根目錄 -->
    <!-- Root Logger -->
    <root>
        <priority value="info" />
        <appender-ref ref="console" />
        <appender-ref ref="log_file" />
    </root>
</log4j:configuration>
  • XML格式
log4j.rootLogger=INFO,M,C,E
log4j.additivity.mnotallow=false

# INFO級(jí)別文件輸出配置
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.Cnotallow=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n

# ERROR級(jí)別文件輸出配置
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.Cnotallow=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n

# 控制臺(tái)輸出配置
log4j.appender.C=org.apache.log4j.ConsoleAppender
log4j.appender.C.Threshold=INFO
log4j.appender.C.layout=org.apache.log4j.PatternLayout
log4j.appender.C.layout.Cnotallow=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %l %m %n

2.2.3、log4j使用

在需要打印日志的類(lèi)中,引入Logger類(lèi),在需要的地方打印即可!

package org.example.log4j.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogPrintUtil {
    /**log靜態(tài)常量*/
    private static final Logger logger = LoggerFactory.getLogger(LogPrintUtil.class);
    public static void main(String[] args){
            logger.info("info信息");
            logger.warn("warn信息");
            logger.error("error信息");
    }
}

當(dāng)然你還可以這樣寫(xiě)

if(logger.isInfoEnabled()) {
    logger.info("info信息");
}
if(logger.isWarnEnabled()) {
    logger.warn("warn信息");
}

2.2.4、isInfoEnabled()有何作用呢?

簡(jiǎn)單來(lái)說(shuō),在某些場(chǎng)景下,用isInfoEnabled()方法判斷下是能提升性能的!

例如我們打印這段內(nèi)容logger.info("User:" + userId + appId),程序在打印這行代碼時(shí),先對(duì)內(nèi)容("User:" + userId + appId)進(jìn)行字符串拼接,然后再輸出。

如果當(dāng)前配置文件中日志輸出級(jí)別是info,是直接輸出的,當(dāng)日志輸出級(jí)別是error時(shí),logger.info()的內(nèi)容時(shí)不輸出的,但是我們卻進(jìn)行了字符串拼接,如果加上if(logger.isInfoEnabled())進(jìn)行一次判定,logger.info()就不會(huì)執(zhí)行,從而更好的提升性能,這個(gè)尤其是在高并發(fā)和復(fù)雜log打印情況下提升非常顯著。

另外,ERROR及其以上級(jí)別的log信息是一定會(huì)被輸出的,所以只有l(wèi)ogger.isDebugEnabled、logger.isInfoEnabled和logger.isWarnEnabled()方法,而沒(méi)有l(wèi)ogger.isErrorEnabled方法。

三、Log4j2

3.1、介紹

log4j2 是 log4j 1.x 的升級(jí)版,參考了 logback 的一些優(yōu)秀的設(shè)計(jì),并且修復(fù)了一些問(wèn)題,因此帶來(lái)了一些重大的提升,主要特點(diǎn)有:

圖片圖片

  • 異常處理:在logback中,Appender中的異常不會(huì)被應(yīng)用感知到,但是在log4j2中,提供了一些異常處理機(jī)制。
  • 性能提升, log4j2相較于log4j 1和logback都具有很明顯的性能提升,后面會(huì)有官方測(cè)試的數(shù)據(jù)。
  • 自動(dòng)重載配置:參考了logback的設(shè)計(jì),當(dāng)然會(huì)提供自動(dòng)刷新參數(shù)配置,最實(shí)用的就是我們?cè)谏a(chǎn)上可以動(dòng)態(tài)的修改日志的級(jí)別而不需要重啟應(yīng)用——那對(duì)監(jiān)控來(lái)說(shuō),是非常敏感的。
  • 無(wú)垃圾機(jī)制:log4j2在大部分情況下,都可以使用其設(shè)計(jì)的一套無(wú)垃圾機(jī)制,避免頻繁的日志收集導(dǎo)致的jvm gc。

3.2、項(xiàng)目應(yīng)用

3.2.1、添加 maven 依賴(lài)

<dependencies>
    <!-- slf4j核心包 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.13</version>
    </dependency>
    <!--用于與common-log保持橋接 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.7.13</version>
        <scope>runtime</scope>
    </dependency>
    <!--核心log4j2jar包 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.4.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.4.1</version>
    </dependency>
    <!--用于與slf4j保持橋接 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.4.1</version>
    </dependency>
    <!--需要使用log4j2的AsyncLogger需要包含disruptor -->
    <dependency>
        <groupId>com.lmax</groupId>
        <artifactId>disruptor</artifactId>
        <version>3.2.0</version>
    </dependency>
</dependencies>

3.2.2、創(chuàng)建log4j2配置

在項(xiàng)目的根目錄下創(chuàng)建一個(gè)log4j2.xml的文件,與log4j相比,log4j2的異步輸出日志性能非常強(qiáng)勁,配置如下:

  • 同步輸出日志
<?xml versinotallow="1.0" encoding="UTF-8"?>
<!-- status : 這個(gè)用于設(shè)置log4j2自身內(nèi)部的信息輸出,可以不設(shè)置,當(dāng)設(shè)置成trace時(shí)。
 注:本配置文件的目標(biāo)是將不同級(jí)別的日志輸出到不同文件,最大1MB一個(gè)文件, 
    文件數(shù)據(jù)達(dá)到最大值時(shí),舊數(shù)據(jù)會(huì)被壓縮并放進(jìn)指定文件夾 ,最多存放20個(gè)文件-->
<Configuration status="error">
    <!-- 配置日志文件輸出目錄,此配置將日志輸出到根目錄下的指定文件夾 -->
    <Properties>
        <Property name="fileDir">/logs/log4j2</Property>
        <Property name="fileHistory">/logs/log4j2/history</Property>
    </Properties>
    <Appenders>
        <!-- 優(yōu)先級(jí)從高到低分別是 OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL -->
        <!-- 單詞解釋?zhuān)?Match:匹配 DENY:拒絕 Mismatch:不匹配 ACCEPT:接受 -->
        <!-- DENY,日志將立即被拋棄不再經(jīng)過(guò)其他過(guò)濾器; NEUTRAL,有序列表里的下個(gè)過(guò)濾器過(guò)接著處理日志; ACCEPT,日志會(huì)被立即處理,不再經(jīng)過(guò)剩余過(guò)濾器。 -->
        <!--輸出日志的格式
        %d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生產(chǎn)時(shí)間
        %t 輸出當(dāng)前線(xiàn)程名稱(chēng)
        %-5level 輸出日志級(jí)別,-5表示左對(duì)齊并且固定輸出5個(gè)字符,如果不足在右邊補(bǔ)0
        %logger 輸出logger名稱(chēng),因?yàn)镽oot Logger沒(méi)有名稱(chēng),所以沒(méi)有輸出
        %msg 日志文本
        %n 換行
        其他常用的占位符有:
        %F 輸出所在的類(lèi)文件名,如Client.java
        %L 輸出行號(hào)
        %M 輸出所在方法名
        %l  輸出語(yǔ)句所在的行數(shù), 包括類(lèi)名、方法名、文件名、行數(shù)
         -->
        <!--這個(gè)輸出控制臺(tái)的配置,這里輸出all信息到System.out -->
        <console name="Console" target="SYSTEM_OUT">
            <!-- 輸出日志的格式 -->
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
        </console>
        <!--這個(gè)輸出文件的配置,這里輸出info信息到j(luò)unbao_info.log -->
        <RollingFile name="RollingFileInfo" fileName="${fileDir}/info.log" filePattern="${fileHistory}/info/%d{yyyy-MM-dd}-%i.log">
            <!-- 此Filter意思是,只輸出info級(jí)別的數(shù)據(jù) DENY,日志將立即被拋棄不再經(jīng)過(guò)其他過(guò)濾器; NEUTRAL,有序列表里的下個(gè)過(guò)濾器過(guò)接著處理日志; 
                    ACCEPT,日志會(huì)被立即處理,不再經(jīng)過(guò)剩余過(guò)濾器。 -->
            <ThresholdFilter level="info" notallow="ACCEPT" notallow="DENY" />
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
            <Policies>
            <!-- 如果啟用此配置,則日志會(huì)按文件名生成新文件, 即如果filePattern配置的日期格式為 %d{yyyy-MM-dd HH} 
                    ,則每小時(shí)生成一個(gè)壓縮文件, 如果filePattern配置的日期格式為 %d{yyyy-MM-dd} ,則天生成一個(gè)壓縮文件,默認(rèn)為1 -->
                <TimeBasedTriggeringPolicy />
                <!-- 每個(gè)日志文件最大1MB,超過(guò)1MB生產(chǎn)新的文件 ; -->
                <SizeBasedTriggeringPolicy size="100MB" />
            </Policies>
             <!--文件夾下最多的文件個(gè)數(shù)-->  
            <DefaultRolloverStrategy max="20" />
        </RollingFile>
        <RollingFile name="RollingFileWarn" fileName="${fileDir}/warn.log" filePattern="${fileHistory}/warn/%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="warn" notallow="ACCEPT" notallow="DENY" />
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="100MB" />
            </Policies>
            <DefaultRolloverStrategy max="20" />
        </RollingFile>
        <RollingFile name="RollingFileError" fileName="${fileDir}/error.log" filePattern="${fileHistory}/error/%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="error" notallow="ACCEPT" notallow="DENY" />
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="100MB" />
            </Policies>
            <DefaultRolloverStrategy max="20" />
        </RollingFile>
    </Appenders>
    <!--然后定義logger,只有定義了logger并引入的appender,appender才會(huì)生效 -->
    <Loggers>
        <!--全異步輸出info級(jí)以上的日志信息--> 
        <!-- <asyncRoot level="info" includeLocatinotallow="true">
            <appender-ref ref="Console" />
            <appender-ref ref="RollingFileInfo" />
        </asyncRoot> -->
        <!--同步輸出info級(jí)以上的日志信息--> 
        <root level="info" includeLocatinotallow="true">
            <appender-ref ref="Console" />
        </root>
    </Loggers>
</Configuration>
  • 異步輸出日志
<?xml versinotallow="1.0" encoding="UTF-8"?>
<!-- status : 這個(gè)用于設(shè)置log4j2自身內(nèi)部的信息輸出,可以不設(shè)置,當(dāng)設(shè)置成trace時(shí)。
 注:本配置文件的目標(biāo)是將不同級(jí)別的日志輸出到不同文件,最大1MB一個(gè)文件, 
    文件數(shù)據(jù)達(dá)到最大值時(shí),舊數(shù)據(jù)會(huì)被壓縮并放進(jìn)指定文件夾 ,最多存放20個(gè)文件-->
<Configuration status="error">
    <!-- 配置日志文件輸出目錄,此配置將日志輸出到根目錄下的指定文件夾 -->
    <Properties>
        <Property name="fileDir">/logs/log4j2</Property>
        <Property name="fileHistory">/logs/log4j2/history</Property>
    </Properties>
    <Appenders>
        <!-- 優(yōu)先級(jí)從高到低分別是 OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL -->
        <!-- 單詞解釋?zhuān)?Match:匹配 DENY:拒絕 Mismatch:不匹配 ACCEPT:接受 -->
        <!-- DENY,日志將立即被拋棄不再經(jīng)過(guò)其他過(guò)濾器; NEUTRAL,有序列表里的下個(gè)過(guò)濾器過(guò)接著處理日志; ACCEPT,日志會(huì)被立即處理,不再經(jīng)過(guò)剩余過(guò)濾器。 -->
        <!--輸出日志的格式
        %d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生產(chǎn)時(shí)間
        %t 輸出當(dāng)前線(xiàn)程名稱(chēng)
        %-5level 輸出日志級(jí)別,-5表示左對(duì)齊并且固定輸出5個(gè)字符,如果不足在右邊補(bǔ)0
        %logger 輸出logger名稱(chēng),因?yàn)镽oot Logger沒(méi)有名稱(chēng),所以沒(méi)有輸出
        %msg 日志文本
        %n 換行
        其他常用的占位符有:
        %F 輸出所在的類(lèi)文件名,如Client.java
        %L 輸出行號(hào)
        %M 輸出所在方法名
        %l  輸出語(yǔ)句所在的行數(shù), 包括類(lèi)名、方法名、文件名、行數(shù)
         -->
        <!--這個(gè)輸出控制臺(tái)的配置,這里輸出all信息到System.out -->
        <console name="Console" target="SYSTEM_OUT">
            <!-- 輸出日志的格式 -->
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
        </console>
        <!--這個(gè)輸出文件的配置,這里輸出info信息到j(luò)unbao_info.log -->
        <RollingFile name="RollingFileInfo" fileName="${fileDir}/info.log" filePattern="${fileHistory}/info/%d{yyyy-MM-dd}-%i.log">
            <!-- 此Filter意思是,只輸出info級(jí)別的數(shù)據(jù) DENY,日志將立即被拋棄不再經(jīng)過(guò)其他過(guò)濾器; NEUTRAL,有序列表里的下個(gè)過(guò)濾器過(guò)接著處理日志; 
                    ACCEPT,日志會(huì)被立即處理,不再經(jīng)過(guò)剩余過(guò)濾器。 -->
            <ThresholdFilter level="info" notallow="ACCEPT" notallow="DENY" />
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
            <Policies>
            <!-- 如果啟用此配置,則日志會(huì)按文件名生成新文件, 即如果filePattern配置的日期格式為 %d{yyyy-MM-dd HH} 
                    ,則每小時(shí)生成一個(gè)壓縮文件, 如果filePattern配置的日期格式為 %d{yyyy-MM-dd} ,則天生成一個(gè)壓縮文件,默認(rèn)為1 -->
                <TimeBasedTriggeringPolicy />
                <!-- 每個(gè)日志文件最大1MB,超過(guò)1MB生產(chǎn)新的文件 ; -->
                <SizeBasedTriggeringPolicy size="100MB" />
            </Policies>
             <!--文件夾下最多的文件個(gè)數(shù)-->  
            <DefaultRolloverStrategy max="20" />
        </RollingFile>
        <RollingFile name="RollingFileWarn" fileName="${fileDir}/warn.log" filePattern="${fileHistory}/warn/%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="warn" notallow="ACCEPT" notallow="DENY" />
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="100MB" />
            </Policies>
            <DefaultRolloverStrategy max="20" />
        </RollingFile>
        <RollingFile name="RollingFileError" fileName="${fileDir}/error.log" filePattern="${fileHistory}/error/%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="error" notallow="ACCEPT" notallow="DENY" />
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="100MB" />
            </Policies>
            <DefaultRolloverStrategy max="20" />
        </RollingFile>
    </Appenders>
    <!--然后定義logger,只有定義了logger并引入的appender,appender才會(huì)生效 -->
    <Loggers>
        <!--全異步輸出info級(jí)以上的日志信息--> 
        <asyncRoot level="info" includeLocatinotallow="true">
            <appender-ref ref="Console" />
            <appender-ref ref="RollingFileInfo" />
        </asyncRoot>
        <!--同步輸出info級(jí)以上的日志信息--> 
        <!-- <root level="info" includeLocatinotallow="true">
            <appender-ref ref="Console" />
        </root> -->
    </Loggers>
</Configuration>

詳細(xì) API 可以參考官方網(wǎng)站!

3.2.3、log4j2使用

與 log4j 類(lèi)似,直接在需要位置打印日志即可。

package org.example.log4j.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogPrintUtil {
    /**log靜態(tài)常量*/
    private static final Logger logger = LoggerFactory.getLogger(LogPrintUtil.class);
    public static void main(String[] args){
            logger.info("info信息");
            logger.warn("warn信息");
            logger.error("error信息");
    }
}

四、Logback

4.1、介紹

Logback 也是用 java 編寫(xiě)一款非常熱門(mén)的日志開(kāi)源框架,由 log4j 創(chuàng)始人寫(xiě)的,性能比 log4j 要好!

logback 主要分為3個(gè)模塊:

  • logback-core:核心代碼模塊
  • logback-classic:log4j的一個(gè)改良版本,同時(shí)實(shí)現(xiàn)了slf4j的接口,這樣你如果之后要切換其他日志組件也是一件很容易的事
  • logback-access:訪(fǎng)問(wèn)模塊與Servlet容器集成提供通過(guò)Http來(lái)訪(fǎng)問(wèn)日志的功能

4.2、項(xiàng)目應(yīng)用

4.2.1、添加 maven 依賴(lài)

<!--這個(gè)依賴(lài)直接包含了 logback-core 以及 slf4j-api的依賴(lài)-->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>
<!-- 支持在xml中寫(xiě)判斷標(biāo)簽 -->
<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>janino</artifactId>
    <version>2.7.8</version>
</dependency>

4.2.2、創(chuàng)建logback配置文件

  • 配置說(shuō)明

logback在啟動(dòng)的時(shí)候,會(huì)按照下面的順序加載配置文件:

a.如果java程序啟動(dòng)時(shí)指定了logback.configurationFile屬性,就用該屬性指定的配置文件。如java -Dlogback.cnotallow=/path/to/mylogback.xml Test,這樣執(zhí)行Test類(lèi)的時(shí)候就會(huì)加載/path/to/mylogback.xml配置

b.在classpath中查找logback.groovy文件

c.在classpath中查找logback-test.xml文件

d.在classpath中查找logback.xml文件

e.如果是jdk6+,那么會(huì)調(diào)用ServiceLoader查找 com.qos.logback.classic.spi.Configurator接口的第一個(gè)實(shí)現(xiàn)類(lèi)

自動(dòng)使用ch.qos.logback.classic.BasicConfigurator,在控制臺(tái)輸出日志

上面的順序表示優(yōu)先級(jí),使用java -D配置的優(yōu)先級(jí)最高,只要獲取到配置后就不會(huì)再執(zhí)行下面的流程。相關(guān)代碼可以看ContextInitializer#autoConfig()方法。

2、同步輸出日志

<?xml versinotallow="1.0" encoding="UTF-8"?>
<!-- scan:當(dāng)此屬性設(shè)置為true時(shí),配置文件如果發(fā)生改變,將會(huì)被重新加載,默認(rèn)值為true。 scanPeriod:設(shè)置監(jiān)測(cè)配置文件是否有修改的時(shí)間間隔,如果沒(méi)有給出時(shí)間單位,默認(rèn)單位是毫秒。當(dāng)scan為true時(shí),此屬性生效。默認(rèn)的時(shí)間間隔為1分鐘。 
    debug:當(dāng)此屬性設(shè)置為true時(shí),將打印出logback內(nèi)部日志信息,實(shí)時(shí)查看logback運(yùn)行狀態(tài)。默認(rèn)值為false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- 運(yùn)行環(huán)境,dev:開(kāi)發(fā),test:測(cè)試,pre:預(yù)生產(chǎn),pro:生產(chǎn) -->
    <property name="system_host" value="dev" />
    <property file="system.properties" />
    <!-- 上下文變量設(shè)置,用來(lái)定義變量值,其中name的值是變量的名稱(chēng),value的值時(shí)變量定義的值。 通過(guò)<property>定義的值會(huì)被插入到logger上下文中。定義變量后,可以使“${}”來(lái)使用變量。 -->
    <property name="CONTEXT_NAME" value="logback-test" />
    <!-- 日志文件存放路徑設(shè)置,絕對(duì)路徑 -->
    <property name="logs.dir" value="/opt/logs" />
    <!-- 日志文件存放路徑設(shè)置,tomcat路徑 -->
    <property name="logs.dir" value="${catalina.base}/logs" />
    <!-- 定義日志文件 相對(duì)輸入位置 -->  
    <property name="log_dir" value="log" />
    <!-- 日志輸出格式設(shè)置 -->
    <!-- 
    %d{yyyy-MM-dd HH:mm:ss} [%level] - %msg%n
      Logger: %logger
      Class: %class
      File: %file
      Caller: %caller
      Line: %line
      Message: %m
      Method: %M
      Relative: %relative
      Thread: %thread
      Exception: %ex
      xException: %xEx
      nopException: %nopex
      rException: %rEx
      Marker: %marker
      newline:%n
    -->
    <property name="CUSTOM_LOG_PATTERN"
        value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{90} - %msg%n" />
    <!-- 上下文名稱(chēng):<contextName>, 每個(gè)logger都關(guān)聯(lián)到logger上下文, 默認(rèn)上下文名稱(chēng)為“default”。但可以使用<contextName>設(shè)置成其他名字,用于區(qū)分不同應(yīng)用程序的記錄。 
        一旦設(shè)置,不能修改。 -->
    <contextName>${CONTEXT_NAME}</contextName>
    <!-- <appender>是<configuration>的子節(jié)點(diǎn),是負(fù)責(zé)寫(xiě)日志的組件。 有兩個(gè)必要屬性name和class。 name指定appender名稱(chēng), 
        class指定appender的實(shí)現(xiàn)類(lèi)。 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 對(duì)日志進(jìn)行格式化。 -->
        <encoder>
            <pattern>${CUSTOM_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <appender name="file"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 按天來(lái)回滾,如果需要按小時(shí)來(lái)回滾,則設(shè)置為{yyyy-MM-dd_HH} -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>log/testC.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 如果按天來(lái)回滾,則最大保存時(shí)間為30天,30天之前的都將被清理掉 -->
            <maxHistory>30</maxHistory>
            <!-- 按時(shí)間回滾的同時(shí),按文件大小來(lái)回滾 -->
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 過(guò)濾器,只記錄WARN級(jí)別的日志 -->
        <!-- 果日志級(jí)別等于配置級(jí)別,過(guò)濾器會(huì)根據(jù)onMath 和 onMismatch接收或拒絕日志。 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 設(shè)置過(guò)濾級(jí)別 -->
            <level>WARN</level>
            <!-- 用于配置符合過(guò)濾條件的操作 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 用于配置不符合過(guò)濾條件的操作 -->
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 日志輸出格式 -->
        <encoder>
            <pattern>${CUSTOM_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <appender name="log_file"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 被寫(xiě)入的文件名,可以是相對(duì)目錄,也可以是絕對(duì)目錄,如果上級(jí)目錄不存在會(huì)自動(dòng)創(chuàng)建,沒(méi)有默認(rèn)值。 -->
        <file>${logs.dir}/logback-test.log</file>
        <!-- 按照固定窗口模式生成日志文件,當(dāng)文件大于20MB時(shí),生成新的日志文件。窗口大小是1到3,當(dāng)保存了3個(gè)歸檔文件后,將覆蓋最早的日志 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <!-- 必須包含“%i”例如,假設(shè)最小值和最大值分別為1和2,命名模式為 mylog%i.log,會(huì)產(chǎn)生歸檔文件mylog1.log和mylog2.log。還可以指定文件壓縮選項(xiàng),例如,mylog%i.log.gz 
                或者 沒(méi)有l(wèi)og%i.log.zip -->
            <FileNamePattern>${logs.dir}/logback-test.%i.log</FileNamePattern>
            <!-- 窗口索引最小值 -->
            <minIndex>1</minIndex>
            <!-- 窗口索引最大值 -->
            <maxIndex>3</maxIndex>
        </rollingPolicy>
        <!-- 日志級(jí)別過(guò)濾器 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 日志級(jí)別過(guò)濾器 -->
            <level>INFO</level>
            <!-- 符合要求的日志級(jí)別,過(guò)濾,ACCEPT:接受 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 不符合要求的日志級(jí)別,過(guò)濾,DENY:拒絕 -->
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 激活滾動(dòng)的條件。 -->
        <triggeringPolicy
            class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <!-- 活動(dòng)文件的大小,默認(rèn)值是10MB -->
            <maxFileSize>30MB</maxFileSize>
        </triggeringPolicy>
        <!-- 對(duì)記錄事件進(jìn)行格式化。 -->
        <encoder>
            <pattern>${CUSTOM_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <!-- 異步輸出 -->
    <appender name="ASYNC_logback" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丟失日志.默認(rèn)的,如果隊(duì)列的80%已滿(mǎn),則會(huì)丟棄TRACT、DEBUG、INFO級(jí)別的日志 -->
        <!-- <discardingThreshold>0</discardingThreshold> -->
        <!-- 更改默認(rèn)的隊(duì)列的深度,該值會(huì)影響性能.默認(rèn)值為256 -->
        <!-- <queueSize>256</queueSize> -->
        <!-- 添加附加的appender,最多只能添加一個(gè) -->
        <appender-ref ref="log_file" />
    </appender>
    <!-- 指定包輸出路徑 -->
    <!-- 用來(lái)設(shè)置某一個(gè) 包 或者具體的某一個(gè) 類(lèi) 的日志打印級(jí)別、以及指定<appender>, name:用來(lái)指定受此logger約束的某一個(gè)包或者具體的某一個(gè)類(lèi)。 
        level:用來(lái)設(shè)置打印級(jí)別,大小寫(xiě)無(wú)關(guān):TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,還有一個(gè)特俗值INHERITED或者同義詞NULL,代表強(qiáng)制執(zhí)行上級(jí)的級(jí)別。如果未設(shè)置此屬性,那么當(dāng)前l(fā)oger將會(huì)繼承上級(jí)的級(jí)別。 
        additivity:是否向上級(jí)logger傳遞打印信息。默認(rèn)是true。(這個(gè)logger的上級(jí)就是上面的root) <logger>可以包含零個(gè)或多個(gè)<appender-ref>元素,標(biāo)識(shí)這個(gè)appender將會(huì)添加到這個(gè)logger。 -->
    <logger name="org.logback.test" level="DEBUG" additivity="true">
        <appender-ref ref="stdout" />
    </logger>
    <!-- 特殊的<logger>元素,是根logger。只有一個(gè)level屬性,應(yīng)為已經(jīng)被命名為"root". level:設(shè)置打印級(jí)別,大小寫(xiě)無(wú)關(guān):TRACE, 
        DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能設(shè)置為INHERITED或者同義詞NULL。默認(rèn)是DEBUG。 <root>可以包含零個(gè)或多個(gè)<appender-ref>元素,標(biāo)識(shí)這個(gè)appender將會(huì)添加到這個(gè)loger。 -->
    <root>
        <level value="WARN" />
        <!-- if表達(dá)式,需要Janino jar -->
        <!-- Janino 2.6.0版本開(kāi)始,除了janino.jar之外, commons-compiler.jar也需要在類(lèi)路徑中 -->
        <if cnotallow='property("system_host").contains("dev")'>
            <then>
                <appender-ref ref="stdout" />
            </then>
        </if>
        <appender-ref ref="file" />
    </root>
</configuration>

注意:logback如果配置要輸出行號(hào),性能會(huì)明顯降低,如果不是必須,建議不要配置!

4.2.3、logback使用

package org.example.logback.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogPrintUtil {
    /**log靜態(tài)常量*/
    private static final Logger logger = LoggerFactory.getLogger(LogPrintUtil.class);
    public static void main(String[] args){
            logger.info("info信息");
            logger.warn("warn信息");
            logger.error("error信息");
    }
}

五、SLF4J橋接

細(xì)心的你,會(huì)發(fā)現(xiàn)上面代碼使用時(shí),都使用的是private static final Logger logger = LoggerFactory.getLogger(LogPrintUtil.class)這個(gè),其中都來(lái)自org.slf4j包,SLF4J是啥?有什么作用呢?

SLF4J本身并不輸出日志,最大的特色是:它可以通過(guò)適配的方式掛接不同的日志系統(tǒng),屬于一個(gè)日志接口。

如果項(xiàng)目適配到log4j就使用log4j日志庫(kù)進(jìn)行輸出;如果適配到logback就使用logback日志庫(kù)進(jìn)行輸出;如果適配到log4j2就使用log4j2日志庫(kù)進(jìn)行輸出。

這樣最大的好處,就是當(dāng)你想將項(xiàng)目從log4j換成log4j2的時(shí)候,只需要在項(xiàng)目pom.xml中進(jìn)行橋接適配即可,不用修改具體需要打印日志的代碼!

六、三大主流日志框架性能比較

介紹了這么多,但是我們還不知道三個(gè)日志框架的日志輸出性能如何,本文以10000條數(shù)據(jù)進(jìn)行打印,比較log4j、log4j2、logback日志的輸出時(shí)間。

本次測(cè)試采用的是本地電腦(win7),每個(gè)電腦的配置不一樣,測(cè)試的結(jié)果也不一樣,結(jié)果是真實(shí)的。

  • 同步輸出

圖片圖片

  • 異步輸出

圖片圖片

從測(cè)試結(jié)果上可以看出:

  • 不建議生產(chǎn)環(huán)境進(jìn)行控制臺(tái)輸出;
  • 在純文件輸出的環(huán)境下,logback的輸出優(yōu)于log4j2,而log4j2要優(yōu)于log4j,如果要進(jìn)行生產(chǎn)環(huán)境的部署,建議采用logback,如果是使用log4j2,建議使用異步方式進(jìn)行輸出,輸出結(jié)果基本是實(shí)時(shí)輸出;

最后需要注意的地方是:log有風(fēng)險(xiǎn),輸出需謹(jǐn)慎!

由于輸出log過(guò)程需要進(jìn)行磁盤(pán)操作,且log4j為了保證log輸出過(guò)程的線(xiàn)程安全性而使用同步鎖,就使得輸出log成為很耗時(shí)的操作,所以log信息一定要言簡(jiǎn)意賅,不要輸出一些無(wú)用的log。

責(zé)任編輯:武曉燕 來(lái)源: 潘志的技術(shù)筆記
相關(guān)推薦

2020-10-23 07:43:37

Log配置性能

2023-11-07 07:46:02

GatewayKubernetes

2021-09-30 07:59:06

zookeeper一致性算法CAP

2019-08-16 09:41:56

UDP協(xié)議TCP

2021-10-21 06:52:17

ZooKeeper分布式配置

2021-05-07 07:52:51

Java并發(fā)編程

2022-03-29 08:23:56

項(xiàng)目數(shù)據(jù)SIEM

2024-08-27 11:00:56

單例池緩存bean

2017-03-30 22:41:55

虛擬化操作系統(tǒng)軟件

2021-09-10 13:06:45

HDFS底層Hadoop

2023-09-25 08:32:03

Redis數(shù)據(jù)結(jié)構(gòu)

2023-10-04 00:32:01

數(shù)據(jù)結(jié)構(gòu)Redis

2021-07-28 13:29:57

大數(shù)據(jù)PandasCSV

2025-02-17 00:00:20

itext生成庫(kù)pdf

2021-04-11 08:30:40

VRAR虛擬現(xiàn)實(shí)技術(shù)

2018-09-26 11:02:46

微服務(wù)架構(gòu)組件

2022-08-18 20:45:30

HTTP協(xié)議數(shù)據(jù)

2023-12-07 09:07:58

2021-11-10 07:47:48

Traefik邊緣網(wǎng)關(guān)

2023-11-22 07:54:33

Xargs命令Linux
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)