(二):集成日志框架:springboot使用logback日志框架
前言
? ? ? ?項(xiàng)目中日志系統(tǒng)是必不可少的,目前比較流行的日志框架有l(wèi)og4j、logback等,可能大家還不知道,這兩個(gè)框架的作者是同一個(gè)人,Logback旨在作為流行的log4j項(xiàng)目的后續(xù)版本,從而恢復(fù)log4j離開的位置。另外 slf4j(Simple Logging Facade for Java) 則是一個(gè)日志門面框架,提供了日志系統(tǒng)中常用的接口,logback 和 log4j 則對(duì)slf4j 進(jìn)行了實(shí)現(xiàn)。我們本文將講述如何在spring boot 中應(yīng)用 logback+slf4j實(shí)現(xiàn)日志的記錄。
為什么使用logback
Logback 是log4j 框架的作者開發(fā)的新一代日志框架,它效率更高、能夠適應(yīng)諸多的運(yùn)行環(huán)境,同時(shí)天然支持SLF4J
Logback的定制性更加靈活,同時(shí)也是spring boot的內(nèi)置日志框架
開始使用
一:添加依賴:maven依賴中添加了spring-boot-starter-logging
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId> </dependency>
但是呢,實(shí)際開發(fā)中我們不需要直接添加該依賴,你會(huì)發(fā)現(xiàn)spring-boot-starter其中包含了 spring-boot-starter-logging,該依賴內(nèi)容就是 Spring Boot 默認(rèn)的日志框架 Logback+SLF4J。而 spring-boot-starter-web 包含了spring-boot-starte,所以我們只需要引入web組件即可:
二:默認(rèn)配置:默認(rèn)情況下Spring Boot將日志輸出到控制臺(tái),不會(huì)寫到日志文件。如果要編寫除控制臺(tái)輸出之外的日志文件,則需在application.properties中設(shè)置logging.file或logging.path屬性
- logging.file,設(shè)置文件,可以是絕對(duì)路徑,也可以是相對(duì)路徑。如:logging.file=my.log
- logging.path,設(shè)置目錄,會(huì)在該目錄下創(chuàng)建spring.log文件,并寫入日志內(nèi)容,如:logging.path=/var/log
注:二者不能同時(shí)使用,如若同時(shí)使用,則只有l(wèi)ogging.file生效,可以看到這種方式配置簡單,但是能實(shí)現(xiàn)的功能也非常有限,如果想要更復(fù)雜的需求,就需要下面的定制化配置了。
三:logback-spring.xml詳解
Spring Boot官方推薦優(yōu)先使用帶有-spring的文件名作為你的日志配置(如使用logback-spring.xml,而不是logback.xml),命名為logback-spring.xml的日志配置文件,將xml放至 src/main/resource下面。
也可以使用自定義的名稱,比如logback-config.xml,只需要在application.properties文件中使用logging.config=classpath:logback-config.xml指定即可。
在講解 log'back-spring.xml之前我們先來了解三個(gè)單詞:Logger, Appenders and Layouts(記錄器、附加器、布局):Logback基于三個(gè)主要類:Logger,Appender和Layout。 這三種類型的組件協(xié)同工作,使開發(fā)人員能夠根據(jù)消息類型和級(jí)別記錄消息,并在運(yùn)行時(shí)控制這些消息的格式以及報(bào)告的位置。首先給出一個(gè)基本的xml配置如下:
<configuration><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><!-- encoders are assigned the typech.qos.logback.classic.encoder.PatternLayoutEncoder by default --><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><logger name="chapters.configuration" level="INFO"/><!-- Strictly speaking, the level attribute is not necessary since --><!-- the level of the root level is set to DEBUG by default. ? ? ? --><root level="DEBUG"> ? ? ? ? ?<appender-ref ref="STDOUT" /></root> ?</configuration>
3.1:<configuration>元素
logback.xml配置文件的基本結(jié)構(gòu)可以描述為<configuration>元素,包含零個(gè)或多個(gè)<appender>元素,后跟零個(gè)或多個(gè)<logger>元素,后跟最多一個(gè)<root>元素(也可以沒有)。下圖說明了這種基本結(jié)構(gòu):
3.2:<logger>元素
<logger>元素只接受一個(gè)必需的name屬性,一個(gè)可選的level屬性和一個(gè)可選的additivity屬性,允許值為true或false。 level屬性的值允許一個(gè)不區(qū)分大小寫的字符串值TRACE,DEBUG,INFO,WARN,ERROR,ALL或OFF。特殊于大小寫不敏感的值INHERITED或其同義詞NULL將強(qiáng)制記錄器的級(jí)別從層次結(jié)構(gòu)中的較高級(jí)別繼承,<logger>元素可以包含零個(gè)或多個(gè)<appender-ref>元素; 這樣引用的每個(gè)appender都被添加到指定的logger中,(注:additivity屬性下面詳說),logger元素級(jí)別具有繼承性。
例1:示例中,僅為根記錄器分配了級(jí)別。 此級(jí)別值DEBUG由其他記錄器X,X.Y和X.Y.Z繼承
| root | DEBUG | DEBUG |
| X | none | DEBUG |
| X.Y | none | DEBUG |
| X.Y.Z | none | DEBUG |
例2:所有記錄器都有一個(gè)指定的級(jí)別值。 級(jí)別繼承不起作用
| root | ERROR | ERROR |
| X | INFO | INFO |
| X.Y | DEBUG | DEBUG |
| X.Y.Z | WARN | WARN |
例3:記錄器root,X和X.Y.Z分別被分配了DEBUG,INFO和ERROR級(jí)別。 Logger X.Y從其父X繼承其級(jí)別值。
| root | DEBUG | DEBUG |
| X | INFO | INFO |
| X.Y | none | INFO |
| X.Y.Z | ERROR | ERROR |
例4:在示例4中,記錄器root和X分別被分配了DEBUG和INFO級(jí)別。 記錄器X.Y和X.Y.Z從其最近的父X繼承其級(jí)別值,該父級(jí)具有指定的級(jí)別。
| root | DEBUG | DEBUG |
| X | INFO | INFO |
| X.Y | none | INFO |
| X.Y.Z | none | INFO |
3.3:<root>元素
<root>元素配置根記錄器。 它支持單個(gè)屬性,即level屬性。 它不允許任何其他屬性,因?yàn)閍dditivity標(biāo)志不適用于根記錄器。 此外,由于根記錄器已被命名為“ROOT”,因此它也不允許使用name屬性。 level屬性的值可以是不區(qū)分大小寫的字符串TRACE,DEBUG,INFO,WARN,ERROR,ALL或OFF之一<root>元素可以包含零個(gè)或多個(gè)<appender-ref>元素; 這樣引用的每個(gè)appender都被添加到根記錄器中(注:additivity屬性下面詳說)。
3.4:<appender>元素
appender使用<appender>元素配置,該元素采用兩個(gè)必需屬性name和class。 name屬性指定appender的名稱,而class屬性指定要實(shí)例化的appender類的完全限定名稱。 <appender>元素可以包含零個(gè)或一個(gè)<layout>元素,零個(gè)或多個(gè)<encoder>元素以及零個(gè)或多個(gè)<filter>元素,下圖說明了常見的結(jié)構(gòu):
重要:在logback中,輸出目標(biāo)稱為appender,addAppender方法將appender添加到給定的記錄器logger。給定記錄器的每個(gè)啟用的日志記錄請(qǐng)求都將轉(zhuǎn)發(fā)到該記錄器中的所有appender以及層次結(jié)構(gòu)中較高的appender。換句話說,appender是從記錄器層次結(jié)構(gòu)中附加地繼承的。例如,如果將控制臺(tái)appender添加到根記錄器,則所有啟用的日志記錄請(qǐng)求將至少在控制臺(tái)上打印。如果另外將文件追加器添加到記錄器(例如L),則對(duì)L和L的子項(xiàng)啟用的記錄請(qǐng)求將打印在文件和控制臺(tái)上。通過將記錄器的additivity標(biāo)志設(shè)置為false,可以覆蓋此默認(rèn)行為,以便不再添加appender累積。
Appender是一個(gè)接口,它有許多子接口和實(shí)現(xiàn)類,具體如下圖所示:
其中最重要的兩個(gè)Appender為:ConsoleAppender 、RollingFileAppender。
3.4.1:ConsoleAppender
ConsoleAppender,如名稱所示,將日志輸出到控制臺(tái)上。
3.4.2:RollingFileAppender
RollingFileAppender,是FileAppender的一個(gè)子類,擴(kuò)展了FileAppender,具有翻轉(zhuǎn)日志文件的功能。 例如,RollingFileAppender 可以記錄到名為log.txt文件的文件,并且一旦滿足某個(gè)條件,就將其日志記錄目標(biāo)更改為另一個(gè)文件。
有兩個(gè)與RollingFileAppender交互的重要子組件。 第一個(gè)RollingFileAppender子組件,即 RollingPolicy 負(fù)責(zé)執(zhí)行翻轉(zhuǎn)所需的操作。 RollingFileAppender的第二個(gè)子組件,即 TriggeringPolicy 將確定是否以及何時(shí)發(fā)生翻轉(zhuǎn)。 因此,RollingPolicy 負(fù)責(zé)什么和TriggeringPolicy 負(fù)責(zé)什么時(shí)候。
作為任何用途,RollingFileAppender 必須同時(shí)設(shè)置 RollingPolicy 和 TriggeringPolicy。 但是,如果其 RollingPolicy 也實(shí)現(xiàn)了TriggeringPolicy 接口,則只需要顯式指定前者。
3.4.3:滾動(dòng)策略
TimeBasedRollingPolicy:可能是最受歡迎的滾動(dòng)策略。 它根據(jù)時(shí)間定義翻轉(zhuǎn)策略,例如按天或按月。 TimeBasedRollingPolicy承擔(dān)滾動(dòng)和觸發(fā)所述翻轉(zhuǎn)的責(zé)任。 實(shí)際上,TimeBasedTriggeringPolicy實(shí)現(xiàn)了RollingPolicy和TriggeringPolicy接口。
SizeAndTimeBasedRollingPolicy:有時(shí)您可能希望按日期歸檔文件,但同時(shí)限制每個(gè)日志文件的大小,特別是如果后處理工具對(duì)日志文件施加大小限制。 為了滿足此要求,logback 提供了 SizeAndTimeBasedRollingPolicy ,它是TimeBasedRollingPolicy的一個(gè)子類,實(shí)現(xiàn)了基于時(shí)間和日志文件大小的翻滾策略。
3.5:<encoder>元素
?encoder中最重要就是pattern屬性,它負(fù)責(zé)控制輸出日志的格式,這里給出一個(gè)我自己寫的示例:
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) --- [%15.15(%thread)] %cyan(%-40.40(%logger{40})) : %msg%n</pattern>
使用后的輸出格式如下圖所示
其中:%d{yyyy-MM-dd HH:mm:ss.SSS}:日期
? ? ? ? ? %-5level:日志級(jí)別
? ? ? ? ? %highlight():顏色,info為藍(lán)色,warn為淺紅,error為加粗紅,debug為黑色
? ? ? ? ? %thread:打印日志的線程
? ? ? ? ? %15.15():如果記錄的線程字符長度小于15(第一個(gè))則用空格在左側(cè)補(bǔ)齊,如果字符長度大于15(第二個(gè)),則從開頭開始截?cái)喽嘤嗟淖址?
? ? ? ? ? %logger:日志輸出的類名
? ? ? ? ? %-40.40():如果記錄的logger字符長度小于40(第一個(gè))則用空格在右側(cè)補(bǔ)齊,如果字符長度大于40(第二個(gè)),則從開頭開始截?cái)喽嘤嗟淖址?/p>
? ? ? ? ?%cyan:顏色
? ? ? ? ?%msg:日志輸出內(nèi)容
? ? ? ? ?%n:換行符
3.6:<filter>元素
filter中最重要的兩個(gè)過濾器為:LevelFilter、ThresholdFilter。
LevelFilter 根據(jù)精確的級(jí)別匹配過濾事件。 如果事件的級(jí)別等于配置的級(jí)別,則篩選器接受或拒絕該事件,具體取決于onMatch和onMismatch屬性的配置。 例如下面配置將只打印INFO級(jí)別的日志,其余的全部禁止打印輸出:
<configuration><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>INFO</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><encoder><pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern></encoder></appender><root level="DEBUG"><appender-ref ref="CONSOLE" /></root> </configuration>
ThresholdFilter 過濾低于指定閾值的事件。 對(duì)于等于或高于閾值的事件,ThresholdFilter將在調(diào)用其decision()方法時(shí)響應(yīng)NEUTRAL。 但是,將拒絕級(jí)別低于閾值的事件,例如下面的配置將拒絕所有低于INFO級(jí)別的日志,只輸出INFO以及以上級(jí)別的日志:
四:詳細(xì)的logback-spring.xml示例:
以上介紹了xml中重要的幾個(gè)元素,下面將我配置的xml貼出來以供參考(實(shí)現(xiàn)了基于日期和大小翻滾的策略,以及經(jīng)INFO和ERROR日志區(qū)分輸出,還有規(guī)范日志輸出格式等):
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="true"><!-- appender是configuration的子節(jié)點(diǎn),是負(fù)責(zé)寫日志的組件。 --><!-- ConsoleAppender:把日志輸出到控制臺(tái) --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><!-- 默認(rèn)情況下,每個(gè)日志事件都會(huì)立即刷新到基礎(chǔ)輸出流。 這種默認(rèn)方法更安全,因?yàn)槿绻麘?yīng)用程序在沒有正確關(guān)閉appender的情況下退出,則日志事件不會(huì)丟失。但是,為了顯著增加日志記錄吞吐量,您可能希望將immediateFlush屬性設(shè)置為false --><!--<immediateFlush>true</immediateFlush>--><encoder><!-- %37():如果字符沒有37個(gè)字符長度,則左側(cè)用空格補(bǔ)齊 --><!-- %-37():如果字符沒有37個(gè)字符長度,則右側(cè)用空格補(bǔ)齊 --><!-- %15.15():如果記錄的線程字符長度小于15(第一個(gè))則用空格在左側(cè)補(bǔ)齊,如果字符長度大于15(第二個(gè)),則從開頭開始截?cái)喽嘤嗟淖址?--><!-- %-40.40():如果記錄的logger字符長度小于40(第一個(gè))則用空格在右側(cè)補(bǔ)齊,如果字符長度大于40(第二個(gè)),則從開頭開始截?cái)喽嘤嗟淖址?--><!-- %msg:日志打印詳情 --><!-- %n:換行符 -->? ? ? ? ? ? <!-- %highlight():轉(zhuǎn)換說明符以粗體紅色顯示其級(jí)別為ERROR的事件,紅色為WARN,BLUE為INFO,以及其他級(jí)別的默認(rèn)顏色。 --><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) --- [%15.15(%thread)] %cyan(%-40.40(%logger{40})) : %msg%n</pattern><!-- 控制臺(tái)也要使用UTF-8,不要使用GBK,否則會(huì)中文亂碼 --><charset>UTF-8</charset></encoder></appender><!-- info 日志--><!-- RollingFileAppender:滾動(dòng)記錄文件,先將日志記錄到指定文件,當(dāng)符合某個(gè)條件時(shí),將日志記錄到其他文件 --><!-- 以下的大概意思是:1.先按日期存日志,日期變了,將前一天的日志文件名重命名為XXX%日期%索引,新的日志仍然是project_info.log --><!-- ? ? ? ? ? ? 2.如果日期沒有發(fā)生變化,但是當(dāng)前日志的文件大小超過10MB時(shí),對(duì)當(dāng)前日志進(jìn)行分割 重命名--><appender name="info_log" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志文件路徑和名稱--><File>logs/project_info.log</File><!--是否追加到文件末尾,默認(rèn)為true--><append>true</append><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>DENY</onMatch><!-- 如果命中ERROR就禁止這條日志 --><onMismatch>ACCEPT</onMismatch><!-- 如果沒有命中就使用這條規(guī)則 --></filter><!--有兩個(gè)與RollingFileAppender交互的重要子組件。 第一個(gè)RollingFileAppender子組件,即RollingPolicy:負(fù)責(zé)執(zhí)行翻轉(zhuǎn)所需的操作。RollingFileAppender的第二個(gè)子組件,即TriggeringPolicy:將確定是否以及何時(shí)發(fā)生翻轉(zhuǎn)。 因此,RollingPolicy負(fù)責(zé)什么和TriggeringPolicy負(fù)責(zé)什么時(shí)候.作為任何用途,RollingFileAppender必須同時(shí)設(shè)置RollingPolicy和TriggeringPolicy,但是,如果其RollingPolicy也實(shí)現(xiàn)了TriggeringPolicy接口,則只需要顯式指定前者。--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!-- 日志文件的名字會(huì)根據(jù)fileNamePattern的值,每隔一段時(shí)間改變一次 --><!-- 文件名:logs/project_info.2017-12-05.0.log --><!-- 注意:SizeAndTimeBasedRollingPolicy中 %i和%d令牌都是強(qiáng)制性的,必須存在,要不會(huì)報(bào)錯(cuò) --><fileNamePattern>logs/project_info.%d.%i.log</fileNamePattern><!-- 每產(chǎn)生一個(gè)日志文件,該日志文件的保存期限為30天, ps:maxHistory的單位是根據(jù)fileNamePattern中的翻轉(zhuǎn)策略自動(dòng)推算出來的,例如上面選用了yyyy-MM-dd,則單位為天如果上面選用了yyyy-MM,則單位為月,另外上面的單位默認(rèn)為yyyy-MM-dd--><maxHistory>30</maxHistory><!-- 每個(gè)日志文件到10mb的時(shí)候開始切分,最多保留30天,但最大到20GB,哪怕沒到30天也要?jiǎng)h除多余的日志 --><totalSizeCap>20GB</totalSizeCap><!-- maxFileSize:這是活動(dòng)文件的大小,默認(rèn)值是10MB,測試時(shí)可改成5KB看效果 --><maxFileSize>10MB</maxFileSize></rollingPolicy><!--編碼器--><encoder><!-- pattern節(jié)點(diǎn),用來設(shè)置日志的輸入格式 ps:日志文件中沒有設(shè)置顏色,否則顏色部分會(huì)有ESC[0:39em等亂碼--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern><!-- 記錄日志的編碼:此處設(shè)置字符集 - --><charset>UTF-8</charset></encoder></appender><!-- error 日志--><!-- RollingFileAppender:滾動(dòng)記錄文件,先將日志記錄到指定文件,當(dāng)符合某個(gè)條件時(shí),將日志記錄到其他文件 --><!-- 以下的大概意思是:1.先按日期存日志,日期變了,將前一天的日志文件名重命名為XXX%日期%索引,新的日志仍然是project_error.log --><!-- ? ? ? ? ? ? 2.如果日期沒有發(fā)生變化,但是當(dāng)前日志的文件大小超過10MB時(shí),對(duì)當(dāng)前日志進(jìn)行分割 重命名--><appender name="error_log" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志文件路徑和名稱--><File>logs/project_error.log</File><!--是否追加到文件末尾,默認(rèn)為true--><append>true</append><!-- ThresholdFilter過濾低于指定閾值的事件。 對(duì)于等于或高于閾值的事件,ThresholdFilter將在調(diào)用其decision()方法時(shí)響應(yīng)NEUTRAL。 但是,將拒絕級(jí)別低于閾值的事件 --><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>ERROR</level><!-- 低于ERROR級(jí)別的日志(debug,info)將被拒絕,等于或者高于ERROR的級(jí)別將相應(yīng)NEUTRAL --></filter><!--有兩個(gè)與RollingFileAppender交互的重要子組件。 第一個(gè)RollingFileAppender子組件,即RollingPolicy:負(fù)責(zé)執(zhí)行翻轉(zhuǎn)所需的操作。RollingFileAppender的第二個(gè)子組件,即TriggeringPolicy:將確定是否以及何時(shí)發(fā)生翻轉(zhuǎn)。 因此,RollingPolicy負(fù)責(zé)什么和TriggeringPolicy負(fù)責(zé)什么時(shí)候.作為任何用途,RollingFileAppender必須同時(shí)設(shè)置RollingPolicy和TriggeringPolicy,但是,如果其RollingPolicy也實(shí)現(xiàn)了TriggeringPolicy接口,則只需要顯式指定前者。--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!-- 活動(dòng)文件的名字會(huì)根據(jù)fileNamePattern的值,每隔一段時(shí)間改變一次 --><!-- 文件名:logs/project_error.2017-12-05.0.log --><!-- 注意:SizeAndTimeBasedRollingPolicy中 %i和%d令牌都是強(qiáng)制性的,必須存在,要不會(huì)報(bào)錯(cuò) --><fileNamePattern>logs/project_error.%d.%i.log</fileNamePattern><!-- 每產(chǎn)生一個(gè)日志文件,該日志文件的保存期限為30天, ps:maxHistory的單位是根據(jù)fileNamePattern中的翻轉(zhuǎn)策略自動(dòng)推算出來的,例如上面選用了yyyy-MM-dd,則單位為天如果上面選用了yyyy-MM,則單位為月,另外上面的單位默認(rèn)為yyyy-MM-dd--><maxHistory>30</maxHistory><!-- 每個(gè)日志文件到10mb的時(shí)候開始切分,最多保留30天,但最大到20GB,哪怕沒到30天也要?jiǎng)h除多余的日志 --><totalSizeCap>20GB</totalSizeCap><!-- maxFileSize:這是活動(dòng)文件的大小,默認(rèn)值是10MB,測試時(shí)可改成5KB看效果 --><maxFileSize>10MB</maxFileSize></rollingPolicy><!--編碼器--><encoder><!-- pattern節(jié)點(diǎn),用來設(shè)置日志的輸入格式 ps:日志文件中沒有設(shè)置顏色,否則顏色部分會(huì)有ESC[0:39em等亂碼--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern><!-- 記錄日志的編碼:此處設(shè)置字符集 - --><charset>UTF-8</charset></encoder></appender><!--給定記錄器的每個(gè)啟用的日志記錄請(qǐng)求都將轉(zhuǎn)發(fā)到該記錄器中的所有appender以及層次結(jié)構(gòu)中較高的appender(不用在意level值)。換句話說,appender是從記錄器層次結(jié)構(gòu)中附加地繼承的。例如,如果將控制臺(tái)appender添加到根記錄器,則所有啟用的日志記錄請(qǐng)求將至少在控制臺(tái)上打印。如果另外將文件追加器添加到記錄器(例如L),則對(duì)L和L'子項(xiàng)啟用的記錄請(qǐng)求將打印在文件和控制臺(tái)上。通過將記錄器的additivity標(biāo)志設(shè)置為false,可以覆蓋此默認(rèn)行為,以便不再添加appender累積--><!-- configuration中最多允許一個(gè)root,別的logger如果沒有設(shè)置級(jí)別則從父級(jí)別root繼承 --><root level="INFO"><appender-ref ref="STDOUT" /></root><!-- 指定項(xiàng)目中某個(gè)包,當(dāng)有日志操作行為時(shí)的日志記錄級(jí)別 --><!-- 級(jí)別依次為【從高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE ?--><logger name="com.sailing.springbootmybatis" level="INFO"><appender-ref ref="info_log" /><appender-ref ref="error_log" /></logger><!-- 利用logback輸入mybatis的sql日志,注意:如果不加 additivity="false" 則此logger會(huì)將輸出轉(zhuǎn)發(fā)到自身以及祖先的logger中,就會(huì)出現(xiàn)日志文件中sql重復(fù)打印--><logger name="com.sailing.springbootmybatis.mapper" level="DEBUG" additivity="false"><appender-ref ref="info_log" /><appender-ref ref="error_log" /></logger><!-- additivity=false代表禁止默認(rèn)累計(jì)的行為,即com.atomikos中的日志只會(huì)記錄到日志文件中,不會(huì)輸出層次級(jí)別更高的任何appender--><logger name="com.atomikos" level="INFO" additivity="false"><appender-ref ref="info_log" /><appender-ref ref="error_log" /></logger></configuration>
五:附加內(nèi)容
5.1:這里再說下log日志輸出代碼,一般有人可能在代碼中使用如下方式輸出:
Object entry = new SomeObject();? logger.debug("The entry is " + entry);
5.2:上面看起來沒什么問題,但是會(huì)存在構(gòu)造消息參數(shù)的成本,即將entry轉(zhuǎn)換成字符串相加。并且無論是否記錄消息,都是如此,即:那怕日志級(jí)別為INFO,也會(huì)執(zhí)行括號(hào)里面的操作,但是日志不會(huì)輸出,下面是優(yōu)化后的寫法:
5.3:5.2的寫法,首先對(duì)設(shè)置的日志級(jí)別進(jìn)行了判斷,如果為debug模式,才進(jìn)行參數(shù)的構(gòu)造,對(duì)第一種寫法進(jìn)行了改善。不過還有最好的寫法,使用占位符:
只有在評(píng)估是否記錄之后,并且只有在決策是肯定的情況下,記錄器實(shí)現(xiàn)才會(huì)格式化消息并將“{}”對(duì)替換為條目的字符串值。 換句話說,當(dāng)禁用日志語句時(shí),此表單不會(huì)產(chǎn)生參數(shù)構(gòu)造的成本。
logback作者進(jìn)行測試得出:第一種和第三種寫法將產(chǎn)生完全相同的輸出。 但是,在禁用日志記錄語句的情況下,第三個(gè)變體將比第一個(gè)變體優(yōu)于至少30倍。
如果有多個(gè)參數(shù),寫法如下:
logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry); 如果需要傳遞三個(gè)或更多參數(shù),則還可以使用Object []變體:Object[] paramArray = {newVal, below, above}; logger.debug("Value {} was inserted between {} and {}.", paramArray);
5.4:記錄日志的時(shí)候我們可能需要在文件中記錄下異常的堆棧信息,經(jīng)過測試,logger.error(e) 不會(huì)打印出堆棧信息,正確的寫法是:
完~
關(guān)于集成其實(shí)java school的有篇文章是很不錯(cuò)的:
springboot配置集成log4jhttp://www.51gjie.com/javaweb/1104.html
總結(jié)
以上是生活随笔為你收集整理的(二):集成日志框架:springboot使用logback日志框架的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux系统给jvm分配来多少内存
- 下一篇: HttpClient:绕开https证书