logback中logger詳解


前言

logback實踐筆記

​ 上一篇主要對root進行了實踐總結,現在基於上一篇中的springboot代碼環境對logback.xml中的logger來進行實踐和自己遇到的坑。

logger簡介

​ 日志屬性,可以根據logger中的name屬性指定某個文件或者文件夾輸出的日志級別,並通過appender-ref指定日志的輸出格式。還有一個additivity屬性,如果設置為false的話就不會向上傳遞。

上代碼

logback.xml:

<?xml version="1.0" encoding="utf-8" ?>
<configuration debug="true" scan="true" scanPeriod="60 seconds">
    <appender name="logger_stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{YYYY-MM-dd HH:mm:ss} | %-5level | %thread | %logger - %msg%n</Pattern>
        </encoder>
    </appender>
	<!-- name=指定打印日志文件級別 level=日志級別 additivity=是否想向上傳遞 先不加上 additivity=false 屬性 -->
    <logger name="com.example.logback.logger" level="info">
      	<!-- 指定輸出的appender -->
        <appender-ref ref="logger_stdout"/>
    </logger>
</configuration>

測試代碼:

package com.example.logback.logger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @ClassName LoggerTest
 * @Description TODO
 * @Author ouyangkang
 * @Date 2019-01-07 17:04
 **/
@Component
public class LoggerTest {

    private final Logger logger = LoggerFactory.getLogger("測試");

    public void loggerTest() {
        logger.info("info=====>");
        logger.error("error====》");
        logger.debug("debug=====》");
    }
}

單元測試代碼:

package com.example.logback;

import com.example.logback.logger.LoggerTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

@RunWith(SpringRunner.class)
@SpringBootTest
public class LogbackApplicationTests {
	@Resource
	private LoggerTest loggerTest;
	@Test
	public void loggerTest(){
		loggerTest.loggerTest();
	}

}

輸出結果如下,圖一

圖一

看到了沒有,並沒有任何的輸出。

分析

​ 自己看到上面輸出的結果也是很懵逼的,仔細查看了logback.xml中的代碼,logger中的name指定的是自己測試代碼的包啊,日志級別是info。怎么就啥都沒輸出啊。appender中的配置也沒錯啊。當初自己是找了好久的錯誤都沒有找出來。

測試代碼

​ 首先查看自己寫的測試代碼,自己對 private final Logger logger = LoggerFactory.getLogger("測試");這行代碼產生了懷疑,這個logger形參指定的是哪一個日志框架中的對象。於是自己修改上面的測試代碼如下

public class LoggerTest {
    public void loggerTest() {
    	Logger logger = LoggerFactory.getLogger("測試");
        logger.info("info=====>");
        logger.error("error====》");
        logger.debug("debug=====》");
    }
}

對logger logger = LoggerFactory.getLogger("測試"); 這行代碼進行debug。進入了,如圖二

圖二

​ getLogger方法是slf4j中獲取logger工廠,查看getILoggerFactory()方法,發現其實他就是獲取一個具體的loggerFactory工廠,看過抽象工廠設計模式的應該就知道了。這里由於我們是新建了logback.xml,那么返回的工廠類其實就是logback-classic中的LoggerContext。然后調用getLogger方法創建一個Logger對象。發現返回的Logger對象如下 圖三

圖三

此時我們繼續跟進logger.info。找到最關鍵的代碼,如圖四

圖四

​ 該關鍵代碼在logback-classic中的Logger類中,根據這個callAppenders方法名可以知道這就是打印日志的關鍵方法,繼續跟進,查看callAppenders方法。如圖五

圖五

這個划重點了,仔細看,這個for循環中,可以看出來257行就是打印這個日志的代碼了。但是這個Logger l = this; 這個代碼是關鍵。這個this就是對象就是我們根據LoggerFactory.getLogger("測試")獲取到的。繼續跟進appendLoopOnAppenders方法。如圖六

圖六

發現是aai來打印這行日志,那么aii是怎么打印這行日志的呢,這個就要回到一開始logback.xml配置的地方了,自己配置了測試代碼下的日志輸出格式,但是沒有配置一個logger.name 叫做”測試“的包下面的日志輸出格式啊。於是自己修改logback.xml中的代碼如下

<?xml version="1.0" encoding="utf-8" ?>
<configuration debug="true" scan="true" scanPeriod="60 seconds">
    <appender name="logger_stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{YYYY-MM-dd HH:mm:ss} | %-5level | %thread | %logger - %msg%n</Pattern>
        </encoder>
    </appender>
	<!-- name=指定打印日志文件級別 level=日志級別 additivity=是否想向上傳遞 先不加上 additivity=false 屬性 -->
    <logger name="測試" level="info">
      	<!-- 指定輸出的appender -->
        <appender-ref ref="logger_stdout"/>
    </logger>
</configuration>

運行單元測試,得出結果如下圖七

圖七

有了日志輸出。

思考

​ 我看公司代碼一般獲取日志對象都是 private final Logger logger = LoggerFactory.getLogger(this.getClass()); 然后logback.xml中的logger屬性中name都是指定某一包名。其實這里自己跟代碼跟了挺久了其中在圖五中那個for循環就是一直向上查找,logback.xml是否設置了有該包下的日志輸出格式。如果查找到有該輸出格式就輸出,並查看logback.xml中logger中你是否設置了additivity。不是這就是默認true,繼續向上查找是否還有不同的輸出格式。如果設置為false,就結束。

我舉一個例子吧這樣就很好理解了

logback.xml代碼如下

<?xml version="1.0" encoding="utf-8" ?>
<!-- debug=是否打印logback內部日志 scan=是否重新加載  scanPeriod=多久掃描一次 -->
<configuration debug="true" scan="true" scanPeriod="60 seconds">
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{YYYY年MM月dd日 HH:mm:ss} | %-5level | %thread | %logger - %msg%n</Pattern>
        </encoder>
    </appender>

    <appender name="logger_stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{YYYY-MM-dd HH:mm:ss} | %-5level | %thread | %logger - %msg%n</Pattern>
        </encoder>
    </appender>

    <!-- 指定name 在該aa.bb.cc 下的日志輸出格式 這個就是在aa.bb.cc.dd 上的日志輸出格式-->
    <logger name="aa.bb.cc" level="info">
        <!-- 指定輸出的appender -->
        <appender-ref ref="logger_stdout"/>
    </logger>
    <!-- 指定name 在該aa.bb.cc.dd 下的日志輸出格式 additivity 默認為true 可以向上傳遞-->
    <logger name="aa.bb.cc.dd" level="info" >
        <appender-ref ref="stdout"/>
    </logger>
</configuration>

測試代碼如下

package com.example.logback.logger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @ClassName LoggerTest
 * @Description TODO
 * @Author ouyangkang
 * @Date 2019-01-07 17:04
 **/
@Component
public class LoggerTest {
    private final Logger logger = LoggerFactory.getLogger("aa.bb.cc.dd.ee");
    public void loggerTest() {
        logger.info("info=====>");
        logger.error("error====》");
        logger.debug("debug=====》");
    }
}

單元測試代碼如 上代碼里面的單元測試代碼一樣。

得到結果如下:

圖八

總結

​ LoggerFactory.getLogger(name),其中name對應着logback.xml中logger屬性中name=對應的子包,當然你也可以設置一樣的。logger中的additivity設置為false是代表該logger日志打印不向上傳遞, appender-ref指定的日志輸出格式。

​ 下一篇把logback.xml中的appender屬性介紹一下並進行實踐。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM