之前在日志?聊一聊slf4j吧 這篇文章中聊了下
slf4j
。本文也從實際的例子出發,針對
logback
的日志配置進行學習。
logack 簡介
logback 官網:https://logback.qos.ch/
目前還沒有看過日志類架構的源碼,僅限于如何使用。是以就不說那些“空話”了。最直覺的認知是:
-
和logback
是一個人寫的log4j
-
預設使用的日志架構是springboot
。logback
- 三個子產品組成
- logback-core
- logback-classic
- logback-access
- 其他的關于性能,關于記憶體占用,關于測試,關于文檔詳見源碼及官網說明
logback-core
是其它子產品的基礎設施,其它子產品基于它建構,顯然,
logback-core
提供了一些關鍵的通用機制。
logback-classic
的地位和作用等同于
Log4J
,它也被認為是
Log4J
的一個改進版,并且它實作了簡單日志門面
SLF4J
;而
logback-access
主要作為一個與
Servlet
容器互動的子產品,比如說
tomcat
或者
jetty
,提供一些與
HTTP
通路相關的功能。
配置檔案詳解
這部分主要來學習下logback配置檔案的一些配置項。
configuration
先來看這張圖,這個結構就是整個logback.xml配置檔案的結構。

對應來看下配置檔案:
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<property name="glmapper-name" value="glmapper-demo" />
<contextName>${glmapper-name}</contextName>
<appender>
//xxxx
</appender>
<logger>
//xxxx
</logger>
<root>
//xxxx
</root>
</configuration>
複制
ps:想使用spring擴充profile支援,要以logback-spring.xml命名,其他如property需要改為springProperty
- scan:當此屬性設定為true時,配置檔案如果發生改變,将會被重新加載,預設值為true。
- scanPeriod:設定監測配置檔案是否有修改的時間間隔,如果沒有給出時間機關,預設機關是毫秒。當scan為true時,此屬性生效。預設的時間間隔為1分鐘。
- debug:當此屬性設定為true時,将列印出logback内部日志資訊,實時檢視logback運作狀态。預設值為false。
contextName
每個
logger
都關聯到
logger
上下文,預設上下文名稱為
“default”
。但可以使用
contextName
标簽設定成其他名字,用于區分不同應用程式的記錄
property
用來定義變量值的标簽,
property
标簽有兩個屬性,
name
和
value
;其中
name
的值是變量的名稱,
value
的值時變量定義的值。通過
property
定義的值會被插入到
logger
上下文中。定義變量後,可以使“${name}”來使用變量。如上面的
xml
所示。
logger
用來設定某一個包或者具體的某一個類的日志列印級别以及指定
appender
。
root
根logger,也是一種logger,且隻有一個level屬性
appender
負責寫日志的元件,下面會細說
filter
filter其實是appender裡面的子元素。它作為過濾器存在,執行一個過濾器會有傳回DENY,NEUTRAL,ACCEPT三個枚舉值中的一個。
- DENY:日志将立即被抛棄不再經過其他過濾器
- NEUTRAL:有序清單裡的下個過濾器過接着處理日志
- ACCEPT:日志會被立即處理,不再經過剩餘過濾器
案例分析
首先來配置一個非常簡單的檔案。這裡申請下,我使用的是
logback-spring.xml
。和
logback.xml
在
properties
上有略微差别。其他都一樣。
工程:springboot+web
先來看下項目目錄
properties中就是指定了日志的列印級别和日志的輸出位置:
#設定應用的日志級别
logging.level.com.glmapper.spring.boot=INFO
#路徑
logging.path=./logs
複制
通過控制台輸出的log
logback-spring.xml的配置如下:
<configuration>
<!-- 預設的控制台日志輸出,一般生産環境都是背景啟動,這個沒太大作用 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
複制
列印日志的controller
private static final Logger LOGGER =
LoggerFactory.getLogger(HelloController.class);
@Autowired
private TestLogService testLogService;
@GetMapping("/hello")
public String hello(){
LOGGER.info("GLMAPPER-SERVICE:info");
LOGGER.error("GLMAPPER-SERVICE:error");
testLogService.printLogToSpecialPackage();
return "hello spring boot";
}
複制
驗證結果:
01:50:39.633 INFO com.glmapper.spring.boot.controller.HelloController
- GLMAPPER-SERVICE:info
01:50:39.633 ERROR com.glmapper.spring.boot.controller.HelloController
- GLMAPPER-SERVICE:error
複制
上面的就是通過控制台列印出來的,這個時候因為我們沒有指定日志檔案的輸出,因為不會在工程目錄下生産
logs
檔案夾。
控制台不列印,直接輸出到日志檔案
先來看下配置檔案:
<configuration>
<!-- 屬性檔案:在properties檔案中找到對應的配置項 -->
<springProperty scope="context" name="logging.path" source="logging.path"/>
<springProperty scope="context" name="logging.level" source="logging.level.com.glmapper.spring.boot"/>
<!-- 預設的控制台日志輸出,一般生産環境都是背景啟動,這個沒太大作用 -->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>
</encoder>
</appender>
<appender name="GLMAPPER-LOGGERONE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<root level="info">
<appender-ref ref="GLMAPPER-LOGGERONE"/>
</root>
</configuration>
複制
這裡我們
appender-ref
指定的
appender
是
GLMAPPER-LOGGERONE
,因為之前沒有名字為
GLMAPPER-LOGGERONE
的
appender
,是以要增加一個
name
為
GLMAPPER-LOGGERONE
的
appender
。
注意上面這個配置,我們是直接接将
root
的
appender-ref
直接指定到我們的
GLMAPPER-LOGGERONE
這個appender的。是以控制台中将隻會列印出bannar之後就啥也不列印了,所有的啟動資訊都會被列印在日志檔案
glmapper-loggerone.log
中。
但是實際上我們不希望我的業務日志中會包括這些啟動資訊。是以這個時候我們就需要通過
logger
标簽來搞事情了。将上面的配置檔案進行簡單修改:
<logger name="com.glmapper.spring.boot.controller" level="${logging.level}"
additivity="false">
<appender-ref ref="GLMAPPER-LOGGERONE" />
</logger>
<root level="${logging.level}">
<appender-ref ref="STDOUT"/>
</root>
複制
讓
root
指向控制台輸出;
logger
負責列印包
com.glmapper.spring.boot.controller
下的日志。
驗證結果
還是通過我們的測試controller來列印日志為例,但是這裡不會在控制台出現日志資訊了。期望的日志檔案在
./logs/glmapper-spring-boot/glmapper-loggerone.log
。
logger和appender的關系
上面兩種是一個基本的配置方式,通過上面兩個案例,我們先來了解下
logger/appender/root
之間的關系,然後再詳細的說下
logger
和
appender
的配置細節。
在最前面介紹中提到,
root
是根
logger
,是以他兩是一回事;隻不過
root
中不能有
name
和
additivity
屬性,是有一個
level
。
appender
是一個日志列印的元件,這裡元件裡面定義了列印過濾的條件、列印輸出方式、滾動政策、編碼方式、列印格式等等。但是它僅僅是一個列印元件,如果我們不使用一個
logger
或者
root
的
appender-ref
指定某個具體的
appender
時,它就沒有什麼意義。
是以
appender
讓我們的應用知道怎麼打、列印到哪裡、列印成什麼樣;而
logger
則是告訴應用哪些可以這麼打。例如某個類下的日志可以使用這個
appender
列印或者某個包下的日志可以這麼列印。
appender 配置詳解
這裡以上面案例中的名為
GLMAPPER-LOGGERONE
的
appender
說明:
<appender name="GLMAPPER-LOGGERONE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
複制
appender
有兩個屬性
name
和
class
;
name
指定
appender
名稱,
class
指定
appender
的全限定名。上面聲明的是名為
GLMAPPER-LOGGERONE
,
class
為
ch.qos.logback.core.rolling.RollingFileAppender
的一個
appender
。
appender 的種類
- ConsoleAppender:把日志添加到控制台
- FileAppender:把日志添加到檔案
- RollingFileAppender:滾動記錄檔案,先将日志記錄到指定檔案,當符合某個條件時,将日志記錄到其他檔案。它是FileAppender的子類
append 子标簽
<append>true</append>
複制
如果是
true
,日志被追加到檔案結尾,如果是
false
,清空現存檔案,預設是
true
。
filter 子标簽
在簡介中提到了
filter
;作用就是上面說的。可以為
appender
添加一個或多個過濾器,可以用任意條件對日志進行過濾。
appender
有多個過濾器時,按照配置順序執行。
ThresholdFilter
臨界值過濾器,過濾掉低于指定臨界值的日志。當日志級别等于或高于臨界值時,過濾器傳回
NEUTRAL
;當日志級别低于臨界值時,日志會被拒絕。
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
複制
LevelFilter
級别過濾器,根據日志級别進行過濾。如果日志級别等于配置級别,過濾器會根據
onMath
(用于配置符合過濾條件的操作) 和
onMismatch
(用于配置不符合過濾條件的操作)接收或拒絕日志。
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
複制
關于
NEUTRAL
、
ACCEPT
、
DENY
見上文簡介中關于
filter
的介紹。
file 子标簽
file
标簽用于指定被寫入的檔案名,可以是相對目錄,也可以是絕對目錄,如果上級目錄不存在會自動建立,沒有預設值。
<file>
${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
</file>
複制
這個表示目前appender将會将日志寫入到
${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
這個目錄下。
rollingPolicy 子标簽
這個子标簽用來描述滾動政策的。這個隻有
appender
的
class
是
RollingFileAppender
時才需要配置。這個也會涉及檔案的移動和重命名(a.log->a.log.2018.07.22)。
TimeBasedRollingPolicy
最常用的滾動政策,它根據時間來制定滾動政策,既負責滾動也負責出發滾動。這個下面又包括了兩個屬性:
- FileNamePattern
- maxHistory
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志檔案輸出的檔案名:按天復原 daily -->
<FileNamePattern>
${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}
</FileNamePattern>
<!--日志檔案保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
複制
上面的這段配置表明每天生成一個日志檔案,儲存30天的日志檔案
FixedWindowRollingPolicy
根據固定視窗算法重命名檔案的滾動政策。
encoder 子标簽
對記錄事件進行格式化。它幹了兩件事:
- 把日志資訊轉換成位元組數組
- 把位元組數組寫入到輸出流
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}
- %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
複制
目前
encoder
隻有
PatternLayoutEncoder
一種類型。
定義一個隻列印error級别日志的appcener
<!-- 錯誤日志 appender : 按照每天生成日志檔案 -->
<appender name="ERROR-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<!-- 過濾器,隻記錄 error 級别的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>error</level>
</filter>
<!-- 日志名稱 -->
<file>${logging.path}/glmapper-spring-boot/glmapper-error.log</file>
<!-- 每天生成一個日志檔案,儲存30天的日志檔案 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志檔案輸出的檔案名:按天復原 daily -->
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-error.log.%d{yyyy-MM-dd}</FileNamePattern>
<!--日志檔案保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級别從左顯示5個字元寬度%msg:日志消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!-- 編碼 -->
<charset>UTF-8</charset>
</encoder>
</appender>
複制
定義一個輸出到控制台的appender
<!-- 預設的控制台日志輸出,一般生産環境都是背景啟動,這個沒太大作用 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>
</encoder>
</appender>
複制
logger 配置詳解
<logger name="com.glmapper.spring.boot.controller"
level="${logging.level}" additivity="false">
<appender-ref ref="GLMAPPER-LOGGERONE" />
</logger>
複制
上面的這個配置檔案描述的是:
com.glmapper.spring.boot.controller
這個包下的
${logging.level}
級别的日志将會使用
GLMAPPER-LOGGERONE
來列印。
logger
有三個屬性和一個子标簽:
- name:用來指定受此
限制的某一個包或者具體的某一個類。logger
- level:用來設定列印級别(
,TRACE
,DEBUG
,INFO
,WARN
,ERROR
和ALL
),還有一個值OFF
或者同義詞INHERITED
,代表強制執行上級的級别。如果沒有設定此屬性,那麼目前NULL
将會繼承上級的級别。logger
- addtivity:用來描述是否向上級
傳遞列印資訊。預設是logger
。true
appender-ref
則是用來指定具體
appender
的。
不同日志隔離列印案例
在前面的例子中我們有三種appender,一個是指定包限制的,一個是控制error級别的,一個是控制台的。然後這小節我們就來實作下不同日志列印到不同的log檔案中。
根據包進行日志檔案隔離
這個例子裡我們将
com.glmapper.spring.boot.controller
中的日志輸出到
glmapper-controller.log
;将
com.glmapper.spring.boot.service
中的日志輸出到
glmapper-service.log
。
<!--列印日志到glmapper-service.log的appender-->
<appender name="GLMAPPER-SERVICE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${logging.path}/glmapper-spring-boot/glmapper-service.log
</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-service.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--列印日志到glmapper-controller.log的appender-->
<appender name="GLMAPPER-CONTROLLER"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${logging.path}/glmapper-spring-boot/glmapper-controller.log
</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-controller.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--此logger限制将.controller包下的日志輸出到GLMAPPER-CONTROLLER,錯誤日志輸出到GERROR-APPENDE;GERROR-APPENDE見上面-->
<logger name="com.glmapper.spring.boot.controller" level="${logging.level}" additivity="false">
<appender-ref ref="GLMAPPER-CONTROLLER" />
<appender-ref ref="GERROR-APPENDER" />
</logger>
<!--此logger限制将.service包下的日志輸出到GLMAPPER-SERVICE,錯誤日志輸出到GERROR-APPENDE;GERROR-APPENDE見上面-->
<logger name="com.glmapper.spring.boot.service" level="${logging.level}" additivity="false">
<appender-ref ref="GLMAPPER-SERVICE" />
<appender-ref ref="GERROR-APPENDER" />
</logger>
複制
來看運作結果
1、glmaper-controller
2、glmapper-service
3、glmapper-error
滿足我們的預期,但是這裡有個小問題。在
info
日志裡出現了
error
,當然這是正常的。假如我們不想在
info
裡面出現
error
怎麼辦呢?很簡單,我們以
APPENDER-SERVICE
為例,将
filter
過濾器進行修改:
将下面的:
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
複制
修改為:
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<!-- 如果命中就禁止這條日志 -->
<onMatch>DENY</onMatch>
<!-- 如果沒有命中就使用這條規則 -->
<onMismatch>ACCEPT</onMismatch>
</filter>
複制
這裡同時要注意的是,在
logger
中
level
需要設定為
info
級别。
根據類進行日志檔案隔離
這個其實也是和上面那個差不過,隻不過粒度更細一點,一般情況下比如說我們有個定時任務類需要單獨來記錄其日志資訊,這樣我們就可以考慮使用基于類次元來限制列印。
<!--特殊功能單獨appender 例如排程類的日志-->
<appender name="SCHEDULERTASKLOCK-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>${logging.path}/glmapper-spring-boot/scheduler-task-lock.log</file>
<!-- 每天生成一個日志檔案,儲存30天的日志檔案 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志檔案輸出的檔案名:按天復原 daily -->
<FileNamePattern>${logging.path}/glmapper-spring-boot/scheduler-task-lock.log.%d{yyyy-MM-dd}</FileNamePattern>
<!--日志檔案保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級别從左顯示5個字元寬度%msg:日志消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!-- 編碼 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--這裡指定到了具體的某一個類-->
<logger name="com.glmapper.spring.boot.task.TestLogTask" level="${logging.level}" additivity="true">
<appender-ref ref="SCHEDULERTASKLOCK-APPENDER" />
<appender-ref ref="ERROR-APPENDER" />
</logger>
複制
最終
TestLogTask
中的日志将會被列印到這個自己獨立的log檔案中。如下所示:
根據自定義 logger 的 name 進行日志檔案隔離
logger
的
name
除了類、包等限制之外,當然還可以這樣來玩。。。
在進行案例之前,這裡先把前面案例中
logger
聲明的代碼貼一下,以作對比,以
TestLogTask
類中的日志為例:
private static final Logger LOGGER =
LoggerFactory.getLogger(TestLogTask.class);
複制
在
getLogger
中我們是将目前對象的
class
作為參數的,這個是為了列印時擷取其全限定名的(見下面3-)。
1-2018-07-21 11:15:42.003 [pool-1-thread-1]
2-INFO
3-com.glmapper.spring.boot.task.TestLogTask -
4-com.glmapper.spring.boot.task:info
複制
業務類定義
我們同樣是
service
包下定義一個類
TestLogNameServiceImpl
package com.glmapper.spring.boot.service;
@Service("testLogNameService")
public class TestLogNameServiceImpl implements TestLogNameService {
private static final Logger LOGGER =
LoggerFactory.getLogger("GLMAPPER-TEST-LOG");
@Override
public void print() {
LOGGER.info("GLMAPPER-TEST-LOG:this is special logger-----info");
LOGGER.error("GLMAPPER-TEST-LOG:this is special logger-------error");
}
}
複制
appender和logger配置
<appender name="ROOT-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>${logging.path}/glmapper-spring-boot/glmapper-test.log</file>
<!-- 每天生成一個日志檔案,儲存30天的日志檔案 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志檔案輸出的檔案名:按天復原 daily -->
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-test.log.%d{yyyy-MM-dd}
</FileNamePattern>
<!--日志檔案保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級别從左顯示5個字元寬度%msg:日志消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!-- 編碼 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--這裡的name和業務類中的getLogger中的字元串是一樣的-->
<logger name="GLMAPPER-TEST-LOG" level="${logging.level}" additivity="true">
<appender-ref ref="ROOT-APPENDER" />
<appender-ref ref="ERROR-APPENDER" />
</logger>
複制
我們這個預期的是
TestLogNameServiceImpl
中的日志不列印到
glmapper-service.log
中,而是列印到
glmapper-test.log
中。
1、glmapper-test.log
2、glmapper-service.log
滿足我們的預期。
如何使用logback列印mybatis的sql語句
這個還是比較坑的。為什麼。看下這個:
<settings>
<setting name="logImpl" value="slf4j" />
</settings>
複制
在
mybatis-configration.xml
中,我們通過這樣一個配置項來關聯到具體的日志元件。但是
logImpl
的實作中是沒有
logback
的。那麼怎麼辦呢?這裡隻能通過
slf4j
的方式橋接到
logback
。
然後在我們的logback-spring.xml中進行如下配置:
<!-- 将sql語句輸出到具體的日志檔案中 -->
<logger name="com.alipay.sofa.cloudplatform.common.dao" level="${logging.sql.level}" additivity="false">
<appender-ref ref="SQL-APPENDER"/>
</logger>
複制
這裡有幾個點需要注意的。首先是
${logging.sql.level}
這個必須是debug,這個是由mybatis本身實作決定的。而這裡的
name
設定的
com.alipay.sofa.cloudplatform.common.dao
值就是我們dao接口的包路徑。
網上看了一個比較典型的案例,這種方式隻能輸出到控制台,并不能将檔案輸出到日志檔案;它是根據内部的一個實作機制偷了個懶。mybatis用logback日志不顯示sql的解決辦法。
總結
本篇部落客要是整理最近工作中的一些日志配置積累,将每個細節進行總結一下,以作備忘。如果有時間的話會考慮看一個日志架構的源碼。其實我覺得還是很有必要的,日志元件畢竟是需要進行日志檔案落盤的,這個會涉及到許多的性能問題、緩沖區問題、隊列問題、當然還有一些鎖的問題、同步列印或者異步列印等問題。有興趣的小夥伴可以看看,然後分享給我們。