【引】主流日誌框架使用及性能對比,看這篇就夠了!

如下文章來源於鴨血粉絲java

1、摘要

無論是使用何種編程語言,何種框架,日誌輸出幾乎無處再也不,也是任何商業軟件中必不可少的一部分。數據庫

總結起來,日誌的用途大體能夠概括成如下三種:apache

  • 問題追蹤:經過日誌不只僅包括咱們程序的一些bug,也能夠在安裝配置時,經過日誌能夠發現問題。
  • 狀態監控:經過實時分析日誌,能夠監控系統的運行狀態,作到早發現問題、早處理問題。
  • 安全審計:審計主要體如今安全上,經過對日誌進行分析,能夠發現是否存在非受權的操做。

以 Java 編程語言爲例,打印日誌的方式有不少,例如經過System.out.print()方法將關鍵信息輸出到控制檯,也能夠經過 JDK 自帶的日誌Logger類輸出,雖然 JDK 從1.4開始支持日誌輸出,可是功能單一,沒法更好的知足商業要求,因而誕生了不少第三方日誌庫,像咱們所熟悉的主流框架log4jlog4j2logback等,提供的 API 功能都遠勝 JDK 提供的Logger編程

2、Log4j

2.一、介紹

Log4j 是一種很是流行的日誌框架,由Ceki Gülcü獨創,以後將其開源貢獻給 Apache 軟件基金會。api

Log4j 有三個主要的組件:Loggers(記錄器),Appenders (輸出源)和Layouts(佈局)。這裏可簡單理解爲日誌類別日誌要輸出的地方日誌以何種形式輸出tomcat

綜合使用這三個組件能夠輕鬆地記錄信息的類型和級別,並能夠在運行時控制日誌輸出的樣式和位置。安全

Log4j 的架構大體以下:網絡

圖片

當咱們使用 Log4j 輸出一條日誌時,Log4j 自動經過不一樣的Appender(輸出源)把同一條日誌輸出到不一樣的目的地。例如:架構

  • console:輸出到屏幕;
  • file:輸出到文件;
  • socket:經過網絡輸出到遠程計算機;
  • jdbc:輸出到數據庫

在輸出日誌的過程當中,經過Filter來過濾哪些log須要被輸出,哪些log不須要被輸出。併發

Loggers(記錄器)組件中,級別分五種:DEBUGINFOWARNERRORFATAL

這五個級別是有順序的,DEBUG < INFO < WARN < ERROR < FATAL,分別用來指定這條日誌信息的重要程度,明白這一點很重要,Log4j有一個規則:只輸出級別不低於設定級別的日誌信息

假設Loggers級別設定爲INFO,則INFOWARNERRORFATAL級別的日誌信息都會輸出,而級別比INFO低的DEBUG則不會輸出。

最後,經過Layout來格式化日誌信息,例如,自動添加日期、時間、方法名稱等信息。

具體輸出樣式配置,能夠參考以下內容Log4j2 - Layouts佈局介紹

2.二、項目應用

以 Java 項目爲例,在 Maven 的pom.xml中添加以下依賴!

2.2.一、添加 maven 依賴
<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.二、建立log4j配置

在實際應用中,要使Log4j在系統中運行須事先設定配置文件。

配置文件實際上也就是對LoggerAppenderLayout進行相應設定。

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

建立一個log4j.xml或者log4j.properties,將其放入項目根目錄下。

一、XML格式
<?xml version="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/">
    <!-- 控制檯輸出配置 -->
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <!-- 目標爲控制檯 -->
        <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">
        <!-- 目標爲文件 -->
        <param name="File" value="/logs/log/file.log" />
        <!-- 向文件追加輸出 -->
        <param name="Append" value="true" />
        <!-- 每一個小時生成一個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>

二、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
2.2.三、log4j使用

在須要打印日誌的類中,引入Logger類,在須要的地方打印便可!

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

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

固然你還能夠這樣寫

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

2.2.四、isInfoEnabled()有何做用呢?

簡單來講,在某些場景下,用isInfoEnabled()方法判斷下是能提高性能的!

例如咱們打印這段內容logger.info("User:" + userId + appId),程序在打印這行代碼時,先對內容("User:" + userId + appId)進行字符串拼接,而後再輸出。

若是當前配置文件中日誌輸出級別是info,是直接輸出的,當日志輸出級別是error時,logger.info()的內容時不輸出的,可是咱們卻進行了字符串拼接,若是加上if(logger.isInfoEnabled())進行一次斷定,logger.info()就不會執行,從而更好的提高性能,這個尤爲是在高併發和複雜log打印狀況下提高很是顯著。

另外,ERROR及其以上級別的log信息是必定會被輸出的,因此只有logger.isDebugEnabledlogger.isInfoEnabledlogger.isWarnEnabled()方法,而沒有logger.isErrorEnabled方法

3、Log4j2

3.一、介紹

log4j2 是 log4j 1.x 的升級版,參考了 logback 的一些優秀的設計,而且修復了一些問題,所以帶來了一些重大的提高,主要特色有:

圖片

  • 異常處理:在logback中,Appender中的異常不會被應用感知到,可是在log4j2中,提供了一些異常處理機制。
  • 性能提高, log4j2相較於log4j 1和logback都具備很明顯的性能提高,後面會有官方測試的數據。
  • 自動重載配置:參考了logback的設計,固然會提供自動刷新參數配置,最實用的就是咱們在生產上能夠動態的修改日誌的級別而不須要重啓應用——那對監控來講,是很是敏感的。
  • 無垃圾機制:log4j2在大部分狀況下,均可以使用其設計的一套無垃圾機制,避免頻繁的日誌收集致使的jvm gc。

3.二、項目應用

3.2.一、添加 maven 依賴
<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.二、建立log4j2配置

在項目的根目錄下建立一個log4j2.xml的文件,與log4j相比,log4j2的異步輸出日誌性能很是強勁,配置以下:

一、同步輸出日誌

<?xml version="1.0" encoding="UTF-8"?>
<!-- status : 這個用於設置log4j2自身內部的信息輸出,能夠不設置,當設置成trace時。
 注:本配置文件的目標是將不一樣級別的日誌輸出到不一樣文件,最大1MB一個文件, 
    文件數據達到最大值時,舊數據會被壓縮並放進指定文件夾 ,最多存放20個文件-->
