既然使用Logback南窗,應(yīng)該對它多些了解(一)

1. 打印logback的內(nèi)部狀態(tài)信息

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.util.StatusPrinter;

public class HelloWorld2 {

  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger("chapters.introduction.HelloWorld2");
    logger.debug("Hello world.");

    // print internal state
    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
    StatusPrinter.print(lc);
  }
}

沒有添加任何的配置文件下,將會 輸出:

12:49:22.203 [main] DEBUG chapters.introduction.HelloWorld2 - Hello world.
12:49:22,076 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
12:49:22,078 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration.

從這里可以看出郎楼,它沒有找到logback的配置文件万伤,就會使用一個(gè)默認(rèn)的配置,其實(shí)默認(rèn)的配置中只會給root添加一個(gè)ConsoleAppender 呜袁。

2. logger命名具有層級性

在logback中敌买,logger的命名可以使用點(diǎn)(.)分開,表示層級性阶界,比如“com”,“com.xinyues”虹钮,這表示com是com.xinyues的父層。每個(gè)logger都需要一個(gè)level的配置膘融,如果某個(gè)logger沒有配置level芙粱,就會使用父logger的level,在最頂層的logger名字是root氧映,如果它沒有配置level春畔,就會給他一個(gè)默認(rèn)的level,它的值是debug岛都。


logger level 層級

3. 相同名字的logger在系統(tǒng)中只有一個(gè)實(shí)例

比如:

Logger x = LoggerFactory.getLogger("wombat"); 
Logger y = LoggerFactory.getLogger("wombat");

這里面的x和y獲得的是同一個(gè)Logger實(shí)例律姨。

4. 日志輸出的添加性(additivity)

默認(rèn)情況下,一個(gè)日志logger的輸出內(nèi)容臼疫,會發(fā)送到這個(gè)日志logger和它上層日志logger的appender中择份,這個(gè)就是日志的appender additivity特性。

但是烫堤,比如荣赶,有一個(gè)logger的名字是com.xinyues凤价,還有一個(gè)logger的名字是com,com是com.xinyues的上層logger讯壶,如果com的logger設(shè)置了additivity為false料仗,那么com.xinyues的日志輸入就不會發(fā)送到com的appender之中了。

5. 指定logback的配置文件位置

  1. 在system property中指定
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1
  1. 在代碼中設(shè)置
System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, "/path/to/config.xml");

在句代碼必須放在打印第一條日志之前伏蚊。

6. 當(dāng)logback配置發(fā)生變化時(shí)立轧,自動加載最新配置

默認(rèn)是1分鐘檢測一次配置文件是否變化:

<configuration scan="true"> 
  ... 
</configuration> 

也可以指定時(shí)間,時(shí)間單位可以是:milliseconds, seconds, minutes or hours,如下所示:

<configuration scan="true" scanPeriod="30 seconds" > 
  ...
</configuration> 

注意躏吊,如果不指定時(shí)間單位氛改,將會按毫秒處理。

7. 同一條日志比伏,可以打印到多個(gè)Appender之中

<configuration>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>myApp.log</file>

    <encoder>
      <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
    </encoder>
  </appender>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="FILE" />
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

在這個(gè)配置文件中胜卤,配置了兩個(gè)Appender,它們配置了兩個(gè)不同的encoder赁项,通過logger的appender-ref關(guān)聯(lián)到這兩個(gè)Appender葛躏,注意,每一個(gè)Appender都有它自己的encoder悠菜,ecoder一般不會在多個(gè)Appender中共享使用舰攒,layout也是如此。

8. 日志重復(fù)打印的問題

默認(rèn)情況下悔醋,Appender是累加的:一個(gè)logger默認(rèn)會綁定它自己appender-ref的appender摩窃,同時(shí),也會繼承這個(gè)logger上級的所有的appender芬骄,并且相同名字的appender不會覆蓋猾愿。這就會導(dǎo)致,一條日志被打印的時(shí)候账阻,如果日志級別相同蒂秘,就會在logger的自己的appender中打印一次,又會在它上級的logger綁定的appender中打印一次淘太,如下所示:

<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>

如果在chapters.configuration包下面有類要打印日志材彪,運(yùn)行的時(shí)候,會輸出:

14:25:36.343 [main] INFO  chapters.configuration.MyApp3 - Entering application.
14:25:36.343 [main] INFO  chapters.configuration.MyApp3 - Entering application.
14:25:36.359 [main] DEBUG chapters.configuration.Foo - Did it again!
14:25:36.359 [main] DEBUG chapters.configuration.Foo - Did it again!
14:25:36.359 [main] INFO  chapters.configuration.MyApp3 - Exiting application.
14:25:36.359 [main] INFO  chapters.configuration.MyApp3 - Exiting application.

這是因?yàn)镾TDOUT被綁定到了兩個(gè)logger上面琴儿,因?yàn)閞oot logger是所有的logger的上級,而 chapters.configuration又是當(dāng)前類的logger上級嘁捷,所以會在 chapters.configuration的logger中打印一次造成,同時(shí)又在root的logger中打印一次。
logback的這種特性并不是一個(gè)無用的設(shè)置雄嚣,相反晒屎,它是非常有用的喘蟆,比如,在開發(fā)中鼓鲁,不同的模塊可能會將日志打印到不同的appender之中蕴轨,但是在開發(fā)階段,又希望所有的日志都在console中打印骇吭,可以這樣配置:

<configuration>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>myApp.log</file>
    <encoder>
      <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
    </encoder>
  </appender>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

  <logger name="chapters.configuration">
    <appender-ref ref="FILE" />
  </logger>

  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

這樣配置橙弱,chapters.configuration一的日志既會打印到FILE的appender之中,又會在console中打印一次燥狰,方便開發(fā)調(diào)試棘脐。

但是在有些開發(fā)環(huán)境中,你不需要這種特性龙致,只想讓日志打印到logger自己的appender之中蛀缝,可以在logger中,將additivity屬性設(shè)置為false即可目代。如下配置所示:

<configuration>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>foo.log</file>
    <encoder>
      <pattern>%date %level [%thread] %logger{10} [%file : %line] %msg%n</pattern>
    </encoder>
  </appender>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

  <logger name="chapters.configuration.Foo" additivity="false">
    <appender-ref ref="FILE" />
  </logger>

  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

9. 公共變量定義

在logback的配置文件中屈梁,可以自定義一些公共變量,然后在使用的地方直接引用變量名即可榛了。如下所示:

<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>

在配置文件開頭定義了USER_HOME變量在讶,就可以在其它地方以${USER_HOME}的方式引用。

logback的變量值也可以從Java的System Property中獲取忽冻,而不需要在配置文件中寫死真朗。如果在配置文件中找不到定義的變量,它將自動從System properties中找查僧诚,System properties可以在進(jìn)程運(yùn)行時(shí)指定:

java -DUSER_HOME="/home/sebastien" MyApp2

另外遮婶,如果變量參數(shù)比較多,也可以把這些變量統(tǒng)一配置到一個(gè)指定的.properties文件中湖笨,然后在logback的配置文件中指定變量的配置文件即可旗扑。
例如變量配置文件內(nèi)容是(/src/main/resources/chapters/configuration/variables1.properties):

USER_HOME=/home/sebastien

logback的配置則為:

<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下面,可以省略路徑慈省,直接使用:

<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>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末臀防,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子边败,更是在濱河造成了極大的恐慌袱衷,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笑窜,死亡現(xiàn)場離奇詭異致燥,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)排截,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門嫌蚤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辐益,“玉大人,你說我怎么就攤上這事脱吱≈钦” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵箱蝠,是天一觀的道長续捂。 經(jīng)常有香客問我,道長抡锈,這世上最難降的妖魔是什么疾忍? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮床三,結(jié)果婚禮上一罩,老公的妹妹穿的比我還像新娘。我一直安慰自己撇簿,他們只是感情好聂渊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著四瘫,像睡著了一般汉嗽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上找蜜,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天饼暑,我揣著相機(jī)與錄音,去河邊找鬼洗做。 笑死弓叛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诚纸。 我是一名探鬼主播撰筷,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼畦徘!你這毒婦竟也來了毕籽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤井辆,失蹤者是張志新(化名)和其女友劉穎关筒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杯缺,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡平委,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了夺谁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廉赔。...
    茶點(diǎn)故事閱讀 38,814評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖匾鸥,靈堂內(nèi)的尸體忽然破棺而出蜡塌,到底是詐尸還是另有隱情,我是刑警寧澤勿负,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布馏艾,位于F島的核電站,受9級特大地震影響奴愉,放射性物質(zhì)發(fā)生泄漏琅摩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一锭硼、第九天 我趴在偏房一處隱蔽的房頂上張望房资。 院中可真熱鬧,春花似錦檀头、人聲如沸轰异。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搭独。三九已至,卻和暖如春廊镜,著一層夾襖步出監(jiān)牢的瞬間牙肝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工嗤朴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留配椭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓播赁,卻偏偏與公主長得像颂郎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子容为,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容