1. 程式人生 > >日誌:slf4j+logback 的配置與使用

日誌:slf4j+logback 的配置與使用

1. 常用日誌元件和選擇

java開發日誌處理是發現和除錯bug所 必不可少的,那麼現在企業中常用的日誌元件有哪些呢,JCL 、 JUL、  SLF4j、Log4j、  Log4j2 、 Logback、 jboss-loggin 等,一般日誌是配套出現的,一般是由  一個日誌門面 和 一個日誌實現 配套使用, 那麼 組成以下結構 日誌門面 日誌實現     JCL      log4j   SLF4j    log4j2        jboss-loggin  logback       JUL 那麼,下面開始 一個個排除 JUL:實現簡陋,很多地方受到開發者的吐槽,所以 首先排除 jboss-loggin:自誕生之初,就不是為了服務大眾,不受到什麼青睞,所以 也排除 log4j:log4j雖然聲名顯赫,但是在這裡 首先要知道一點  slf4j 、log4j、logback 這三個框架都是同一個作者ceki 開發的,作者說 log4j 太爛,不想修改了,因此開發了 升級版的 log4j,也就是 logback ,因此在這裡 我們劃掉 log4j log4j2:log4j2不是log4j的升級版,而是apache開發的,log4j2 該框架很優秀,正是因為太優秀,設計時與 部分框架對其支援的程度有限,不一定會什麼時候踩坑,而log4j2在設計時的效能是優於logback的,但是 99%的開發者不會有機會體會到這種差距,因為  logback也很優秀,足夠我們日常開發,所以我們劃掉 log4j2 JCL:劃掉JCL 主要是因為 日誌實現上我們選擇了 logback,而 logback和slf4j 畢竟是同一個作者寫的,親生的,合得來,而且在springboot 中 ,也是使用的  slf4j + logback,所以我們劃掉了 JCL 因此,最後剩下的就是我們 這篇部落格的 內容了 ,如何配置和使用  SLF4j + logback

2. 日誌的使用

2.1 在這裡我們新建一個springboot專案做測試 2.2 建立一個測試類,內容如下:
package com.lonely;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * Created by 15072 on 2018/1/6.
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class LoggerTest {

    private static Logger logger = LoggerFactory.getLogger(LoggerTest.class);

    @Test
    public void testLogger(){
        logger.debug("debug:....");
        logger.info("info...");
        logger.error("error...");
    }

}
在這裡 ,我們需要在每個類中 建立一個 Logger物件,並且使用 當前類的類名來建立,那麼 這個類名存在的意義在哪裡?我們可以先執行 第一個測試,看下結果

由上圖可知,我們的類名在 日誌中 是為了方便我們找到異常是在哪個類中,進行鎖定,不信的話,我們可以在新建一個測試類, LoggerTest2,裡面什麼都不寫, 然後將 LoggerFactory.getLogger(LoggerTest2.class); ,我們可以在測試一次,看看結果
因此,使用類名建立的logger 的作用就是在這裡,但是如果我們需要在每個類中都這樣的建立一個logger物件,不方便,因此可以通過 一個註解來幫我們實現 那就是  @Slf4j ,該註解就可以幫我們自動建立一個 log物件 但是 如果使用 @Slf4j 註解 需要兩點, 2.新增 lombok的依賴

測試一下,編寫測試方法
@Test
    public void testSl4j(){
        log.debug("sl4j.debug...");
        log.info("sl4j.info");
        log.error("sl4j.error");
    }

這裡的日誌輸出格式 是預設的,我們可以通過的教程 來配置 日誌輸出配置

3. 日誌的配置

日誌可以通過兩種方法配置,一種是  application.yml配置,一種是  lobback-spring.xml配置 3.1 application.yml配置,這種配置方法 配置項較少,一般有以下屬性配置 1. 配置輸出格式 為  時間  -  訊息  換行
logging:
  pattern:
    console: "%d - %msg%n"

2. 配置日誌輸出位置 比如磁碟 e盤
logging:
  pattern:
    console: "%d - %msg%n"
  path: e:/
執行後,我們可以看到 在 e盤下生成了一個檔案  spring.log  這檔案是spring生成

3. 配置日誌輸出檔案 ,這樣可以指定日誌輸出到哪個位置
logging:
  pattern:
    console: "%d - %msg%n"
  path: e:/
  file: e:/sell.log
我們可以看到 在e盤下生成了以下檔案
這裡注意:我們可以配置日誌儲存位置,以及具體輸出的檔案,如果同時配置的話,會使用我們指定的file為主,可以測
試,看e盤下具體生成什麼檔案 4. 配置日誌 輸出級別 日誌一般主要看重的有5個級別,優先順序如 DEBUG<INFO<WARN<ERROR<FATAL等,而springboot預設配置 是 INFO級別,所以 我們測試程式碼中寫了三行,在結果中我們只看到了 info 和 error的 因為 debug優先順序比info低,所以我們 看不到。那麼我們配置一下格式 logging.level.包名或類名: 級別 即可, 舉例如下
logging:
  pattern:
    console: "%d - %msg%n"
  #path: e:/
  file: e:/sell.log
  level:
    #這裡可以是包名也可以是類名
    com.lonely: debug