<Configuration status="error">
    <!-- 配置日誌文件輸出目錄,此配置將日誌輸出到根目錄下的指定文件夾 -->
    <Properties>
        <Property name="fileDir">/logs/log4j2</Property>
        <Property name="fileHistory">/logs/log4j2/history</Property>
    </Properties>
    <Appenders>
        <!-- 優先級從高到低分別是 OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL -->
        <!-- 單詞解釋:Match:匹配 DENY:拒絕 Mismatch:不匹配 ACCEPT:接受 -->
        <!-- DENY,日誌將當即被拋棄再也不通過其餘過濾器;NEUTRAL,有序列表裏的下個過濾器過接着處理日誌;ACCEPT,日誌會被當即處理,再也不通過剩餘過濾器。 -->
        <!--輸出日誌的格式
        %d{yyyy-MM-dd HH:mm:ss, SSS} : 日誌生產時間
        %t 輸出當前線程名稱
        %-5level 輸出日誌級別,-5表示左對齊而且固定輸出5個字符,若是不足在右邊補0
        %logger 輸出logger名稱,由於Root Logger沒有名稱,因此沒有輸出
        %msg 日誌文本
        %n 換行
        其餘經常使用的佔位符有:
        %F 輸出所在的類文件名,如Client.java
        %L 輸出行號
        %M 輸出所在方法名
        %l  輸出語句所在的行數, 包括類名、方法名、文件名、行數
         -->
        <!--這個輸出控制檯的配置,這裏輸出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>
        <!--這個輸出文件的配置,這裏輸出info信息到junbao_info.log -->
        <RollingFile name="RollingFileInfo" fileName="${fileDir}/info.log" filePattern="${fileHistory}/info/%d{yyyy-MM-dd}-%i.log">
            <!-- 此Filter意思是,只輸出info級別的數據 DENY,日誌將當即被拋棄再也不通過其餘過濾器;NEUTRAL,有序列表裏的下個過濾器過接着處理日誌; 
                    ACCEPT,日誌會被當即處理,再也不通過剩餘過濾器。 -->
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
            <Policies>
            <!-- 若是啓用此配置,則日誌會按文件名生成新文件, 即若是filePattern配置的日期格式爲 %d{yyyy-MM-dd HH} 
                    ,則每小時生成一個壓縮文件, 若是filePattern配置的日期格式爲 %d{yyyy-MM-dd} ,則天生成一個壓縮文件,默認爲1 -->
                <TimeBasedTriggeringPolicy />
                <!-- 每一個日誌文件最大1MB,超過1MB生產新的文件 ; -->
                <SizeBasedTriggeringPolicy size="100MB" />
            </Policies>
             <!--文件夾下最多的文件個數-->  
            <DefaultRolloverStrategy max="20" />
        </RollingFile>
        <RollingFile name="RollingFileWarn" fileName="${fileDir}/warn.log" filePattern="${fileHistory}/warn/%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="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" onMatch="ACCEPT" onMismatch="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纔會生效 -->
    <Loggers>
        <!--全異步輸出info級以上的日誌信息--> 
        <!-- <asyncRoot level="info" includeLocation="true">
            <appender-ref ref="Console" />
            <appender-ref ref="RollingFileInfo" />
        </asyncRoot> -->
        <!--同步輸出info級以上的日誌信息--> 
        <root level="info" includeLocation="true">
            <appender-ref ref="Console" />
        </root>
    </Loggers>
</Configuration>

二、異步輸出日誌

<?xml version="1.0" encoding="UTF-8"?>
<!-- status : 這個用於設置log4j2自身內部的信息輸出,能夠不設置,當設置成trace時。
 注:本配置文件的目標是將不一樣級別的日誌輸出到不一樣文件,最大1MB一個文件, 
    文件數據達到最大值時,舊數據會被壓縮並放進指定文件夾 ,最多存放20個文件-->
<Configuration status="error">
    <!-- 配置日誌文件輸出目錄,此配置將日誌輸出到根目錄下的指定文件夾 -->
    <Properties>
        <Property name="fileDir">/logs/log4j2</Property>
        <Property name="fileHistory">/logs/log4j2/history</Property>
    </Properties>
    <Appenders>
        <!-- 優先級從高到低分別是 OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL -->
        <!-- 單詞解釋:Match:匹配 DENY:拒絕 Mismatch:不匹配 ACCEPT:接受 -->
        <!-- DENY,日誌將當即被拋棄再也不通過其餘過濾器;NEUTRAL,有序列表裏的下個過濾器過接着處理日誌;ACCEPT,日誌會被當即處理,再也不通過剩餘過濾器。 -->
        <!--輸出日誌的格式
        %d{yyyy-MM-dd HH:mm:ss, SSS} : 日誌生產時間
        %t 輸出當前線程名稱
        %-5level 輸出日誌級別,-5表示左對齊而且固定輸出5個字符,若是不足在右邊補0
        %logger 輸出logger名稱,由於Root Logger沒有名稱,因此沒有輸出
        %msg 日誌文本
        %n 換行
        其餘經常使用的佔位符有:
        %F 輸出所在的類文件名,如Client.java
        %L 輸出行號
        %M 輸出所在方法名
        %l  輸出語句所在的行數, 包括類名、方法名、文件名、行數
         -->
        <!--這個輸出控制檯的配置,這裏輸出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>
        <!--這個輸出文件的配置,這裏輸出info信息到junbao_info.log -->
        <RollingFile name="RollingFileInfo" fileName="${fileDir}/info.log" filePattern="${fileHistory}/info/%d{yyyy-MM-dd}-%i.log">
            <!-- 此Filter意思是,只輸出info級別的數據 DENY,日誌將當即被拋棄再也不通過其餘過濾器;NEUTRAL,有序列表裏的下個過濾器過接着處理日誌; 
                    ACCEPT,日誌會被當即處理,再也不通過剩餘過濾器。 -->
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %l %msg%n" />
            <Policies>
            <!-- 若是啓用此配置,則日誌會按文件名生成新文件, 即若是filePattern配置的日期格式爲 %d{yyyy-MM-dd HH} 
                    ,則每小時生成一個壓縮文件, 若是filePattern配置的日期格式爲 %d{yyyy-MM-dd} ,則天生成一個壓縮文件,默認爲1 -->
                <TimeBasedTriggeringPolicy />
                <!-- 每一個日誌文件最大1MB,超過1MB生產新的文件 ; -->
                <SizeBasedTriggeringPolicy size="100MB" />
            </Policies>
             <!--文件夾下最多的文件個數-->  
            <DefaultRolloverStrategy max="20" />
        </RollingFile>
        <RollingFile name="RollingFileWarn" fileName="${fileDir}/warn.log" filePattern="${fileHistory}/warn/%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="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" onMatch="ACCEPT" onMismatch="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纔會生效 -->
    <Loggers>
        <!--全異步輸出info級以上的日誌信息--> 
        <asyncRoot level="info" includeLocation="true">
            <appender-ref ref="Console" />
            <appender-ref ref="RollingFileInfo" />
        </asyncRoot>
        <!--同步輸出info級以上的日誌信息--> 
        <!-- <root level="info" includeLocation="true">
            <appender-ref ref="Console" />
        </root> -->
    </Loggers>
