03.spring-boot與日志

spring-boot與日志

使用slf4j

如何讓系統(tǒng)中所有的日志都統(tǒng)一到slf4j

  1. 將系統(tǒng)中其他日志框架先排除出去馍资。
  2. 用中間包來替換原有的日志框架。
  3. 我們導(dǎo)入slf4j其他的實現(xiàn)撕捍。
spring-boot的日志依賴
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring‐boot‐starter‐logging</artifactId>
</dependency>

總結(jié):

  1. spring-boot底層選用的是slf4j+logback進行日志記錄。
  2. spring-boot把其他的日志都替換成了slf4j泣洞。
  3. 如果我們要引入其他框架忧风,需要把默認的日志依賴移除掉。
spring-boot的日志使用

導(dǎo)入slf4j的jar和logback的實現(xiàn)jar

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RunWith(SpringRunner.class)
@SpringBootTest
public class LoggerApplicationTests {

    @Test
    public void contextLoads() {

        Logger logger = LoggerFactory.getLogger(LoggerApplicationTests.class);
        logger.trace("trace");
        logger.debug("debug");
        logger.info("info");
        logger.warn("warn");
        logger.error("error");

    }

}
日志級別

spring-boot默認日志級別是info

1. trace
2. debug
3. info
4. warn
5. error
日志默認配置修改
日志輸出格式: 
    %d:表示日期時間球凰,
    %thread:表示線程名狮腿,
    %‐5level:級別從左顯示5個字符寬度
    %logger{50}:表示logger名字最長50個字符,否則按照句點分割呕诉。 
    %msg:日志消息缘厢,
    %n:是換行符
例子:
    %d{yyyy‐MM‐dd HH:mm:ss} [%thread] %-5level %logger- %msg%n

控制臺:

//修改默認日志級別,level后面跟著包名
logging.level.com.bafan.springboot.logger=trace
//修改控制臺
logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n

指定文件輸出:

在實際的項目開發(fā)中甩挫,我們習(xí)慣將日志輸出到服務(wù)器的某個文件下
  • 需要將日志的配置文件放在類路徑下(spring-boot就不使用他默認的配置了)贴硫。
  • logback.xml:直接被日志框架識別。
  • logback-spring.xml:日志框架不直接加載日志的配置項伊者,由spring-boot解析日志配置夜畴,可以使用spring-boot的高級profile功能。(推薦)删壮。(<springProfile name="dev">可以根據(jù)環(huán)境來決定功能)

spring-boot識別logback.xml文件

1--LoggingApplicationListener的initialize方法

protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {
    (new LoggingSystemProperties(environment)).apply();
    LogFile logFile = LogFile.get(environment);
    if (logFile != null) {
        logFile.applyToSystemProperties();
    }

    this.initializeEarlyLoggingLevel(environment);
    //進入
    this.initializeSystem(environment, this.loggingSystem, logFile);
    this.initializeFinalLoggingLevels(environment, this.loggingSystem);
    this.registerShutdownHookIfNecessary(environment, this.loggingSystem);
}

2--LoggingApplicationListener的initializeSystem方法

private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system, LogFile logFile) {
    LoggingInitializationContext initializationContext = new LoggingInitializationContext(environment);
    String logConfig = environment.getProperty("logging.config");
    if (this.ignoreLogConfig(logConfig)) {
        //進入
        system.initialize(initializationContext, (String)null, logFile);
    } else {
        try {
            ResourceUtils.getURL(logConfig).openStream().close();
            system.initialize(initializationContext, logConfig, logFile);
        } catch (Exception var7) {
            System.err.println("Logging system failed to initialize using configuration from '" + logConfig + "'");
            var7.printStackTrace(System.err);
            throw new IllegalStateException(var7);
        }
    }

}

3--LogbackLoggingSystem的initialize方法

