国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - logback 配置詳解(推薦)

logback 配置詳解(推薦)

2021-06-10 15:21beanlam Java教程

這篇文章主要介紹了logback 配置詳解(推薦),詳細(xì)的介紹了logback的組成使用和配置,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

概覽

簡(jiǎn)單地說(shuō),logback 是一個(gè) java 領(lǐng)域的日志框架。它被認(rèn)為是 log4j 的繼承人。

logback 主要由三個(gè)模塊組成:

  • logback-core
  • logback-classic
  • logback-access

logback-core 是其它模塊的基礎(chǔ)設(shè)施,其它模塊基于它構(gòu)建,顯然,logback-core 提供了一些關(guān)鍵的通用機(jī)制。logback-classic 的地位和作用等同于 log4j,它也被認(rèn)為是 log4j 的一個(gè)改進(jìn)版,并且它實(shí)現(xiàn)了簡(jiǎn)單日志門面 slf4j;而 logback-access 主要作為一個(gè)與 servlet 容器交互的模塊,比如說(shuō) tomcat 或者 jetty,提供一些與 http 訪問(wèn)相關(guān)的功能。

目前 logback 的使用很廣泛,很多知名的開(kāi)源軟件都使用了 logback作為日志框架,比如說(shuō) akka,apache camel 等。

logback 與 log4j

實(shí)際上,這兩個(gè)日志框架都出自同一個(gè)開(kāi)發(fā)者之手,logback 相對(duì)于 log4j 有更多的優(yōu)點(diǎn)

  • 同樣的代碼路徑,logback 執(zhí)行更快
  • 更充分的測(cè)試
  • 原生實(shí)現(xiàn)了 slf4j api(log4j 還需要有一個(gè)中間轉(zhuǎn)換層)
  • 內(nèi)容更豐富的文檔
  • 支持 xml 或者 groovy 方式配置
  • 配置文件自動(dòng)熱加載
  • 從 io 錯(cuò)誤中優(yōu)雅恢復(fù)
  • 自動(dòng)刪除日志歸檔
  • 自動(dòng)壓縮日志成為歸檔文件
  • 支持 prudent 模式,使多個(gè) jvm 進(jìn)程能記錄同一個(gè)日志文件
  • 支持配置文件中加入條件判斷來(lái)適應(yīng)不同的環(huán)境
  • 更強(qiáng)大的過(guò)濾器
  • 支持 siftingappender(可篩選 appender)
  • 異常棧信息帶有包信息

快速上手

想在 java 程序中使用 logback,需要依賴三個(gè) jar 包,分別是 slf4j-api,logback-core,logback-classic。其中 slf4j-api 并不是 logback 的一部分,是另外一個(gè)項(xiàng)目,但是強(qiáng)烈建議將 slf4j 與 logback 結(jié)合使用。要引用這些 jar 包,在 maven 項(xiàng)目中引入以下3個(gè) dependencies

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
 <groupid>org.slf4j</groupid>
 <artifactid>slf4j-api</artifactid>
 <version>1.7.5</version>
</dependency>
<dependency>
 <groupid>ch.qos.logback</groupid>
 <artifactid>logback-core</artifactid>
 <version>1.0.11</version>
</dependency>
<dependency>
 <groupid>ch.qos.logback</groupid>
 <artifactid>logback-classic</artifactid>
 <version>1.0.11</version>
</dependency>

第一個(gè)簡(jiǎn)單的例子

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package io.beansoft.logback.demo.universal;
 
import org.slf4j.logger;
import org.slf4j.loggerfactory;
 
/**
 *
 *
 * @author beanlam
 * @date 2017年2月9日 下午11:17:53
 * @version 1.0
 *
 */
public class simpledemo {
 
 private static final logger logger = loggerfactory.getlogger(simpledemo.class);
 
 public static void main(string[] args) {
 logger.info("hello, this is a line of log message logged by logback");
 }
}

以上代碼的運(yùn)行結(jié)果是:

23:19:41.131 [main] info i.b.l.demo.universal.simpledemo - hello, this is a line of log message logged by logback

注意到這里,代碼里并沒(méi)有引用任何一個(gè)跟 logback 相關(guān)的類,而是引用了 slf4j 相關(guān)的類,這邊是使用 slf4j 的好處,在需要將日志框架切換為其它日志框架時(shí),無(wú)需改動(dòng)已有的代碼。

loggerfactory 的 getlogger() 方法接收一個(gè)參數(shù),以這個(gè)參數(shù)決定 logger 的名字,這里傳入了 simpledemo 這個(gè)類的 class 實(shí)例,那么 logger 的名字便是 simpledemo 這個(gè)類的全限定類名:io.beansoft.logback.demo.universal.simpledemo

讓 logback 打印出一些它自身的內(nèi)部消息

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package io.beansoft.logback.demo.universal;
 
import org.slf4j.logger;
import org.slf4j.loggerfactory;
 
import ch.qos.logback.classic.loggercontext;
import ch.qos.logback.core.util.statusprinter;
 
/**
 *
 *
 * @author beanlam
 * @date 2017年2月9日 下午11:31:55
 * @version 1.0
 *
 */
public class loginternalstatedemo {
 
 private static final logger logger = loggerfactory.getlogger(loginternalstatedemo.class);
 
 public static void main(string[] args) {
 logger.info("hello world");
 
 //打印 logback 內(nèi)部狀態(tài)
 loggercontext lc = (loggercontext) loggerfactory.getiloggerfactory();
 statusprinter.print(lc);
 }
}

除了打印正常的日志信息,還打印出了 logback 自身的內(nèi)部狀態(tài)信息

23:33:19.340 [main] info  i.b.l.d.u.loginternalstatedemo - hello world
23:33:19,265 |-info in ch.qos.logback.classic.loggercontext[default] - could not find resource [logback.groovy]
23:33:19,265 |-info in ch.qos.logback.classic.loggercontext[default] - could not find resource [logback-test.xml]
23:33:19,265 |-info in ch.qos.logback.classic.loggercontext[default] - could not find resource [logback.xml]
23:33:19,266 |-info in ch.qos.logback.classic.loggercontext[default] - setting up default configuration.

logger,appenders 與 layouts

在 logback 里,最重要的三個(gè)類分別是

  • logger
  • appender
  • layout

logger 類位于 logback-classic 模塊中, 而 appender 和 layout 位于 logback-core 中,這意味著, appender 和 layout 并不關(guān)心 logger 的存在,不依賴于 logger,同時(shí)也能看出, logger 會(huì)依賴于 appender 和 layout 的協(xié)助,日志信息才能被正常打印出來(lái)。

分層命名規(guī)則

為了可以控制哪些信息需要輸出,哪些信息不需要輸出,logback 中引進(jìn)了一個(gè) 分層 概念。每個(gè) logger 都有一個(gè) name,這個(gè) name 的格式與 java 語(yǔ)言中的包名格式相同。這也是前面的例子中直接把一個(gè) class 對(duì)象傳進(jìn) loggerfactory.getlogger() 方法作為參數(shù)的原因。

logger 的 name 格式?jīng)Q定了多個(gè) logger 能夠組成一個(gè)樹(shù)狀的結(jié)構(gòu),為了維護(hù)這個(gè)分層的樹(shù)狀結(jié)構(gòu),每個(gè) logger 都被綁定到一個(gè) logger 上下文中,這個(gè)上下文負(fù)責(zé)厘清各個(gè) logger 之間的關(guān)系。

例如, 命名為 io.beansoft 的 logger,是命名為 io.beansoft.logback 的 logger 的父親,是命名為 io.beansoft.logback.demo 的 logger 的祖先。

在 logger 上下文中,有一個(gè) root logger,作為所有 logger 的祖先,這是 logback 內(nèi)部維護(hù)的一個(gè) logger,并非開(kāi)發(fā)者自定義的 logger。

可通過(guò)以下方式獲得這個(gè) logger :

?
1
logger rootlogger = loggerfactory.getlogger(org.slf4j.logger.root_logger_name);

同樣,通過(guò) logger 的 name,就能獲得對(duì)應(yīng)的其它 logger 實(shí)例。

logger 這個(gè)接口主要定義的方法有:

?
1
2
3
4
5
6
7
8
9
10
package org.slf4j;
public interface logger {
 
 // printing methods:
 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);
}

日志打印級(jí)別

logger 有日志打印級(jí)別,可以為一個(gè) logger 指定它的日志打印級(jí)別。

如果不為一個(gè) logger 指定打印級(jí)別,那么它將繼承離他最近的一個(gè)有指定打印級(jí)別的祖先的打印級(jí)別。這里有一個(gè)容易混淆想不清楚的地方,如果 logger 先找它的父親,而它的父親沒(méi)有指定打印級(jí)別,那么它會(huì)立即忽略它的父親,往上繼續(xù)尋找它爺爺,直到它找到 root logger。因此,也能看出來(lái),要使用 logback, 必須為 root logger 指定日志打印級(jí)別。