執行後,我們可以看到 原來只能看到 info 和 error 的,現在的debug也可以看到

3.2 lobback-spring.xml 配置
1. 我們先把 application.yml的關於日誌的註釋掉,新建一個檔案  logback-spring.xml,為什麼要取這個名字呢,Spring Boot官方推薦優先使用帶有-spring的檔名作為你的日誌配置(如使用logback-spring.xml,而不是logback.xml),如果我們想自定義名字,也可以,可以在 application.yml中通過  logging.config=classpath:/xxx.xml等方式配置。 2.  注意幾個 xml節點的含義 appender:配置項,規則,通過這個節點內容配置,我們可以配置輸出位置(控制檯,檔案),輸出格式等 root:根節點,表明整個專案基本的日誌級別,裡面可以應用多個appender規則      demo如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d -- %msg%n</pattern>
        </layout>
    </appender>

    <root level="info">
        <appender-ref ref="consoleLog" />
    </root>
</configuration>
在上面的 logback-spring.xml中,appender配置了一個規則, ConsoleAppender表明日誌輸出到控制檯,layout表明輸出格式,root節點配置表明該專案基礎的日誌級別為info,引入 控制檯輸出的規則,那麼我們執行看結果
從結果上來看,配置的是 info級別,所以 debug的沒有輸出,現在如果我想把日誌輸出到檔案怎麼處理呢,可以使用如下配置,新增一個 appender規則,由於日誌可能比較多,一般是按照日期來輸出日誌,因此如下配置了每天一個日誌到指定位置
<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d -- %msg%n</pattern>
        </layout>
    </appender>

    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d -- %msg%n</pattern>
        </encoder>
        <!--滾動策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--路徑-->
            <fileNamePattern>e:/info-%d.log</fileNamePattern>
        </rollingPolicy>
    </appender>

    <root level="info">
        <appender-ref ref="consoleLog" />
        <appender-ref ref="fileInfoLog"/>
    </root>
</configuration>
3. 如果我們想 把 info 的日誌 和  error的日誌區分到兩個檔案放置,該怎麼寫呢? 我們現在 在新建一個規則,結構如上圖,只是在裡面添加了一個過濾器,使用的是範圍過濾,也就是攔截Error級別的資訊,demo如下
<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d -- %msg%n</pattern>
        </layout>
    </appender>

    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d -- %msg%n</pattern>
        </encoder>
        <!--滾動策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--路徑-->
            <fileNamePattern>e:/info-%d.log</fileNamePattern>
        </rollingPolicy>
    </appender>

    <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--新增 範圍 過濾-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>%d -- %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>e:/error-%d.log</fileNamePattern>
        </rollingPolicy>
    </appender>

    <root level="info">
        <appender-ref ref="consoleLog" />
        <appender-ref ref="fileInfoLog"/>
        <appender-ref ref="fileErrorLog"/>
    </root>
</configuration>
執行後,我們可以在 e盤下的 error.log中看到 裡面只有一條記錄,關於error的記錄,但是我們在info的那個檔案中,依舊有info和error的資訊,那麼如果將info提取出來呢? 能不能也想這樣新增一個過濾器呢,測試一下,經過測試我們發現沒有作用,因為攔截info,error還是會顯示,因為error的優先順序高,那麼我們可以利用如下方法來處理,demo如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d -- %msg%n</pattern>
        </layout>
    </appender>

    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!--要攔截的日誌級別-->
            <level>ERROR</level>
            <!--如果匹配,則禁止-->
            <onMatch>DENY</onMatch>
            <!--如果不匹配,則允許記錄-->
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <encoder>
            <pattern>%d -- %msg%n</pattern>
        </encoder>
        <!--滾動策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--路徑-->
            <fileNamePattern>e:/info-%d.log</fileNamePattern>
        </rollingPolicy>
    </appender>

    <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--新增 範圍 過濾-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>%d -- %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>e:/error-%d.log</fileNamePattern>
        </rollingPolicy>
    </appender>

    <root level="info">
        <appender-ref ref="consoleLog" />
        <appender-ref ref="fileInfoLog"/>
        <appender-ref ref="fileErrorLog"/>
    </root>
</configuration>
執行後,發現確實實現了  info 和 error的日誌分開,但是 在上圖例子中,雖然我們排除了 error,但是除開info,如果我們還有 warn級別的日誌資訊,還是會輸出在 info.log檔案中,因為warn優先順序比info高,但是我們只是攔截了error而已。 以上就是 關於  slf4j日誌的總結,邊學邊敲邊分享~