</Configuration>

詳細 API 能夠參考官方網站!

3.2.三、log4j2使用

與 log4j 相似,直接在須要位置打印日誌便可

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

4、Logback

4.一、介紹

Logback 也是用 java 編寫一款很是熱門的日誌開源框架,由 log4j 創始人寫的,性能比 log4j 要好!

logback 主要分爲3個模塊:

  • logback-core:核心代碼模塊
  • logback-classic:log4j的一個改良版本,同時實現了slf4j的接口,這樣你若是以後要切換其餘日誌組件也是一件很容易的事
  • logback-access:訪問模塊與Servlet容器集成提供經過Http來訪問日誌的功能

4.二、項目應用

4.2.一、添加 maven 依賴
<!--這個依賴直接包含了 logback-core 以及 slf4j-api的依賴-->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>
<!-- 支持在xml中寫判斷標籤 -->
<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>janino</artifactId>
    <version>2.7.8</version>
</dependency>
4.2.二、建立logback配置文件
一、配置說明

logback在啓動的時候,會按照下面的順序加載配置文件:

  • 若是java程序啓動時指定了logback.configurationFile屬性,就用該屬性指定的配置文件。如java -Dlogback.configurationFile=/path/to/mylogback.xml Test,這樣執行Test類的時候就會加載/path/to/mylogback.xml配置
  • classpath中查找logback.groovy文件
  • classpath中查找logback-test.xml文件
  • classpath中查找logback.xml文件
  • 若是是jdk6+,那麼會調用ServiceLoader查找 com.qos.logback.classic.spi.Configurator接口的第一個實現類
  • 自動使用ch.qos.logback.classic.BasicConfigurator,在控制檯輸出日誌

上面的順序表示優先級,使用java -D配置的優先級最高,只要獲取到配置後就不會再執行下面的流程。相關代碼能夠看ContextInitializer#autoConfig()方法。