日志打印級(jí)別從低級(jí)到高級(jí)排序的順序是:
trace < debug < info < warn < error

如果一個(gè) logger 允許打印一條具有某個(gè)日志級(jí)別的信息,那么它也必須允許打印具有比這個(gè)日志級(jí)別更高級(jí)別的信息,而不允許打印具有比這個(gè)日志級(jí)別更低級(jí)別的信息。

舉個(gè)例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package io.beansoft.logback.demo.universal;
 
import org.slf4j.logger;
import org.slf4j.loggerfactory;
 
import ch.qos.logback.classic.level;
 
/**
 *
 *
 * @author beanlam
 * @date 2017年2月10日 上午12:20:33
 * @version 1.0
 *
 */
public class logleveldemo {
 
 public static void main(string[] args) {
 
 //這里強(qiáng)制類型轉(zhuǎn)換時(shí)為了能設(shè)置 logger 的 level
 ch.qos.logback.classic.logger logger =
  (ch.qos.logback.classic.logger) loggerfactory.getlogger("com.foo");
 logger.setlevel(level.info);
 
 logger barlogger = loggerfactory.getlogger("com.foo.bar");
 
 // 這個(gè)語(yǔ)句能打印,因?yàn)?warn > info
 logger.warn("can be printed because warn > info");
 
 // 這個(gè)語(yǔ)句不能打印,因?yàn)?debug < info.
 logger.debug("can not be printed because debug < info");
 
 // barlogger 是 logger 的一個(gè)子 logger
 // 它繼承了 logger 的級(jí)別 info
 // 以下語(yǔ)句能打印,因?yàn)?info >= info
 barlogger.info("can be printed because info >= info");
 
 // 以下語(yǔ)句不能打印,因?yàn)?debug < info
 barlogger.debug("can not be printed because debug < info");
 }
}

打印結(jié)果是:

00:27:19.251 [main] warn  com.foo - can be printed because warn > info
00:27:19.255 [main] info  com.foo.bar - can be printed because info >= info

獲取 logger

在 logback 中,每個(gè) logger 都是一個(gè)單例,調(diào)用 loggerfactory.getlogger 方法時(shí),如果傳入的 logger name 相同,獲取到的 logger 都是同一個(gè)實(shí)例。

在為 logger 命名時(shí),用類的全限定類名作為 logger name 是最好的策略,這樣能夠追蹤到每一條日志消息的來(lái)源。

appender 和 layout

在 logback 的世界中,日志信息不僅僅可以打印至 console,也可以打印至文件,甚至輸出到網(wǎng)絡(luò)流中,日志打印的目的地由 appender 來(lái)決定,不同的 appender 能將日志信息打印到不同的目的地去。

appender 是綁定在 logger 上的,同時(shí),一個(gè) logger 可以綁定多個(gè) appender,意味著一條信息可以同時(shí)打印到不同的目的地去。例如,常見(jiàn)的做法是,日志信息既輸出到控制臺(tái),同時(shí)也記錄到日志文件中,這就需要為 logger 綁定兩個(gè)不同的 logger。

appender 是綁定在 logger 上的,而 logger 又有繼承關(guān)系,因此一個(gè) logger 打印信息時(shí)的目的地 appender 需要參考它的父親和祖先。在 logback 中,默認(rèn)情況下,如果一個(gè) logger 打印一條信息,那么這條信息首先會(huì)打印至它自己的 appender,然后打印至它的父親和父親以上的祖先的 appender,但如果它的父親設(shè)置了 additivity = false,那么這個(gè) logger 除了打印至它自己的 appender 外,只會(huì)打印至其父親的 appender,因?yàn)樗母赣H的 additivity 屬性置為了 false,開(kāi)始變得忘祖忘宗了,所以這個(gè) logger 只認(rèn)它父親的 appender;此外,對(duì)于這個(gè) logger 的父親來(lái)說(shuō),如果父親的 logger 打印一條信息,那么它只會(huì)打印至自己的 appender中(如果有的話),因?yàn)楦赣H已經(jīng)忘記了爺爺及爺爺以上的那些父輩了。

打印的日志除了有打印的目的地外,還有日志信息的展示格式。在 logback 中,用 layout 來(lái)代表日志打印格式。比如說(shuō),patternlayout 能夠識(shí)別以下這條格式:

%-4relative [%thread] %-5level %logger{32} - %msg%n

然后打印出來(lái)的格式效果是:

176 [main] debug manual.architecture.helloworld2 - hello world.

上面這個(gè)格式的第一個(gè)字段代表從程序啟動(dòng)開(kāi)始后經(jīng)過(guò)的毫秒數(shù),第二個(gè)字段代表打印出這條日志的線程名字,第三個(gè)字段代表日志信息的日志打印級(jí)別,第四個(gè)字段代表 logger name,第五個(gè)字段是日志信息,第六個(gè)字段僅僅是代表一個(gè)換行符。

參數(shù)化打印日志

經(jīng)常能看到打印日志的時(shí)候,使用以下這種方式打印日志:

?
1
logger.debug("the message is " + msg + " from " + somebody);

這種打印日志的方式有個(gè)缺點(diǎn),就是無(wú)論日志級(jí)別是什么,程序總要先執(zhí)行 "the message is " + msg + " from " + somebody 這段字符串的拼接操作。當(dāng) logger 設(shè)置的日志級(jí)別為比 debug 級(jí)別更高級(jí)別時(shí),debug 級(jí)別的信息不回被打印出來(lái)的,顯然,字符串拼接的操作是不必要的,當(dāng)要拼接的字符串很大時(shí),這無(wú)疑會(huì)帶來(lái)很大的性能白白損耗。

于是,一種改進(jìn)的打印日志方式被人們發(fā)現(xiàn)了:

?
1
2
3
if(logger.isdebugenabled()) {
 logger.debug("the message is " + msg + " from " + somebody);
}

這樣的方式確實(shí)能避免字符串拼接的不必要損耗,但這也不是最好的方法,當(dāng)日志級(jí)別為 debug 時(shí),那么打印這行消息,需要判斷兩次日志級(jí)別。一次是logger.isdebugenabled(),另一次是 logger.debug() 方法內(nèi)部也會(huì)做的判斷。這樣也會(huì)帶來(lái)一點(diǎn)點(diǎn)效率問(wèn)題,如果能找到更好的方法,誰(shuí)愿意無(wú)視白白消耗的效率。

有一種更好的方法,那就是提供占位符的方式,以參數(shù)化的方式打印日志,例如上述的語(yǔ)句,可以是這樣的寫法:

?
1
logger.debug("the message {} is from {}", msg, somebody);

這樣的方式,避免了字符串拼接,也避免了多一次日志級(jí)別的判斷。

logback 內(nèi)部運(yùn)行流程

logback 配置詳解(推薦)

當(dāng)應(yīng)用程序發(fā)起一個(gè)記錄日志的請(qǐng)求,例如 info() 時(shí),logback 的內(nèi)部運(yùn)行流程如下所示

  • 獲得過(guò)濾器鏈條
  • 檢查日志級(jí)別以決定是否繼續(xù)打印
  • 創(chuàng)建一個(gè) loggingevent 對(duì)象
  • 調(diào)用 appenders
  • 進(jìn)行日志信息格式化
  • 發(fā)送 loggingevent 到對(duì)應(yīng)的目的地

有關(guān)性能問(wèn)題

關(guān)于日志系統(tǒng),人們討論得最多的是性能問(wèn)題,即使是小型的應(yīng)用程序,也有可能輸出大量的日志。打印日志中的不當(dāng)處理,會(huì)引發(fā)各種性能問(wèn)題,例如太多的日志記錄請(qǐng)求可能使磁盤 io 成為性能瓶頸,從而影響到應(yīng)用程序的正常運(yùn)行。在合適的時(shí)候記錄日志、以更好的方式發(fā)起日志請(qǐng)求、以及合理設(shè)置日志級(jí)別方面,都有可能造成性能問(wèn)題。
關(guān)于性能問(wèn)題,以下幾個(gè)方面需要了解

  • 建議使用占位符的方式參數(shù)化記錄日志
  • logback 內(nèi)部機(jī)制保證 logger 在記錄日志時(shí),不必每一次都去遍歷它的父輩以獲得關(guān)于日志級(jí)別、appender 的信息
  • 在 logback 中,將日志信息格式化,以及輸出到目的地,是最損耗性能的操作

logback 配置

配置須知

配置方式

logback 提供的配置方式有以下幾種:

  1. 編程式配置
  2. xml 格式
  3. groovy 格式