public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {
    LoggerContext loggerContext = this.getLoggerContext();
    if (!this.isAlreadyInitialized(loggerContext)) {
        //調(diào)用父類的初始化方法
        super.initialize(initializationContext, configLocation, logFile);
        loggerContext.getTurboFilterList().remove(FILTER);
        this.markAsInitialized(loggerContext);
        if (StringUtils.hasText(System.getProperty("logback.configurationFile"))) {
            this.getLogger(LogbackLoggingSystem.class.getName()).warn("Ignoring 'logback.configurationFile' system property. Please use 'logging.config' instead.");
        }

    }
}

4--AbstractLoggingSystem的initialize方法

public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {
    if (StringUtils.hasLength(configLocation)) {
        this.initializeWithSpecificConfig(initializationContext, configLocation, logFile);
    } else {
        //進入
        this.initializeWithConventions(initializationContext, logFile);
    }
}

5--AbstractLoggingSystem的initializeWithConventions方法

private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile) {
    //查找自己的配置(logback.xml)
    String config = this.getSelfInitializationConfig();
    if (config != null && logFile == null) {
        this.reinitialize(initializationContext);    
    } else { //如果沒有找到贪绘,就去找spring的文件
        if (config == null) {
            //查找spring的配置(logback-spring.xml)
            config = this.getSpringInitializationConfig();
        }

        if (config != null) {
            this.loadConfiguration(initializationContext, config, logFile);
        } else { //如果都沒有找到,只使用properties默認的配置
            this.loadDefaults(initializationContext, logFile);
        }
    }
}

6--AbstractLoggingSystem的getSelfInitializationConfig方法央碟,執(zhí)行結(jié)束后到7

protected String getSelfInitializationConfig() {
    //獲取spring-boot標準的配置
    return this.findConfig(this.getStandardConfigLocations());
}
protected String[] getStandardConfigLocations() {
    return new String[]{"logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml"};
}

7--AbstractLoggingSystem的findConfig方法税灌,執(zhí)行結(jié)束后到5

private String findConfig(String[] locations) {
    String[] var2 = locations;
    int var3 = locations.length;

    //如果能夠找到配置文件的位置均函,則返回配置文件位置,否則返回null
    for(int var4 = 0; var4 < var3; ++var4) {
        String location = var2[var4];
        ClassPathResource resource = new ClassPathResource(location, this.classLoader);
        if (resource.exists()) {
            return "classpath:" + location;
        }
    }

    return null;
}

8--AbstractLoggingSystem的getSpringConfigLocations方法菱涤,執(zhí)行結(jié)束后到7

protected String[] getSpringConfigLocations() {   
    String[] locations = this.getStandardConfigLocations();

    for(int i = 0; i < locations.length; ++i) {
        //加上-spring后綴再在跟路徑下查找
        String extension = StringUtils.getFilenameExtension(locations[i]);
        locations[i] = locations[i].substring(0, locations[i].length() - extension.length() - 1) + "-spring." + extension;
    }

    return locations;
}

logback常用配置

1--根節(jié)點configuration

  • 通常不加任何屬性苞也。

2--configuration的子節(jié)點

2.1 property
//用來定義變量
<property name="FILE_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %c{35} %M %L - %msg%n"/>
...
<encoder>
    <pattern>${FILE_PATTERN}</pattern>
</encoder>
2.2 logger
  • name:用來指定受此logger約束的某一個包或者具體的某一個類。
  • level:用來打印日志級別粘秆。(root<append<logger)
  • additivity:是否向上級傳遞打印信息如迟,默認是true,項目中都用false
<logger name="com.mogujie.raptor" level="@root.log.level@" additivity="false">
    <appender-ref ref="RAPTOR_FILE"/>
</logger>
2.3 root
  • 也屬于logger標簽攻走,只有一個屬性殷勘,定義日志級別,默認是全路徑昔搂。
<root level="INFO">
    <appender-ref ref="STDOUT" />
    <appender-ref ref="FILE" />
</root>

3--appender和它的子節(jié)點

  • appender是configuration的子節(jié)點玲销。
  • name:指定appender名稱,class指定appender的全限名摘符。
3.1 ConsoleAppender
  • 控制臺日志
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>${CONSOLE_LOG_PATTERN}</pattern>
    </encoder>