二、同步輸出日誌
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan:當此屬性設置爲true時,配置文件若是發生改變,將會被從新加載,默認值爲true。scanPeriod:設置監測配置文件是否有修改的時間間隔,若是沒有給出時間單位,默認單位是毫秒。當scan爲true時,此屬性生效。默認的時間間隔爲1分鐘。 
    debug:當此屬性設置爲true時,將打印出logback內部日誌信息,實時查看logback運行狀態。默認值爲false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- 運行環境,dev:開發,test:測試,pre:預生產,pro:生產 -->
    <property name="system_host" value="dev" />
    <property file="system.properties" />
    <!-- 上下文變量設置,用來定義變量值,其中name的值是變量的名稱,value的值時變量定義的值。 經過<property>定義的值會被插入到logger上下文中。定義變量後,可使「${}」來使用變量。 -->
    <property name="CONTEXT_NAME" value="logback-test" />
    <!-- 日誌文件存放路徑設置,絕對路徑 -->
    <property name="logs.dir" value="/opt/logs" />
    <!-- 日誌文件存放路徑設置,tomcat路徑 -->
    <property name="logs.dir" value="${catalina.base}/logs" />
    <!-- 定義日誌文件 相對輸入位置 -->  
    <property name="log_dir" value="log" />
    <!-- 日誌輸出格式設置 -->
    <!-- 
    %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" />
    <!-- 上下文名稱:<contextName>, 每一個logger都關聯到logger上下文, 默認上下文名稱爲「default」。但可使用<contextName>設置成其餘名字,用於區分不一樣應用程序的記錄。 
        一旦設置,不能修改。 -->
    <contextName>${CONTEXT_NAME}</contextName>
    <!-- <appender>是<configuration>的子節點,是負責寫日誌的組件。 有兩個必要屬性name和class。name指定appender名稱, 
        class指定appender的實現類。 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 對日誌進行格式化。 -->
        <encoder>
            <pattern>${CUSTOM_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <appender name="file"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 按天來回滾,若是須要按小時來回滾,則設置爲{yyyy-MM-dd_HH} -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>log/testC.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 若是按天來回滾,則最大保存時間爲30天,30天以前的都將被清理掉 -->
            <maxHistory>30</maxHistory>
            <!-- 按時間回滾的同時,按文件大小來回滾 -->
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 過濾器,只記錄WARN級別的日誌 -->
        <!-- 果日誌級別等於配置級別,過濾器會根據onMath 和 onMismatch接收或拒絕日誌。 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 設置過濾級別 -->
            <level>WARN</level>
            <!-- 用於配置符合過濾條件的操做 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 用於配置不符合過濾條件的操做 -->
            <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">
        <!-- 被寫入的文件名,能夠是相對目錄,也能夠是絕對目錄,若是上級目錄不存在會自動建立,沒有默認值。 -->
        <file>${logs.dir}/logback-test.log</file>
        <!-- 按照固定窗口模式生成日誌文件,當文件大於20MB時,生成新的日誌文件。窗口大小是1到3,當保存了3個歸檔文件後,將覆蓋最先的日誌 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <!-- 必須包含「%i」例如,假設最小值和最大值分別爲1和2,命名模式爲 mylog%i.log,會產生歸檔文件mylog1.log和mylog2.log。還能夠指定文件壓縮選項,例如,mylog%i.log.gz 
                或者 沒有log%i.log.zip -->
            <FileNamePattern>${logs.dir}/logback-test.%i.log</FileNamePattern>
            <!-- 窗口索引最小值 -->
            <minIndex>1</minIndex>
            <!-- 窗口索引最大值 -->
            <maxIndex>3</maxIndex>
        </rollingPolicy>
        <!-- 日誌級別過濾器 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 日誌級別過濾器 -->
            <level>INFO</level>
            <!-- 符合要求的日誌級別,過濾,ACCEPT:接受 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 不符合要求的日誌級別,過濾,DENY:拒絕 -->
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 激活滾動的條件。 -->
        <triggeringPolicy
            class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <!-- 活動文件的大小,默認值是10MB -->
            <maxFileSize>30MB</maxFileSize>
        </triggeringPolicy>
        <!-- 對記錄事件進行格式化。 -->
        <encoder>
            <pattern>${CUSTOM_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
 
    <!-- 異步輸出 -->
    <appender name="ASYNC_logback" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丟失日誌.默認的,若是隊列的80%已滿,則會丟棄TRACT、DEBUG、INFO級別的日誌 -->
        <!-- <discardingThreshold>0</discardingThreshold> -->
        <!-- 更改默認的隊列的深度,該值會影響性能.默認值爲256 -->
        <!-- <queueSize>256</queueSize> -->
        <!-- 添加附加的appender,最多隻能添加一個 -->
        <appender-ref ref="log_file" />
    </appender>
    <!-- 指定包輸出路徑 -->
    <!-- 用來設置某一個 包 或者具體的某一個 類 的日誌打印級別、以及指定<appender>, name:用來指定受此logger約束的某一個包或者具體的某一個類。 
        level:用來設置打印級別,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,還有一個特俗值INHERITED或者同義詞NULL,表明強制執行上級的級別。若是未設置此屬性,那麼當前loger將會繼承上級的級別。 
        additivity:是否向上級logger傳遞打印信息。默認是true。(這個logger的上級就是上面的root) <logger>能夠包含零個或多個<appender-ref>元素,標識這個appender將會添加到這個logger。 -->
    <logger name="org.logback.test" level="DEBUG" additivity="true">
        <appender-ref ref="stdout" />
    </logger>
    <!-- 特殊的<logger>元素,是根logger。只有一個level屬性,應爲已經被命名爲"root". level:設置打印級別,大小寫無關:TRACE, 
        DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能設置爲INHERITED或者同義詞NULL。默認是DEBUG。 <root>能夠包含零個或多個<appender-ref>元素,標識這個appender將會添加到這個loger。 -->
    <root>
        <level value="WARN" />
        <!-- if表達式,須要Janino jar -->
        <!-- Janino 2.6.0版本開始,除了janino.jar以外, commons-compiler.jar也須要在類路徑中 -->
        <if condition='property("system_host").contains("dev")'>
            <then>
                <appender-ref ref="stdout" />
            </then>
        </if>
        <appender-ref ref="file" />
    </root>
</configuration>

注意:logback若是配置要輸出行號,性能會明顯下降,若是不是必須,建議不要配置!

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

5、SLF4J橋接

細心的你,會發現上面代碼使用時,都使用的是private static final Logger logger = LoggerFactory.getLogger(LogPrintUtil.class)這個,其中都來自org.slf4j包,SLF4J是啥?有什麼做用呢?

SLF4J自己並不輸出日誌,最大的特點是:它能夠經過適配的方式掛接不一樣的日誌系統,屬於一個日誌接口

若是項目適配到log4j就使用log4j日誌庫進行輸出;若是適配到logback就使用logback日誌庫進行輸出;若是適配到log4j2就使用log4j2日誌庫進行輸出。

這樣最大的好處,就是當你想將項目從log4j換成log4j2的時候,只須要在項目pom.xml中進行橋接適配便可,不用修改具體須要打印日誌的代碼

6、三大主流日誌框架性能比較

介紹了這麼多,可是咱們還不知道三個日誌框架的日誌輸出性能如何,本文以10000條數據進行打印,比較log4jlog4j2logback日誌的輸出時間。

本次測試採用的是本地電腦(win7),每一個電腦的配置不同,測試的結果也不同,結果是真實的。

  • 同步輸出

圖片

  • 異步輸出

圖片

從測試結果上能夠看出:

  • 不建議生產環境進行控制檯輸出;
  • 在純文件輸出的環境下,logback的輸出優於log4j2,而log4j2要優於log4j,若是要進行生產環境的部署,建議採用logback,若是是使用log4j2,建議使用異步方式進行輸出,輸出結果基本是實時輸出;

最後須要注意的地方是:log有風險,輸出需謹慎!

因爲輸出log過程須要進行磁盤操做,且log4j爲了保證log輸出過程的線程安全性而使用同步鎖,就使得輸出log成爲很耗時的操做,因此log信息必定要言簡意賅,不要輸出一些無用的log

7、總結

本文主要圍繞項目中使用到的日誌框架進行應用介紹,限於筆者的才疏學淺,對本文內容可能還有理解不到位的地方,若有闡述不合理之處還望留言一塊兒探討。

相關文章
相關標籤/搜索