logback 在啟動(dòng)時(shí),根據(jù)以下步驟尋找配置文件:

  1. 在 classpath 中尋找 logback-test.xml文件
  2. 如果找不到 logback-test.xml,則在 classpath 中尋找 logback.groovy 文件
  3. 如果找不到 logback.groovy,則在 classpath 中尋找 logback.xml文件
  4. 如果上述的文件都找不到,則 logback 會(huì)使用 jdk 的 spi 機(jī)制查找 meta-inf/services/ch.qos.logback.classic.spi.configurator 中的 logback 配置實(shí)現(xiàn)類,這個(gè)實(shí)現(xiàn)類必須實(shí)現(xiàn) configuration 接口,使用它的實(shí)現(xiàn)來(lái)進(jìn)行配置
  5. 如果上述操作都不成功,logback 就會(huì)使用它自帶的 basicconfigurator 來(lái)配置,并將日志輸出到 console

logback-test.xml 一般用來(lái)在測(cè)試代碼中打日志,如果是 maven 項(xiàng)目,一般把 logback-test.xml 放在 src/test/resources 目錄下。maven 打包的時(shí)候也不會(huì)把這個(gè)文件打進(jìn) jar 包里。
logback 啟動(dòng)的時(shí)候解析配置文件大概需要 100 毫秒的時(shí)間,如果希望更快啟動(dòng),可以采用 spi 的方式。

默認(rèn)的配置

前面有提到默認(rèn)的配置,由 basicconfiguator 類配置而成,這個(gè)類的配置可以用如下的配置文件來(lái)表示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configuration>
 
 <appender name="stdout" class="ch.qos.logback.core.consoleappender">
 <!-- encoders are assigned the type
  ch.qos.logback.classic.encoder.patternlayoutencoder by default -->
 <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>

啟動(dòng)時(shí)打印狀態(tài)信息

如果 logback 在啟動(dòng)時(shí),解析配置文件時(shí),出現(xiàn)了需要警告的信息或者錯(cuò)誤信息,那 logback 會(huì)自動(dòng)先打印出自身的狀態(tài)信息。

如果希望正常情況下也打印出狀態(tài)信息,則可以使用之前提到的方式,在代碼里顯式地調(diào)用使其輸出:

?
1
2
3
4
5
6
7
public static void main(string[] args) {
 // assume slf4j is bound to logback in the current environment
 loggercontext lc = (loggercontext) loggerfactory.getiloggerfactory();
 // print logback's internal status
 statusprinter.print(lc);
 ...
}

也可以在配置文件中,指定 configuration 的 debug 屬性為 true

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configuration debug="true">
 <appender name="stdout" class="ch.qos.logback.core.consoleappender">
  <!-- encoders are assigned the type ch.qos.logback.classic.encoder.patternlayoutencoder
   by default -->
  <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>

還可以指定一個(gè) listener:

?
1
2
3
4
<configuration>
 <statuslistener class="ch.qos.logback.core.status.onconsolestatuslistener" />
 ... the rest of the configuration file
</configuration>

重置默認(rèn)的配置文件位置

設(shè)置 logback.configurationfile 系統(tǒng)變量,可以通過(guò) -d 參數(shù)設(shè)置,所指定的文件名必須以 .xml 或者 .groovy 作為文件后綴,否則 logback 會(huì)忽略這些文件。

配置文件自動(dòng)熱加載

要使配置文件自動(dòng)重載,需要把 scan 屬性設(shè)置為 true,默認(rèn)情況下每分鐘才會(huì)掃描一次,可以指定掃描間隔:

?
1
2
3
<configuration scan="true" scanperiod="30 seconds" >
 ...
</configuration>

注意掃描間隔要加上單位,可用的單位是 milliseconds,seconds,minutes 和 hours。如果只指定了數(shù)字,但沒(méi)有指定單位,這默認(rèn)單位為 milliseconds。

在 logback 內(nèi)部,當(dāng)設(shè)置 scan 屬性為 true 后,一個(gè)叫做 reconfigureonchangefilter 的過(guò)濾器就會(huì)被牽扯進(jìn)來(lái),它負(fù)責(zé)判斷是否到了該掃描的時(shí)候,以及是否該重新加載配置。logger 的任何一個(gè)打印日志的方法被調(diào)用時(shí),都會(huì)觸發(fā)這個(gè)過(guò)濾器,所以關(guān)于這個(gè)過(guò)濾器的自身的性能問(wèn)題,變得十分重要。logback 目前采用這樣一種機(jī)制,當(dāng) logger 的調(diào)用次數(shù)到達(dá)一定次數(shù)后,才真正讓過(guò)濾器去做它要做的事情,這個(gè)次數(shù)默認(rèn)是 16,而 logback 會(huì)在運(yùn)行時(shí)根據(jù)調(diào)用的頻繁度來(lái)動(dòng)態(tài)調(diào)整這個(gè)數(shù)目。