</appender>
3.2 RollingFileAppender
滾動日志文件:先將日志記錄到指定文件贤斜,當(dāng)符合某個條件的時候,將日志記錄到 其它文件逛裤。FileAppender沒有滾動功能瘩绒,要么追加要么覆蓋,項目中幾乎不用带族。
  • file:寫入文件的名字草讶。
  • append:默認是true、追加炉菲;false是覆蓋堕战。
  • encoder:對記錄事件進行格式化。一是把日志信息轉(zhuǎn)成字節(jié)數(shù)組拍霜,二是把字節(jié)數(shù)組寫入輸出流嘱丢。
  • rollingPolicy:發(fā)生滾動時,涉及文件移動和重命名祠饺。
rollingPolicy:
  • TimeBasedRollingPolicy:最常用的滾動方式越驻,根據(jù)時間制定滾動策略,既負責(zé)滾動道偷,也負責(zé)觸發(fā)滾動缀旁。
  1. fileNamePattern:包含文件名及“%d”轉(zhuǎn)換符。
  2. maxHistory:保留最大時間勺鸦,根據(jù)fileNamePattern的時間決定單位是年月日并巍。
  3. timeBasedFileNamingAndTriggeringPolicy:當(dāng)文件大小超過多少時觸發(fā)滾動,里面配置maxFileSize换途,例如500MB懊渡。
<appender name="errorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <encoder>
        <pattern>${FILE_PATTERN}</pattern>
    </encoder>
    <Encoding>UTF-8</Encoding>
    <file>${CATALINA_APPLOG}/finance_mall_error.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${CATALINA_APPLOG}/finance_mall_error_%d{yyyy_MM_dd}-%i.log</fileNamePattern>
        <MaxHistory>10</MaxHistory>
        <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <maxFileSize>500MB</maxFileSize>
        </timeBasedFileNamingAndTriggeringPolicy>
    </rollingPolicy>
</appender>
4. filter
屬于appender下的標簽刽射,一般用于日志級別過濾
  • level:日志級別
  • onMatch:如果匹配上,接受(ACCEPT)
  • onMismatch:如果沒有匹配上剃执,拒絕(DENY)
<filter class="ch.qos.logback.classic.filter.LevelFilter"> 
  <level>INFO</level> 
  <onMatch>ACCEPT</onMatch> 
  <onMismatch>DENY</onMismatch> 
</filter> 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末誓禁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子肾档,更是在濱河造成了極大的恐慌摹恰,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怒见,死亡現(xiàn)場離奇詭異俗慈,居然都是意外死亡,警方通過查閱死者的電腦和手機速种,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來低千,“玉大人配阵,你說我怎么就攤上這事∈狙” “怎么了棋傍?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長难审。 經(jīng)常有香客問我瘫拣,道長,這世上最難降的妖魔是什么告喊? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任麸拄,我火速辦了婚禮,結(jié)果婚禮上黔姜,老公的妹妹穿的比我還像新娘拢切。我一直安慰自己,他們只是感情好秆吵,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布淮椰。 她就那樣靜靜地躺著,像睡著了一般纳寂。 火紅的嫁衣襯著肌膚如雪主穗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天毙芜,我揣著相機與錄音忽媒,去河邊找鬼。 笑死腋粥,一個胖子當(dāng)著我的面吹牛猾浦,可吹牛的內(nèi)容都是我干的陆错。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼金赦,長吁一口氣:“原來是場噩夢啊……” “哼音瓷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起夹抗,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤绳慎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后漠烧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杏愤,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年已脓,在試婚紗的時候發(fā)現(xiàn)自己被綠了珊楼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡度液,死狀恐怖厕宗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情堕担,我是刑警寧澤已慢,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站霹购,受9級特大地震影響佑惠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜齐疙,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一膜楷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贞奋,春花似錦把将、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至催训,卻和暖如春洽议,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背漫拭。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工亚兄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人采驻。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓审胚,卻偏偏與公主長得像匈勋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子膳叨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359