參考資料
一票罐、基本規(guī)則
使用
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
//logger定義
package org.slf4j;
public interface Logger {
public void trace(String message);
public void debug(String message);
public void info(String message);
public void warn(String message);
public void error(String message);
}
logger打印規(guī)則
如果一條的日志的打印級(jí)別大于 logger 的有效級(jí)別,該條日志才可以被打印出來(lái)绅这。這條規(guī)則總結(jié)如下:
日志的打印級(jí)別為 p,Logger 實(shí)例的級(jí)別為 q,如果 p >= q悍手,則該條日志可以打印出來(lái)。
這條規(guī)則是 logbakc 的核心袍患。各級(jí)別的排序?yàn)椋篢RACE < DEBUG < INFO < WARN < ERROR坦康。
舉例
ch.qos.logback.classic.Logger logger =
(ch.qos.logback.classic.Logger)LoggerFactory.getLogger("com.foo");
// 設(shè)置 logger 的級(jí)別為 INFO
logger.setLevel(Level.INFO);
// 這條日志可以打印,因?yàn)?WARN >= INFO
logger.warn("警告信息");
// 這條日志不會(huì)打印诡延,因?yàn)?DEBUG < INFO
logger.debug("調(diào)試信息");
appender疊加規(guī)則
如果 root logger 添加了一個(gè) console appender滞欠,所有允許輸出的日志至少會(huì)在控制臺(tái)打印出來(lái)。如果再給一個(gè)叫做 L 的 logger 添加了一個(gè) file appender肆良,那么 L 以及 L 的子級(jí) logger 都可以在文件和控制臺(tái)打印日志筛璧。可以通過(guò)設(shè)置 additivity = false 來(lái)改寫(xiě)默認(rèn)的設(shè)置惹恃,這樣 appender 將不再具有疊加性夭谤。
提前判定,避免損耗
if(logger.isDebugEnabled()) {
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}
更優(yōu)的日志格式化
下面兩行輸出的結(jié)果是一樣的巫糙,但是一旦禁止日志打印朗儒,第二個(gè)變量的性能至少比第一個(gè)變量好上 30 倍。
logger.debug("The new entry is " + entry + "."); //不推薦
logger.debug("The new entry is {}", entry);
logger.debug("The new entry is {}, It replaces {}.", entry, oldEntry);//使用兩個(gè)參數(shù)的例子
Object[] paramArray = {newVal, below, above};
logger.debug("Value {} was inserted between {} and {}.", paramArray);//使用三個(gè)或三個(gè)以上的參數(shù)
一、配置相關(guān)
自動(dòng)化配置logback.xml
以下是 logback 的初始化步驟:
- logback 會(huì)在類路徑下尋找名為 logback-test.xml 的文件醉锄。
- 如果沒(méi)有找到疲牵,logback 會(huì)繼續(xù)尋找名為 logback.groovy 的文件。
- 如果沒(méi)有找到榆鼠,logback 會(huì)繼續(xù)尋找名為 logback.xml 的文件纲爸。
- 如果沒(méi)有找到,將會(huì)通過(guò) JDK 提供的 ServiceLoader 工具在類路徑下尋找文件 META-INFO/services/ch.qos.logback.classic.spi.Configurator妆够,該文件的內(nèi)容為實(shí)現(xiàn)了
Configurator
接口的實(shí)現(xiàn)類的全限定類名识啦。- 如果以上都沒(méi)有成功,logback 會(huì)通過(guò)BasicConfigurator為自己進(jìn)行配置神妹,并且日志將會(huì)全部在控制臺(tái)打印出來(lái)颓哮。
最后一步的目的是為了保證在所有的配置文件都沒(méi)有被找到的情況下,提供一個(gè)默認(rèn)的(但是是非惩臆基礎(chǔ)的)配置冕茅。
下面的配置等同于通過(guò) BasicConfigurator進(jìn)行配置
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
在警告或錯(cuò)誤的情況下自動(dòng)打印狀態(tài)信息
編碼方式實(shí)現(xiàn)
LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);
配置方式實(shí)現(xiàn),增加debug="true"
<configuration debug="true"></configuration>
等效配置
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<!-- 剩下的配置跟之前的相同 -->
</configuration>
區(qū)別:
但是,如果配置文件沒(méi)有被找到蛹找,logback 不會(huì)打印它的內(nèi)部狀態(tài)信息姨伤,因?yàn)闆](méi)有檢測(cè)到錯(cuò)誤。通過(guò)編碼方式調(diào)用 StatusPrinter.print() 方法會(huì)在任何情況下都打印狀態(tài)信息庸疾。
當(dāng)配置文件更改時(shí)乍楚,自動(dòng)加載
<!-- 默認(rèn)情況下,一分鐘掃描一次配置文件届慈,看是否有更改徒溪。通過(guò) <configuration> 標(biāo)簽上的 scanPeriod 屬性可以指定掃描周期。掃描周期的時(shí)間單位可以是毫秒金顿、秒臊泌、分鐘或者小時(shí)-->
<configuration scan="true" scanPeriod="30 seconds">
</configuration>
當(dāng)設(shè)置了 scan="true"
,會(huì)新建一個(gè) ReconfigureOnChangeTask 任務(wù)用于監(jiān)視配置文件是否變化揍拆。ReconfigureOnChangeTask
也會(huì)自動(dòng)監(jiān)視外部文件的變化渠概。
查看內(nèi)部狀態(tài)信息
logback-classic 包含一個(gè)名叫 ViewStatusMessagesServlet 的 servlet。這個(gè) servlet 打印當(dāng)前 LoggerContext 的 StatusManager 的內(nèi)容礁凡,通過(guò) html 進(jìn)行輸出高氮。
在 WEB-INF/web.xml 中添加如下代碼:
<servlet>
<servlet-name>ViewStatusMessages</servlet-name>
<servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ViewStatusMessages</servlet-name>
<url-pattern>/lbClassicStatus</url-pattern>
</servlet-mapping>
然后可以通過(guò) http://host/yourWebapp/lbClassicStatus 進(jìn)行訪問(wèn)。
配置 <logger> 標(biāo)簽
【must】 name 屬性
【option】 level 屬性
【option】 additivity 屬性
【0-n】<appender-ref> 元素
配置<root> 元素
【option】 level 屬性
【0-n】<appender-ref> 元素
<logger name="chapters.configuration" level="INFO" />
<logger name="chapters.configuration.Foo" level="DEBUG" />
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
與 log4j 不同的是顷牌,logbakc-classic 不會(huì)關(guān)閉或移除任何之前在 logger 上定義好的的 appender剪芍。
配置<appender> 元素
【must】 name】、class 屬性
【0-n】<layout>窟蓝、<filter>罪裹、<encoder> 元素
<layout>
元素強(qiáng)制一個(gè) class 屬性去指定一個(gè)類的全限定名饱普,用于實(shí)例化。與<appender>
元素一樣状共,<layout>
元素也可以包含與 layout 實(shí)例相關(guān)的屬性套耕。如果 layout 的 class 是PatternLayout
,那么 class 屬性可以被隱藏掉(參考:默認(rèn)類映射)峡继,因?yàn)檫@個(gè)很常見(jiàn)冯袍。.
<encoder
元素強(qiáng)制一個(gè) class 屬性去指定一個(gè)類的全限定名,用于實(shí)例化碾牌。如果 encoder 的 class 是PatternLayoutEncoder
康愤,那么基于默認(rèn)類映射,class 屬性可以被隱藏舶吗。
錯(cuò)誤示范征冷,會(huì)導(dǎo)致重復(fù)打印chapters.configuration包下的類容
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration">
<appender-ref ref="STDOUT" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
設(shè)置 context 的名字
默認(rèn)這個(gè) logger context 的名字為 "default"。但是你可以通過(guò) <contextName> 設(shè)置其它的名字誓琼。
<configuration>
<contextName>myAppName</contextName>
</configuration>
變量的定義
<configuration>
<!-- 定義方式一 -->
<property name="USER_NAME" value="/data/logs" />
<!-- 定義方式二 -->
<property file="F:\project\logback-examples\src\main\resources\variables1.properties"/>
<!-- 定義方式三 -->
<property resource="resource1.properties" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_NAME}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
變量的作用域
屬性的作用域分別為本地(local scope)检激、上下文(context scope)、系統(tǒng)(system scope)腹侣。默認(rèn)為本地作用域叔收。
在進(jìn)行變量替換的時(shí)候,會(huì)先從本地范圍去找筐带,再?gòu)纳舷挛娜フ医翊購(gòu)南到y(tǒng)屬性中去找,最后會(huì)去系統(tǒng)的環(huán)境變量中去找伦籍。
可以通過(guò) <property>、<define>腮出、<insertFromJNDI> 元素的 scope 屬性來(lái)設(shè)置變量的作用范圍帖鸦。scope 屬性可能的值為:local,context胚嘲,system作儿。如果沒(méi)有指定,則默認(rèn)為 local馋劈。
<property scope="context" name="nodeId" value="firstNode"/>
變量的默認(rèn)值
攻锰。在 bash shell 中,默認(rèn)值可以通過(guò) ":-" 來(lái)指定妓雾。例如:假設(shè)變量 aName 沒(méi)有被定義娶吞,"${aNme:-golden}" 會(huì)被解釋成 "golden" 。
<file>${USER_NAME:-jack js}/myApp.log</file>
變量的嵌套
USER_HOME=/data/logs
fileName=myApp.log
destination=${USER_HOME}/${fileName}
系統(tǒng)預(yù)定義屬性
<pattern>${HOSTNAME} - %msg%n</pattern>
<pattern>${CONTEXT_NAME} - %msg%n</pattern>
引入文件
通過(guò) <include> 元素可以引入外部的配置文件械姻。
<configuration>
<include file="src/main/resources/includedConfig.xml" />
<root level="DEBUG">
<appender-ref ref="includedConsole" />
</root>
</configuration>
目標(biāo)文件必須是由 <included> 元素包裹的妒蛇。
<included>
<appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d - %m%n</pattern>
</encoder>
</appender>
</included>
如果 logback 沒(méi)有通過(guò) include 元素找到指定的配置文件,會(huì)在控制臺(tái)打印出內(nèi)部狀態(tài)信息。如果引入的外部配置文件是可選的绣夺,可以設(shè)置 optional=true吏奸。
<include optional="true" ..../>