輸出異常棧時(shí)也打印出 jar 包的信息

這個(gè)屬性默認(rèn)是關(guān)閉,可通過(guò)以下方式開(kāi)啟:

?
1
2
3
<configuration packagingdata="true">
 ...
</configuration>

也可以通過(guò) loggercontext 的 setpackagingdataenabled(boolean) 方法來(lái)開(kāi)啟

 

?
1
2
loggercontext lc = (loggercontext) loggerfactory.getiloggerfactory();
 lc.setpackagingdataenabled(true);

直接調(diào)用 joranconfigurator

joran 是 logback 使用的一個(gè)配置加載庫(kù),如果想要重新實(shí)現(xiàn) logback 的配置機(jī)制,可以直接調(diào)用這個(gè)類 joranconfigurator 來(lái)實(shí)現(xiàn):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package chapters.configuration;
 
import org.slf4j.logger;
import org.slf4j.loggerfactory;
 
import ch.qos.logback.classic.loggercontext;
import ch.qos.logback.classic.joran.joranconfigurator;
import ch.qos.logback.core.joran.spi.joranexception;
import ch.qos.logback.core.util.statusprinter;
 
public class myapp3 {
 final static logger logger = loggerfactory.getlogger(myapp3.class);
 
 public static void main(string[] args) {
 // assume slf4j is bound to logback in the current environment
 loggercontext context = (loggercontext) loggerfactory.getiloggerfactory();
 
 try {
  joranconfigurator configurator = new joranconfigurator();
  configurator.setcontext(context);
  // call context.reset() to clear any previous configuration, e.g. default
  // configuration. for multi-step configuration, omit calling context.reset().
  context.reset();
  configurator.doconfigure(args[0]);
 } catch (joranexception je) {
  // statusprinter will handle this
 }
 statusprinter.printincaseoferrorsorwarnings(context);
 
 logger.info("entering application.");
 
 foo foo = new foo();
 foo.doit();
 logger.info("exiting application.");
 }
}

配置文件格式

配置文件的基本結(jié)構(gòu)

logback 配置詳解(推薦)

根節(jié)點(diǎn)是 configuration,可包含0個(gè)或多個(gè) appender,0個(gè)或多個(gè) logger,最多一個(gè) root。

配置 logger 節(jié)點(diǎn)

在配置文件中,logger 的配置在<logger> 標(biāo)簽中配置,<logger> 標(biāo)簽只有一個(gè)屬性是一定要的,那就是 name,除了name 屬性,還有 level 屬性,additivity 屬性可以配置,不過(guò)它們是可選的。

level 的取值可以是 trace, debug, info, warn, error, all, off, inherited, null, 其中 inherited 和 null 的作用是一樣的,并不是不打印任何日志,而是強(qiáng)制這個(gè) logger 必須從其父輩繼承一個(gè)日志級(jí)別。

additivity 的取值是一個(gè)布爾值,true 或者 false。

<logger> 標(biāo)簽下只有一種元素,那就是 <appender-ref>,可以有0個(gè)或多個(gè),意味著綁定到這個(gè) logger 上的 appender。

配置 root 節(jié)點(diǎn)

<root> 標(biāo)簽和 <logger> 標(biāo)簽的配置類似,只不過(guò) <root> 標(biāo)簽只允許一個(gè)屬性,那就是 level 屬性,并且它的取值范圍只能取 trace, debug, info, warn, error, all, off。
<root> 標(biāo)簽下允許有0個(gè)或者多個(gè) <appender-ref>。

配置 appender 節(jié)點(diǎn)

<appender> 標(biāo)簽有兩個(gè)必須填的屬性,分別是 name 和 class,class 用來(lái)指定具體的實(shí)現(xiàn)類。<appender> 標(biāo)簽下可以包含至多一個(gè) <layout>,0個(gè)或多個(gè) <encoder>,0個(gè)或多個(gè) <filter>,除了這些標(biāo)簽外,<appender> 下可以包含一些類似于 javabean 的配置標(biāo)簽。

