根標(biāo)簽 configuration
屬性
<configuration scan="true" scanPeriod="120 seconds" debug="false">
<!-- ... -->
</configuration>
scan
當(dāng)此屬性設(shè)置為true時,配置文件如果發(fā)生改變,將會被重新加載,默認(rèn)值為true莺葫。
scanPeriod
設(shè)置監(jiān)測配置文件是否有修改的時間間隔,如果沒有給出時間單位枪眉,默認(rèn)單位是毫秒徙融。當(dāng)scan為true時,此屬性生效瑰谜。默認(rèn)的時間間隔為1分鐘欺冀。
debug
當(dāng)此屬性設(shè)置為true時,將打印出logback內(nèi)部日志信息萨脑,實時查看logback運行狀態(tài)隐轩。默認(rèn)值為false
子節(jié)點
上下文名稱 contextName
默認(rèn)為default,用于區(qū)分不同應(yīng)用程序的記錄渤早,一旦設(shè)置职车,不能修改
使用時可用${contextName}
<configuration scan="true" scanPeriod="120 seconds" debug="false">
<contextName>serverName</contextName>
<!-- ... -->
</configuration>
變量 property
全局變量,類似于maven的pom.xml中的property,有兩個屬性:name悴灵、value扛芽,使用時使用${}占位符
<configuration scan="true" scanPeriod="120 seconds" debug="false">
<property name="serverName" value="TestServer"/>
<contextName>${serverName}</contextName>
<!-- ... -->
</configuration>
日志管理 logger
負(fù)責(zé)寫日志 appender
日志管理-logger
可以包含零個或多個<appender-ref>
屬性
name
用來約束某個包或者某個具體的類
root為全局配置
level
設(shè)置日志級別,與大小寫無關(guān)积瞒,默認(rèn)為DEBUG
日志級別從高到低:OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL
- ALL 最低等級的川尖,用于打開所有日志記錄。
- TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12茫孔,很低的日志級別叮喳,一般不會使用。
- DEBUG 指出細(xì)粒度信息事件對調(diào)試應(yīng)用程序是非常有幫助的缰贝,主要用于開發(fā)過程中打印一些運行信息馍悟。
- INFO 消息在粗粒度級別上突出強(qiáng)調(diào)應(yīng)用程序的運行過程。打印一些你感興趣的或者重要的信息剩晴,這個可以用于生產(chǎn)環(huán)境中輸出程序運行的一些重要信息锣咒,但是不能濫用,避免打印過多的日志赞弥。
- WARN 表明會出現(xiàn)潛在錯誤的情形宠哄,有些信息不是錯誤信息,但是也要給程序員的一些提示嗤攻。
- ERROR 指出雖然發(fā)生錯誤事件,但仍然不影響系統(tǒng)的繼續(xù)運行诽俯。打印錯誤和異常信息妇菱,如果不想輸出太多的日志,可以使用這個級別暴区。
- FATAL 指出每個嚴(yán)重的錯誤事件將會導(dǎo)致應(yīng)用程序的退出闯团。這個級別比較高了。重大錯誤仙粱,這種級別你可以直接停止程序了房交。
- OFF 最高等級的,用于關(guān)閉所有日志記錄伐割。
additivity
是否向上級logger傳遞打印信息候味,默認(rèn)是true,即INFO級別會向DEBUG傳遞
例
<configuration>
<!-- 指定包中的日志隔心,日志級別為DEBUG白群,不向上傳遞,打印至控制臺及指定日志文件 -->
<logger name="test.yong.mapper.dao" additivity="false" level="DEBUG">
<appender-ref ref="console"/>
<appender-ref ref="logfile_info"/>
</logger>
<!-- 指定類中的日志硬霍,日志級別為ERROR -->
<logger name="org.mybatis.spring.SqlSessionUtils" level="ERROR"/>
<!-- 配置<appender-ref>使用帜慢,設(shè)置統(tǒng)一日志級別 -->
<logger name="root" level="INFO">
</logger>
</configuration>
負(fù)責(zé)寫日志-appender
屬性
name
appender的名稱,全局唯一,appender-ref 關(guān)聯(lián)該name
class
appender的全限定名
ConsoleAppender 日志寫到控制臺
把日志添加到控制臺
<encoder>:對日志進(jìn)行格式化
<target>:字符串 System.out 或者 System.err 粱玲,默認(rèn) System.out
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="console" />
</root>
</configuration>
FileAppender 日志寫到文件
把日志添加到文件
<file>:被寫入的文件名躬柬,可以是相對目錄,也可以是絕對目錄抽减,如果上級目錄不存在會自動創(chuàng)建绿渣,沒有默認(rèn)值。
<append>:如果是 true档桃,日志被追加到文件結(jié)尾粘拾,如果是 false,清空現(xiàn)存文件偎箫,默認(rèn)是true木柬。
<encoder>:對記錄事件進(jìn)行格式化。
<prudent>:如果是 true淹办,日志會被安全的寫入文件眉枕,即使其他的FileAppender也在向此文件做寫入操作,效率低怜森,默認(rèn)是 false速挑。
prudent支持多JVM同時操作同一個日志文件
官方給的說明如下:如果使用prudent模式,F(xiàn)ileAppender將安全的寫入到指定文件副硅,即使存在運行在不同機(jī)器上的姥宝、其他JVM中運行的其他FileAppender實例。
Prudent模式更依賴于排他文件鎖恐疲,經(jīng)驗表明加了文件鎖后腊满,寫日志的開始是正常的3倍以上。當(dāng)prudent模式關(guān)閉時培己,每秒logging event的吞吐量為100,000碳蛋,當(dāng)prudent模式開啟時,大約為每秒33,000
<configuration>
<contextName>serverName</contextName>
<appender name="logfile_info" class="ch.qos.logback.core.FileAppender">
<file>${contextName}.log</file>
<append>true</append>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="logfile_info" />
</root>
</configuration>
RollingFileAppender 滾動記錄文件
滾動記錄文件省咨,先將日志記錄到指定文件肃弟,當(dāng)符合某個條件時,將日志記錄到其他文件
<file>:被寫入的文件名零蓉,可以是相對目錄笤受,也可以是絕對目錄,如果上級目錄不存在會自動創(chuàng)建敌蜂,沒有默認(rèn)值感论。
<append>:如果是 true,日志被追加到文件結(jié)尾紊册,如果是 false比肄,清空現(xiàn)存文件快耿,默認(rèn)是true。
<encoder>:對記錄事件進(jìn)行格式化芳绩。(具體參數(shù)稍后講解 )
<rollingPolicy>:當(dāng)發(fā)生滾動時掀亥,決定 RollingFileAppender 的行為,涉及文件移動和重命名妥色。
<triggeringPolicy >: 告知 RollingFileAppender 合適激活滾動搪花。
<prudent>:當(dāng)為true時,不支持FixedWindowRollingPolicy嘹害。支持TimeBasedRollingPolicy撮竿,但是有兩個限制,1不支持也不允許文件壓縮笔呀,2不能設(shè)置file屬性幢踏,必須留空。
rollingPolicy 滾動策略
TimeBasedRollingPolicy
最常用的滾動策略许师,它根據(jù)時間來制定滾動策略房蝉,既負(fù)責(zé)滾動也負(fù)責(zé)出發(fā)滾動。
<fileNamePattern>:
必要節(jié)點微渠,包含文件名及“%d”轉(zhuǎn)換符搭幻, “%d”可以包含一個 java.text.SimpleDateFormat指定的時間格式,如:%d{yyyy-MM}
RollingFileAppender的file字節(jié)點可有可無逞盆,通過設(shè)置file檀蹋,可以為活動文件和歸檔文件指定不同位置,當(dāng)前日志總是記錄到file指定的文件(活動文件)云芦,
活動文件的名字不會改變俯逾;如果沒設(shè)置file,活動文件的名字會根據(jù)fileNamePattern 的值焕数,每隔一段時間改變一次∨傩ィ“/”或者“\”會被當(dāng)做目錄分隔符堡赔。
<maxHistory>:
可選節(jié)點,控制保留的歸檔文件的最大數(shù)量设联,超出數(shù)量就刪除舊文件善已。
假設(shè)設(shè)置每個月滾動,且 <maxHistory>是6离例,則只保存最近6個月的文件换团,刪除之前的舊文件。
刪除舊文件時宫蛆,那些為了歸檔而創(chuàng)建的目錄也會被刪除艘包。
FixedWindowRollingPolicy
根據(jù)固定窗口算法重命名文件的滾動策略
<minIndex>:窗口索引最小值
<maxIndex>:窗口索引最大值的猛,當(dāng)用戶指定的窗口過大時,會自動將窗口設(shè)置為12想虎。
<fileNamePattern >:
必須包含“%i”例如卦尊,假設(shè)最小值和最大值分別為1和2,命名模式為 mylog%i.log,會產(chǎn)生歸檔文件mylog1.log和mylog2.log舌厨。還可以指定文件壓縮選項岂却,例如,mylog%i.log.gz或者log%i.log.zip
SizeAndTimeBasedRollingPolicy
按時間滾動裙椭,按大小歸檔
<fileNamePattern>
必要節(jié)點躏哩,%d和%i 必須有
<maxFileSize>
最大文件大小,超過大小進(jìn)行歸檔
<maxHistory>
可選節(jié)點揉燃,控制保留的歸檔文件的最大數(shù)量扫尺,超出數(shù)量就刪除舊文件。
<totalSizeCap>
總?cè)罩疚募畲蟠笮∧愦疲?dāng)總?cè)罩疚募畲蟠笮〕^最大值時器联,刪除舊文件,優(yōu)先級大于maxHistory
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>
/app/log/${CONTEXT_NAME}/info/${HOSTNAME}.${CONTEXT_NAME}.%d{yyyy-MM-dd}.ysData.%i.log
</FileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
triggeringPolicy 日志觸發(fā)器策略
SizeBasedTriggeringPolicy: 查看當(dāng)前活動文件的大小婿崭,如果超過指定大小會告知 RollingFileAppender 觸發(fā)當(dāng)前活動文件滾動拨拓。只有一個節(jié)點:
<maxFileSize>:這是活動文件的大小,默認(rèn)值是10MB氓栈。
例:
<!-- 每天生成一個日志文件渣磷,保存30天的日志文件 -->
<configuration>
<appender name="loggerFile_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="loggerFile_info" />
</root>
</configuration>
<!-- 按照固定窗口模式生成日志文件,當(dāng)文件大于20MB時授瘦,生成新的日志文件醋界。窗口大小是1到3,當(dāng)保存了3個歸檔文件后提完,將覆蓋最早的日志形纺。 -->
<configuration>
<appender name="loggerFile_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>test.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>tests.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>20MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="loggerFile_info" />
</root>
</configuration>
DBAppender 日志入庫
DBAppender將日志存入三張表中,這三張表分別為:logging_event, logging_event_property 與 logging_event_exception徒欣。在使用 DBAppender 之前逐样,它們必須存在。
logback 自帶 SQL 腳本來創(chuàng)建表打肝。這些腳本在 logback-classic/src/main/java/ch/qos/logback/classic/db/script 文件夾下脂新。每一種最流行的數(shù)據(jù)庫都有一個對應(yīng)的腳本。
目前 logback 支持的數(shù)據(jù)庫方言有 H2, HSQL, MS SQL Server, MySQL, Oracle, PostgreSQL, SQLLite and Sybase粗梭。
下面的表格總結(jié)了數(shù)據(jù)庫類型争便,以及它們是否支持 getGeneratedKeys()
方法:
RDBMS | 測試版本 | JDBC 驅(qū)動的測試版本 | 是否支持 getGeneratedKeys()
|
logback 是否提供對應(yīng)的方言 |
---|---|---|---|---|
DB2 | untested | untested | unknown | NO |
H2 | 1.2.132 | - | unknown | YES |
HSQL | 1.8.0.7 | - | NO | YES |
Microsoft SQL Server | 2005 | 2.0.1008.2 (sqljdbc.jar) | YES | YES |
MySQL | 5.0.22 | 5.0.8 (mysql-connector.jar) | YES | YES |
PostgreSQL | 8.x | 8.4-701.jdbc4 | NO | YES |
Oracle | 10g | 10.2.0.1 (ojdbc14.jar) | YES | YES |
SQLLite | 3.7.4 | - | unknown | YES |
Sybase SQLAnywhere | 10.0.1 | - | unknown | YES |
logging_event 表包含了以下字段:
Field | Type | Description |
---|---|---|
timestamp | big int |
日志事件的創(chuàng)建時間 |
formatted_message | text |
經(jīng)過 org.slf4j.impl.MessageFormatter 格式化后的消息 |
logger_name | varchar |
發(fā)出日志的 logger 名 |
level_string | varchar |
日志事件的級別 |
reference_flag | smallint |
用來表示是否是異常或者與 MDC 屬性相關(guān)聯(lián)断医。它的值通過 ch.qos.logback.classic.db.DBHelper 計算得到滞乙。日志時間包含 MDC 或者 Context 時奏纪,它的值為 1。包含異常時酷宵,它的值為 2亥贸。包含兩者,則值為 3浇垦。 |
caller_filename | varchar |
發(fā)出日志請求的文件名 |
caller_class | varchar |
發(fā)出日志請求的類 |
caller_method | varchar |
發(fā)出日志請求的方法 |
caller_line | char |
發(fā)出日志請求所在的行 |
event_id | int |
日志事件在數(shù)據(jù)庫的 id |
logging_event_property 表用于存儲 MDC
或者 Context
中的 key 與 value炕置。它包含如下字段:
Field | Type | Description |
---|---|---|
event_id | int |
日志事件的數(shù)據(jù)庫 id |
mapped_key | varchar |
MDC 屬性的 key |
mapped_value | text |
MDC 屬性的 value |
logging_event_exception 表包含如下字段:
Field | Type | Description |
---|---|---|
event_id | int |
日志事件的數(shù)據(jù)庫 id |
i | smallint |
堆棧所在的行 |
trace_line | varchar |
相對應(yīng)的堆棧信息 |
ConnectionSource
ConnectionSource 接口提供了一種可插拔式的方式為需要使用 java.sql.Connection 的 logback 類獲取 JDBC 連接。
目前有三種實現(xiàn)男韧,分別為:DataSourceConnectionSource朴摊,DriverManagerConnectionSource 與 JNDIConnectionSource
DriverManagerConnectionSource
DriverManagerConnectionSource 實現(xiàn)了 ConnectionSource 接口,通過基于 URL 的傳統(tǒng) JDBC 方式來獲取連接此虑。
這個類為每一個調(diào)用 getConnection()
的方法都新建一個 Connection
連接甚纲。推薦你使用本地支持的連接池的 JDBC 驅(qū)動,或者創(chuàng)建你自己實現(xiàn)的 ConnectionSource
朦前,基于你已經(jīng)使用的任何連接池機(jī)制
<!-- DriverManagerConnectionSource示例 -->
<configuration>
<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
<driverClass>com.mysql.jdbc.Driver</driverClass>
<url>jdbc:mysql://host_name:3306/datebase_name</url>
<user>username</user>
<password>password</password>
</connectionSource>
</appender>
<root level="DEBUG" >
<appender-ref ref="DB" />
</root>
</configuration>
JNDIConnectionSource
JNDIConnectionSource是 logback 自帶的介杆,ConnectionSource的另一種實現(xiàn)。從名字可以看出來韭寸,它通過 JNDI 獲取 javax.sql.DataSource春哨,然后再獲取 java.sql.Connection 實例。JNDIConnectionSource主要設(shè)計用在 J2EE 應(yīng)用服務(wù)器以及應(yīng)用服務(wù)器客戶端中恩伺,這里假設(shè)應(yīng)用服務(wù)器支持遠(yuǎn)程獲取 javax.sql.DataSource赴背。因為可以利用連接池或者其它應(yīng)用服務(wù)器所提供的好處。更加重要的是晶渠,你的應(yīng)用不需要做重復(fù)的工作凰荚,因為不需要在 logback.xml 中定義一個 DataSource。
<!-- tomcat中配置jndl -->
<Context docBase="/path/to/app.war" path="/myapp">
...
<Resource name="jdbc/logging"
auth="Container"
type="javax.sql.DataSource"
username="..."
password="..."
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://localhost/..."
maxActive="8"
maxIdle="4"/>
...
</Context>
<!-- JNDIConnectionSource示例 -->
<configuration debug="true">
<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
<connectionSource class="ch.qos.logback.core.db.JNDIConnectionSource">
<!-- please note the "java:comp/env/" prefix -->
<jndiLocation>java:comp/env/jdbc/logging</jndiLocation>
</connectionSource>
</appender>
<root level="INFO">
<appender-ref ref="DB" />
</root>
</configuration>
這個類通過無參構(gòu)造函數(shù)獲取一個 javax.naming.InitialContext
褒脯。在 J2EE 環(huán)境通潮闵可以行得通。但是在 J2EE 環(huán)境之外番川,你需要根據(jù) JNDI 提供者的文檔提供一個 jndi.properties 屬性文件
DataSourceConnectionSource
<configuration debug="true">
<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
<connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
<dataSource class="${dataSourceClass}">
<!-- Joran 不能替換不是屬性的變量到涂。因此我們不能像其它變量一樣聲明接下來的變量
-->
<param name="${url-key:-url}" value="${url_value}"/>
<serverName>${serverName}</serverName>
<databaseName>${databaseName}</databaseName>
</dataSource>
<user>${user}</user>
<password>${password}</password>
</connectionSource>
</appender>
<root level="INFO">
<appender-ref ref="DB" />
</root>
</configuration>
在這個例子中,我們大量使用了變量替換爽彤。當(dāng)需要把一些連接的細(xì)節(jié)集中在一個配置文件中养盗,并且通過 logback 與其它框架共享時非常方便缚陷。
連接池
日志事件可以很快的被創(chuàng)建适篙。為了讓日志事件都能被插入到數(shù)據(jù)庫,推薦DBAppender使用連接池配置箫爷。
經(jīng)過實驗發(fā)現(xiàn)嚷节,使用連接池聂儒,可以讓 DBAppender 有大幅的性能提升。下面的配置文件硫痰,將日志事件發(fā)送給 MySQL衩婚,沒有使用連接池。
<configuration>
<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
<connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
<dataSource class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
<serverName>${serverName}</serverName>
<port>${port$</port>
<databaseName>${dbName}</databaseName>
<user>${user}</user>
<password>${pass}</password>
</dataSource>
</connectionSource>
</appender>
<root level="DEBUG">
<appender-ref ref="DB" />
</root>
</configuration>
在這個配置文件中效斑,發(fā)送 500 個日志事件到 MySQL 數(shù)據(jù)庫非春,需要高達(dá) 5 秒的時間,相當(dāng)每條請求需要 10 毫秒缓屠。在大型的應(yīng)用中奇昙,這個數(shù)字是不能夠被接受的。
DBAppender` 連接池需要使用一個專業(yè)的外部庫敌完。下一個例子中使用 c3p0储耐。為了使用 c2p0,你需要下載并將 c3p0-VERSION.jar 放在類路徑下滨溉。
<configuration>
<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
<connectionSource
class="ch.qos.logback.core.db.DataSourceConnectionSource">
<dataSource
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<driverClass>com.mysql.jdbc.Driver</driverClass>
<jdbcUrl>jdbc:mysql://${serverName}:${port}/${dbName}</jdbcUrl>
<user>${user}</user>
<password>${password}</password>
</dataSource>
</connectionSource>
</appender>
<root level="DEBUG">
<appender-ref ref="DB" />
</root>
</configuration>
使用這個新的配置什湘,發(fā)送 500 條日志事件到 MySQL 數(shù)據(jù)庫大約需要 0.5 秒,大約 1 毫秒一條請求晦攒,性能提升了十倍闽撤。
SiftingAppender 分離或者過濾日志
SiftingAppender 根據(jù)給定的運行時屬性分離或者過濾日志。例如勤家,SiftingAppender 可以根據(jù)用戶的 session 分離日志腹尖,因此不同的用戶的日志會有不同的日志文件,一個用戶一個日志文件伐脖。
屬性名 | 類型 | 描述 |
---|---|---|
timeout | Duration | 一個內(nèi)置的 appender 如果在指定 timeout 時間內(nèi)沒有被訪問热幔,則被認(rèn)為是過時的。一個過時的 appender 會被關(guān)閉讼庇,并且不會被 SiftingAppende 所引用绎巨。默認(rèn)值為 30 分鐘 |
maxAppenderCount | integer |
SiftingAppender 可以創(chuàng)建并且跟蹤內(nèi)置 appender 的最大數(shù)量。默認(rèn)值為 Integer.MAX_VALUE |
通過動態(tài)創(chuàng)建來實現(xiàn)這個蠕啄。SiftingAppender 通過配置文件中指定的模板 (通過閉合的 <sift> 元素场勤,見下面的例子) 來創(chuàng)建內(nèi)置的 appender。SiftingAppender 負(fù)責(zé)管理子 appender 的生命周期歼跟。例如和媳,SiftingAppender 會自動關(guān)閉并移除任何過時的 appender。在指定的 timeout 時間內(nèi)沒有被訪問過的內(nèi)置 appender哈街,被認(rèn)為是過時的留瞳。
在處理一個日志事件時,SiftingAppender會委托一個子 appender 去進(jìn)行處理骚秦。選擇的標(biāo)準(zhǔn)是通過 discriminator 在運行時計算她倘。用戶也可以通過 Discriminator 來指定一個選擇標(biāo)準(zhǔn)璧微。
示例
應(yīng)用通過打印日志來表明應(yīng)用已經(jīng)啟動。通過 MDC 設(shè)置鍵 "userid" 對應(yīng)的值為 "Alice"硬梁,并打印了一條日志信息前硫。
logger.debug("Application started");
MDC.put("userid", "Alice");
logger.debug("Alice says hello");
<configuration>
<property name="FILE_NAME" value="FILE" />
<appender name="SIFT"
class="ch.qos.logback.classic.sift.SiftingAppender">
<!-- 在缺少 class 屬性的情況下,默認(rèn)的 discriminator 類型為 ch.qos.logback.classic.sift.MDCBasedDiscriminator -->
<discriminator>
<key>userid</key>
<defaultValue>unknown</defaultValue>
</discriminator>
<sift>
<appender name="FILE-${userid}"
class="ch.qos.logback.core.FileAppender">
<file>${userid}_${FILE_NAME}.log</file>
<append>false</append>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</pattern>
</layout>
</appender>
</sift>
</appender>
<root level="DEBUG">
<appender-ref ref="SIFT" />
</root>
</configuration>
在沒有 class 屬性的情況下荧止,默認(rèn)的 discriminator 類型為 MDCBasedDiscriminator屹电。discriminator 的的值為 MDC 的 key 所對應(yīng)的值。但是跃巡,如果 MDC 的值為 null嗤详,那么 defaultValue 的將為 discriminator 的值。
SiftingAppender 的獨特之處在于它有能力去引用以及配置子 appender瓷炮。在上面的例子中葱色,SiftingAppender 會創(chuàng)建多個 FileAppender 實例。每個 FileAppender 實例通過 MDC 的 key 所對應(yīng)的值來標(biāo)識娘香。每當(dāng) MDC 的 key "userid" 被分配一個新值時苍狰,一個新的 FileAppender 將會被構(gòu)建。SiftingAppender 可以追蹤它所創(chuàng)建的 appender烘绽。appender 在 30 分鐘之內(nèi)沒有被使用將會被自動關(guān)閉并丟棄淋昭。
導(dǎo)出變量 有不同 appender 實例是不夠的。每一個實例都必須輸出到一個唯一的資源中安接。為了做到這種區(qū)分翔忽,在 appender 模板中,key 被傳遞給 discriminator盏檐。在上面的例子中是 "userid"歇式,它將被導(dǎo)出并變成一個變量。因此胡野,該變量可以通過給定的子 appender 來區(qū)分具體的資源材失。
在上面的示例中,使用 "byUserid.xml" 來運行 SiftExample硫豆,將會創(chuàng)建兩個不同的日志文件龙巨,"unknown.log" 與 "Alice.log"。
本地變量 在版本 1.0.12 中熊响,配置文件中局部變量的屬性也可以應(yīng)用到內(nèi)置的 appender 中旨别。而且,你可以在 元素中定義變量以及動態(tài)定義屬性汗茄〗粘冢或者在 元素之外定義變量,在里面使用也是支持的。
獲取正確的 timeout
對于特定類型的應(yīng)用胆屿,正確的獲取 timeout 參數(shù)非常困難。如果 timeout 過小偶宫,一個新的內(nèi)置 appender 在創(chuàng)建幾秒鐘之后就被移除了非迹。這種現(xiàn)象被稱為 "制造垃圾"。如果 timeout 的值過大纯趋,那么 appender 會快速接連的被創(chuàng)建憎兽,可能會耗盡資源。同理吵冒,設(shè)置 maxAppenderCount 的值太低會產(chǎn)生垃圾纯命。
在大多數(shù)情況下,在代碼中顯示的指出不需要再創(chuàng)建內(nèi)置的 appender痹栖。需要在代碼中標(biāo)記日志事件為 FINALIZE_SESSION亿汞。無論什么時候 SiftingAppender 看到日志事件標(biāo)記為 FINALIZE_SESSION,它將會終結(jié)相關(guān)的子 appender揪阿。在生命周期快結(jié)束時疗我,內(nèi)置的 appender 將會留存幾秒鐘來處理之后到來的日志事件,然后再關(guān)閉南捂。
import org.slf4j.Logger;
import static ch.qos.logback.classic.ClassicConstants.FINALIZE_SESSION_MARKER;
void job(String jobId) {
MDC.put("jobId", jobId);
logger.info("Starting job.");
... do whather the job needs to do
// 將導(dǎo)致內(nèi)置 appender 結(jié)束生命周期吴裤。但是會留存幾秒鐘
logger.info(FINALIZE_SESSION_MARKER, "About to end the job");
try {
.. perform clean up
} catch(Exception e);
// 被留存的 appender 處理,但是不會再創(chuàng)建新的 appender
logger.error("unexpected error while cleaning up", e);
}
}
其余appender
SocketAppender溺健、SMTPAppender麦牺、SyslogAppender、SiftingAppender
<encoder>
負(fù)責(zé)兩件事鞭缭,一是把日志信息轉(zhuǎn)換成字節(jié)數(shù)組剖膳,二是把字節(jié)數(shù)組寫入到輸出流。
目前PatternLayoutEncoder 是唯一有用的且默認(rèn)的encoder 岭辣,有一個<pattern>節(jié)點潮秘,用來設(shè)置日志的輸入格式。使用“%”加“轉(zhuǎn)換符”方式易结,如果要輸出“%”枕荞,則必須用“\”對“%”進(jìn)行轉(zhuǎn)義
例:
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
轉(zhuǎn)換符 作用
c {length } lo {length } logger {length } | 輸出日志的logger名,可有一個整形參數(shù)搞动,功能是縮短logger名躏精,設(shè)置為0表示只輸入logger最右邊點符號之后的字符串。 Conversion specifier Logger name Result%loggermainPackage.sub.sample.BarmainPackage.sub.sample.Bar%logger{0}mainPackage.sub.sample.BarBar%logger{5}mainPackage.sub.sample.Barm.s.s.Bar%logger{10}mainPackage.sub.sample.Barm.s.s.Bar%logger{15}mainPackage.sub.sample.Barm.s.sample.Bar%logger{16}mainPackage.sub.sample.Barm.sub.sample.Bar%logger{26}mainPackage.sub.sample.BarmainPackage.sub.sample.Bar |
C {length } class {length } | 輸出執(zhí)行記錄請求的調(diào)用者的全限定名鹦肿。參數(shù)與上面的一樣矗烛。盡量避免使用,除非執(zhí)行速度不造成任何問題。 |
contextName cn | 輸出上下文名稱瞭吃。 |
d {pattern } date {pattern } | 輸出日志的打印日志碌嘀,模式語法與java.text.SimpleDateFormat 兼容。 Conversion Pattern Result%d2006-10-20 14:06:49,812%date2006-10-20 14:06:49,812%date{ISO8601}2006-10-20 14:06:49,812%date{HH:mm:ss.SSS}14:06:49.812%date{dd MMM yyyy ;HH:mm:ss.SSS}20 oct. 2006;14:06:49.812 |
F / file | 輸出執(zhí)行記錄請求的java源文件名歪架。盡量避免使用股冗,除非執(zhí)行速度不造成任何問題。 |
caller{depth} caller{depth, evaluator-1, ... evaluator-n} | 輸出生成日志的調(diào)用者的位置信息和蚪,整數(shù)選項表示輸出信息深度止状。例如, %caller{2} 輸出為:0 [main] DEBUG - logging statement Caller+0 at mainPackage.sub.sample.Bar.sampleMethodName(Bar.java:22) Caller+1 at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17) 例如攒霹, %caller{3} 輸出為:16 [main] DEBUG - logging statement Caller+0 at mainPackage.sub.sample.Bar.sampleMethodName(Bar.java:22) Caller+1 at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17) Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38)
|
L / line | 輸出執(zhí)行日志請求的行號怯疤。盡量避免使用,除非執(zhí)行速度不造成任何問題催束。 |
m / msg / message | 輸出應(yīng)用程序提供的信息集峦。 |
M / method | 輸出執(zhí)行日志請求的方法名。盡量避免使用抠刺,除非執(zhí)行速度不造成任何問題少梁。 |
n | 輸出平臺先關(guān)的分行符“\n”或者“\r\n”。 |
p / le / level | 輸出日志級別矫付。 |
r / relative | 輸出從程序啟動到創(chuàng)建日志記錄的時間凯沪,單位是毫秒 |
t / thread | 輸出產(chǎn)生日志的線程名。 |
replace(*p* ){r, t} | p 為日志內(nèi)容买优,r 是正則表達(dá)式妨马,將p 中符合r 的內(nèi)容替換為t 。例如杀赢, "%replace(%msg){'\s', ''}" |
格式修飾符烘跺,與轉(zhuǎn)換符共同使用:
可選的格式修飾符位于“%”和轉(zhuǎn)換符之間。
第一個可選修飾符是左對齊 標(biāo)志脂崔,符號是減號“-”滤淳;接著是可選的最小寬度 修飾符,用十進(jìn)制數(shù)表示砌左。
如果字符小于最小寬度脖咐,則左填充或右填充,默認(rèn)是左填充(即右對齊)汇歹,填充符為空格屁擅。
如果字符大于最小寬度,字符永遠(yuǎn)不會被截斷产弹。最大寬度 修飾符派歌,符號是點號"."后面加十進(jìn)制數(shù)。
如果字符大于最大寬度,則從前面截斷胶果。點符號“.”后面加減號“-”在加數(shù)字匾嘱,表示從尾部截斷。
例如:%-4relative 表示早抠,將輸出從程序啟動到創(chuàng)建日志記錄的時間 進(jìn)行左對齊 且最小寬度為
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}| %-4relative [%thread][%-5level][%logger:%L]%n %msg%n</pattern>
<charset>GBK</charset>
</encoder>
<filter>
過濾器霎烙,執(zhí)行一個過濾器會有返回個枚舉值,即DENY贝或,NEUTRAL,ACCEPT其中之一锐秦。
DENY咪奖,日志將立即被拋棄不再經(jīng)過其他過濾器;
NEUTRAL酱床,有序列表里的下個過濾器過接著處理日志羊赵;
ACCEPT,日志會被立即處理扇谣,不再經(jīng)過剩余過濾器昧捷。
過濾器被添加到<Appender>中,為<Appender>添加一個或多個過濾器后罐寨,可以用任意條件對日志進(jìn)行過濾靡挥。<Appender> 有多個過濾器時,按照配置順序執(zhí)行鸯绿。
LevelFilter
級別過濾器跋破,根據(jù)日志級別進(jìn)行過濾
如果日志級別等于配置級別,過濾器會根據(jù)onMath 和 onMismatch接收或拒絕日志
<level>:設(shè)置過濾級別
<onMatch>:用于配置符合過濾條件的操作
<onMismatch>:用于配置不符合過濾條件的操作
<!-- 將過濾器的日志級別配置為INFO瓶蝴,所有INFO級別的日志交給appender處理毒返,非INFO級別的日志,被過濾掉 -->
<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
臨界值過濾器舷手,過濾掉低于指定臨界值的日志
當(dāng)日志級別等于或高于臨界值時拧簸,過濾器返回NEUTRAL;當(dāng)日志級別低于臨界值時男窟,日志會被拒絕
<!-- 過濾掉所有低于INFO級別的日志 -->
<configuration>
<appender name="CONSOLE"
class="ch.qos.logback.core.ConsoleAppender">
<!-- 過濾掉 TRACE 和 DEBUG 級別的日志-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger{30} - %msg%n
</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
EvaluatorFilter
求值過濾器盆赤,評估、鑒別日志是否符合指定條件
需要額外的兩個JAR包歉眷,commons-compiler.jar和janino.jar
<evaluator>
鑒別器弟劲,常用的鑒別器是JaninoEventEvaluato,也是默認(rèn)的鑒別器姥芥,它以任意的java布爾值表達(dá)式作為求值條件兔乞,求值條件在配置文件解釋過成功被動態(tài)編譯,布爾值表達(dá)式返回true就表示符合過濾條件。evaluator有個子標(biāo)簽<expression>庸追,用于配置求值條件
求值表達(dá)式作用于當(dāng)前日志霍骄,logback向求值表達(dá)式暴露日志的各種字段:
Name | Type | Description |
---|---|---|
event | LoggingEvent |
與記錄請求相關(guān)聯(lián)的原始記錄事件,下面所有變量都來自event淡溯,例如读整,event.getMessage()返回下面"message"相同的字符串 |
message | String |
日志的原始消息,例如咱娶,設(shè)有l(wèi)ogger mylogger米间,"name"的值是"AUB",對于 mylogger.info("Hello {}",name); "Hello {}"就是原始消息膘侮。 |
formatedMessage | String |
日志被各式話的消息屈糊,例如,設(shè)有l(wèi)ogger mylogger琼了,"name"的值是"AUB"逻锐,對于 mylogger.info("Hello {}",name); "Hello Aub"就是格式化后的消息。 |
logger | String |
logger 名雕薪。 |
loggerContext | LoggerContextVO |
日志所屬的logger上下文昧诱。 |
level | int |
級別對應(yīng)的整數(shù)值,所以 level > INFO 是正確的表達(dá)式所袁。 |
timeStamp | long |
創(chuàng)建日志的時間戳盏档。 |
marker | Marker |
與日志請求相關(guān)聯(lián)的Marker對象,注意“Marker”有可能為null燥爷,所以你要確保它不能是null妆丘。 |
mdc | Map |
包含創(chuàng)建日志期間的MDC所有值得map。訪問方法是: mdc.get("myKey") 局劲。mdc.get()返回的是Object不是String勺拣,要想調(diào)用String的方法就要強(qiáng)轉(zhuǎn),例如鱼填,((String) mdc.get("k")).contains("val") .MDC可能為null药有,調(diào)用時注意。 |
throwable | java.lang.Throwable | 如果沒有異常與日志關(guān)聯(lián)"throwable" 變量為 null. 不幸的是苹丸, "throwable" 不能被序列化愤惰。在遠(yuǎn)程系統(tǒng)上永遠(yuǎn)為null,對于與位置無關(guān)的表達(dá)式請使用下面的變量throwableProxy
|
throwableProxy | IThrowableProxy |
與日志事件關(guān)聯(lián)的異常代理赘理。如果沒有異常與日志事件關(guān)聯(lián)宦言,則變量"throwableProxy" 為 null. 當(dāng)異常被關(guān)聯(lián)到日志事件時,"throwableProxy" 在遠(yuǎn)程系統(tǒng)上不會為null |
<onMatch>:用于配置符合過濾條件的操作
<onMismatch>:用于配置不符合過濾條件的操作
<!-- 過濾掉所有日志消息中不包含“billing”字符串的日志 -->
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator> <!-- 默認(rèn)為 ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
<expression>return message.contains("billing");</expression>
</evaluator>
<OnMatch>ACCEPT </OnMatch>
<OnMismatch>DENY</OnMismatch>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="console" />
</root>
</configuration>
<matcher>
匹配器
盡管可以使用String類的matches()方法進(jìn)行模式匹配商模,但會導(dǎo)致每次調(diào)用過濾器時都會創(chuàng)建一個新的Pattern對象奠旺,為了消除這種開銷蜘澜,可以預(yù)定義一個或多個matcher對象,定以后就可以在求值表達(dá)式中重復(fù)引用响疚。
<matcher>是<evaluator>的子標(biāo)簽鄙信。
<matcher>中包含兩個子標(biāo)簽,一個是<name>忿晕,用于定義matcher的名字装诡,求值表達(dá)式中使用這個名字來引用matcher;另一個是<regex>践盼,用于配置匹配條件
<configuration debug="true">
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<matcher>
<Name>odd</Name>
<!-- filter out odd numbered statements -->
<regex>statement [13579]</regex>
</matcher>
<expression>odd.matches(formattedMessage)</expression>
</evaluator>
<OnMismatch>NEUTRAL</OnMismatch>
<OnMatch>DENY</OnMatch>
</filter>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="console" />
</root>
</configuration>
MDC使用
logback.xml中配置:
使用%X{xxx} 進(jìn)行占位鸦采,可配置多個,名稱不能重復(fù)
<!-- %X{logToken}為MDC的占位符 -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}|%X{logToken}|%X{IP}|%X{HOSTNAME}| %-4relative [%thread][%-5level][%logger:%L]%n %msg%n</pattern>
<charset>GBK</charset>
</encoder>
在java代碼中賦值咕幻,可put多個與占位符名稱相同的屬性,無順序要求
MDC.put("logToken", "xxxxxx");
MDC.put("IP",getServerIpAddress());
MDC.put("HOSTNAME",getHostName());
MDC線程安全鸟款,使用結(jié)束后應(yīng)及時清除MDC
// 清空全部
MDC.clear();
// 移除指定key
MDC.remove(key);
導(dǎo)入其他logback文件
<!-- logback.xml -->
<configuration>
<contextName>xxxx</contextName>
<!-- <include resource="org/springframework/boot/logging/logback/base.xml"/> -->
<include resource="logback-common.xml"/>
</configuration>
<?xml version="1.0" encoding="GBK"?>
<!-- logback-common.xml -->
<included>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread][track: %X{trackToken}] %-5level %logger:%L%n
%msg%n
</pattern>
<charset>GBK</charset>
</encoder>
</appender>
<appender name="logfile_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<Prudent>true</Prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
/app/log/${CONTEXT_NAME}/error/${HOSTNAME}.${CONTEXT_NAME}.%d{yyyy-MM-dd-HH}.error.log
</FileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread][%X{trackToken}][%-5level][%logger:%L]%n %msg%n
</pattern>
<charset>GBK</charset>
</encoder>
</appender>
<appender name="logfile_debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<Prudent>true</Prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
/app/log/${CONTEXT_NAME}/debug/${HOSTNAME}.${CONTEXT_NAME}.%d{yyyy-MM-dd-HH}.debug.log
</FileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread][%X{trackToken}][%-5level][%logger:%L]%n %msg%n
</pattern>
<charset>GBK</charset>
</encoder>
</appender>
<logger name="root" level="DEBUG">
<appender-ref ref="logfile_debug"/>
<appender-ref ref="logfile_error"/>
</logger>
<logger name="xxxx" level="DEBUG"/>
<logger name="org.hibernate" level="WARN"/>
<logger name="org.hibernate.SQL" level="DEBUG"/>
<logger name="org.apache.camel" level="ERROR"/>
<logger name="org.apache.activemq.transport" level="WARN"/>
<logger name="java.sql" level="DEBUG"/>
<logger name="com.mchange" level="WARN"/>
<logger name="org.springframework" level="WARN"/>
<logger name="org.apache.commons" level="WARN"/>
<logger name="org.apache.http.wire" level="OFF"/>
<logger name="org.apache.http.headers" level="OFF"/>
<logger name="org.springframework.data.mongodb.core" level="DEBUG"/>
<logger name="org.mongodb.driver.cluster" level="WARN"/>
<logger name="org.mongodb.driver.protocol.command" level="WARN"/>
<logger name="com.netflix" level="INFO"/>
<logger name="org.apache.http.impl.conn" level="INFO"/>
<logger name="org.apache.http.client.protocol" level="INFO"/>
</included>
與SpringBoot結(jié)合
官方推薦使用logback-spring.xml作為配置文件命名
<springProfile>
<springProfile> 標(biāo)簽允許我們更加靈活配置文件精钮,可選地包含或排除配置部分牲尺。
元素中的任何位置均支持輪廓部分扫夜。使用該name屬性指定哪個配置文件接受配置百框』昴牵可以使用逗號分隔列表指定多個配置文件奇钞。
<springProfile name="dev">
<!-- 開發(fā)環(huán)境時激活 -->
</springProfile>
<springProfile name="dev,test">
<!-- 開發(fā)忽刽,測試的時候激活-->
</springProfile>
<springProfile name="!prod">
<!-- 當(dāng) "生產(chǎn)" 環(huán)境時鲜侥,該配置不激活-->
</springProfile>
<!-- 開發(fā)環(huán)境日志級別為DEBUG -->
<springProfile name="dev">
<root level="DEBUG">
<appender-ref ref="FILE"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<!-- 測試環(huán)境日志級別為INFO -->
<springProfile name="test">
<root level="INFO">
<appender-ref ref="FILE"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProperty>
1.該 <springProperty> 標(biāo)簽允許我們從Spring中顯示屬性褂始,Environment 以便在Logback中使用。如果你想將 application.properties在回讀配置中訪問文件中的值描函,這將非常有用
2.標(biāo)簽的工作方式與Logback的標(biāo)準(zhǔn) <property> 標(biāo)簽類似崎苗,但不是直接value 指定source屬性(從Environment)指定。
scope 如果需要將屬性存儲在local范圍之外的其他位置舀寓,則可以使用該屬性胆数。如果您需要一個后備值,以防該屬性未設(shè)置互墓,則Environment可以使用該defaultValue屬性必尼。
<!-- 讀取spring.application.name中的屬性來生成日志文件名 -->
<!-- 如果無法獲取,在springProperty前添加property標(biāo)簽 -->
<springProperty scope="context" name="logName" source="spring.application.name" defaultValue="localhost.log"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/${logName}.log</file> <!-- 使用方法 -->
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/${logName}-%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>7</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] [%logger:%line] --%mdc{client} %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
</filter>
</appender>