<layout> 包含了一個(gè)必須填寫的屬性 class,用來(lái)指定具體的實(shí)現(xiàn)類,不過(guò),如果該實(shí)現(xiàn)類的類型是 patternlayout 時(shí),那么可以不用填寫。<layout> 也和 <appender> 一樣,可以包含類似于 javabean 的配置標(biāo)簽。
<encoder> 標(biāo)簽包含一個(gè)必須填寫的屬性 class,用來(lái)指定具體的實(shí)現(xiàn)類,如果該類的類型是 patternlayoutencoder ,那么 class 屬性可以不填。

如果想要往一個(gè) logger 上綁定 appender,則使用以下方式:

?
1
2
3
4
<logger name="hello" level="debug">
 <appender-ref ref="file" />
 <appender-ref ref="stdout" />
</logger>

設(shè)置 context name

?
1
2
3
4
5
6
7
8
9
10
11
12
<configuration>
 <contextname>myappname</contextname>
 <appender name="stdout" class="ch.qos.logback.core.consoleappender">
 <encoder>
  <pattern>%d %contextname [%t] %level %logger{36} - %msg%n</pattern>
 </encoder>
 </appender>
 
 <root level="debug">
 <appender-ref ref="stdout" />
 </root>
</configuration>

變量替換

在 logback 中,支持以 ${varname} 來(lái)引用變量

定義變量

可以直接在 logback.xml 中定義變量

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<configuration>
 
 <property name="user_home" value="/home/sebastien" />
 
 <appender name="file" class="ch.qos.logback.core.fileappender">
 <file>${user_home}/myapp.log</file>
 <encoder>
  <pattern>%msg%n</pattern>
 </encoder>
 </appender>
 
 <root level="debug">
 <appender-ref ref="file" />
 </root>
</configuration>

也可以通過(guò)大d參數(shù)來(lái)定義

?
1
java -duser_home="/home/sebastien" myapp2

也可以通過(guò)外部文件來(lái)定義

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<configuration>
 
 <property file="src/main/java/chapters/configuration/variables1.properties" />
 
 <appender name="file" class="ch.qos.logback.core.fileappender">
  <file>${user_home}/myapp.log</file>
  <encoder>
  <pattern>%msg%n</pattern>
  </encoder>
 </appender>
 
 <root level="debug">
  <appender-ref ref="file" />
 </root>
</configuration>

外部文件也支持 classpath 中的文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<configuration>
 
 <property resource="resource1.properties" />
 
 <appender name="file" class="ch.qos.logback.core.fileappender">
  <file>${user_home}/myapp.log</file>
  <encoder>
  <pattern>%msg%n</pattern>
  </encoder>
 </appender>
 
 <root level="debug">
  <appender-ref ref="file" />
 </root>
</configuration>

外部文件的格式是 key-value 型。

?
1
user_home=/home/sebastien

變量的作用域

變量有三個(gè)作用域

  • local
  • context
  • system

local 作用域在配置文件內(nèi)有效,context 作用域的有效范圍延伸至 logger context,system 作用域的范圍最廣,整個(gè) jvm 內(nèi)都有效。

logback 在替換變量時(shí),首先搜索 local 變量,然后搜索 context,然后搜索 system。

如何為變量指定 scope ?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<configuration>
 
 <property scope="context" name="nodeid" value="firstnode" />
 
 <appender name="file" class="ch.qos.logback.core.fileappender">
 <file>/opt/${nodeid}/myapp.log</file>
 <encoder>
  <pattern>%msg%n</pattern>
 </encoder>
 </appender>
 
 <root level="debug">
 <appender-ref ref="file" />
 </root>
</configuration>

變量的默認(rèn)值

在引用一個(gè)變量時(shí),如果該變量未定義,那么可以為其指定默認(rèn)值,做法是:

?
1
${aname:-golden}

運(yùn)行時(shí)定義變量

需要使用 <define> 標(biāo)簽,指定接口 propertydfiner 對(duì)應(yīng)的實(shí)現(xiàn)類。如下所示:

?
1
2
3
4
5
6
7
8
9
10
<configuration>
 
 <define name="rootlevel" class="a.class.implementing.propertydefiner">
 <shape>round</shape>
 <color>brown</color>
 <size>24</size>
 </define>
 
 <root level="${rootlevel}"/>
</configuration>

條件化處理配置文件

logback 允許在配置文件中定義條件語(yǔ)句,以決定配置的不同行為,具體語(yǔ)法格式如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- if-then form -->
<if condition="some conditional expression">
<then>
 ...
</then>
</if>
 
<!-- if-then-else form -->
<if condition="some conditional expression">
<then>
 ...
</then>
<else>
 ...
</else>
</if>

示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<configuration debug="true">
 
 <if condition='property("hostname").contains("torino")'>
 <then>
  <appender name="con" class="ch.qos.logback.core.consoleappender">
  <encoder>
   <pattern>%d %-5level %logger{35} - %msg %n</pattern>
  </encoder>
  </appender>
  <root>
  <appender-ref ref="con" />
  </root>
 </then>
 </if>
 
 <appender name="file" class="ch.qos.logback.core.fileappender">
 <file>${randomoutputdir}/conditional.log</file>
 <encoder>
  <pattern>%d %-5level %logger{35} - %msg %n</pattern>
 </encoder>
 </appender>
 
 <root level="error">
  <appender-ref ref="file" />
 </root>
</configuration>

從jndi 獲取變量

使用 <insertfromjndi> 可以從 jndi 加載變量,如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configuration>
 <insertfromjndi env-entry-name="java:comp/env/appname" as="appname" />
 <contextname>${appname}</contextname>
 
 <appender name="console" class="ch.qos.logback.core.consoleappender">
 <encoder>
  <pattern>%d ${context_name} %level %msg %logger{50}%n</pattern>
 </encoder>
 </appender>
 
 <root level="debug">
 <appender-ref ref="console" />
 </root>
</configuration>

文件包含

可以使用 ?include> 標(biāo)簽在一個(gè)配置文件中包含另外一個(gè)配置文件,如下圖所示:

?
1
2
3
4
5
6
7
8
<configuration>
 <include file="src/main/java/chapters/configuration/includedconfig.xml"/>
 
 <root level="debug">
 <appender-ref ref="includedconsole" />
 </root>
 
</configuration>

被包含的文件必須有以下格式:

?
1
2
3
4
5
6
7
<included>
 <appender name="includedconsole" class="ch.qos.logback.core.consoleappender">
 <encoder>
  <pattern>"%d - %m%n"</pattern>
 </encoder>
 </appender>
</included>

支持從多種源頭包含

從文件中包含

?
1
<include file="src/main/java/chapters/configuration/includedconfig.xml"/>

從 classpath 中包含

?
1
<include resource="includedconfig.xml"/>

從 url 中包含

?
1
<include url="http://some.host.com/includedconfig.xml"/>

如果包含不成功,那么 logback 會(huì)打印出一條警告信息,如果不希望 logback 抱怨,只需這樣做:

?
1
<include optional="true" ..../>

添加一個(gè) context listener

loggercontextlistener 接口的實(shí)例能監(jiān)聽(tīng) logger context 上發(fā)生的事件,比如說(shuō)日志級(jí)別的變化,添加的方式如下所示:

?
1
2
3
4
<configuration debug="true">
 <contextlistener class="ch.qos.logback.classic.jul.levelchangepropagator"/>
 ....
</configuration>

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://segmentfault.com/a/1190000008315137

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产成人精品一区二区三区四区 | 亚洲一区亚洲二区 | 无毒黄网 | 亚洲视频1区 | 精品日韩一区二区三区 | 色图自拍偷拍 | 操操网站| 日韩中文字幕在线免费观看 | 欧美xo影院 | 色婷婷一区 | 国产高清视频在线 | 日本在线黄色 | av中文字幕在线播放 | 青春草国产免费福利视频一区 | 欧美日韩在线播放 | 国产一区不卡 | 色呦呦网站在线观看 | 免费看一区二区三区 | www.色综合 | 久久精品国产免费 | 亚洲经典一区 | 久久视频国产 | 日韩欧美视频免费 | 亚洲区视频在线观看 | 色欧美片视频在线观看 | 欧美高清一区 | 国产资源在线免费观看 | 国产成人黄色av | 天堂va久久久噜噜噜久久va | 国产无套丰满白嫩对白 | 黄色免费网站在线观看 | 日韩在线观看中文字幕 | 蜜臀久久精品99国产精品日本 | 国产一区二区在线免费观看 | 欧美一区 | 欧美一区亚洲二区 | 中文字幕一区二区三区久久 | 操操网站 | 久久高清 | 久久视频在线 | 精品欧美一区二区三区久久久 |