1. 程式人生 > >非常詳細的logback學習筆記

非常詳細的logback學習筆記

Logback介紹

Logback 分為三個模組:CoreClassic  AccessCore模組是其他兩個模組的基礎。 Classic模組擴充套件了core模組。 Classic模組相當於log4j的顯著改進版。Logback-classic 直接實現了 SLF4J API

要引入logback,由於Logback-classic依賴slf4j-api.jarlogback-core.jar,所以要把slf4j-api.jarlogback-core.jarlogback-classic.jar新增到要引入Logbac日誌管理的專案的class path.

Logback

的配置

LoggerAppender Layout

Logback建立於三個主要類之上:LoggerAppender  LayoutLogger類是logback-classic模組的一部分,而AppenderLayout介面來自logback-core。作為一個多用途模組,logback-core 不包含任何logger

Logger作為日誌的記錄器,把它關聯到應用的對應的context上後,主要用於存放日誌物件,也可以定義日誌型別、級別。Appender主要用於指定日誌輸出的目的地,目的地可以是控制檯、檔案、遠端套接字伺服器、MySQL PostreSQL Oracle

和其他資料庫、 JMS和遠端UNIXSyslog守護程序等。Layout 負責把事件轉換成字串,格式化的日誌資訊的輸出。

各個logger 都被關聯到一個 LoggerContextLoggerContext負責製造logger,也負責以樹結構排列各logger

如果 logger的名稱帶上一個點號後是另外一個 logger的名稱的字首,那麼,前者就被稱為後者的祖先。如果logger與其後代 logger之間沒有其他祖先,那麼,前者就被稱為子logger 之父。比如,名為"com.foo"" logger 是名為"com.foo.Bar"之父。root logger 位於

 logger 等級的最頂端,root logger 可以通過其名稱取得,如下所示:

其他所有logger也通過org.slf4j.LoggerFactory 類的靜態方法getLogger取得。 getLogger方法以logger 名稱為引數。用同一名字呼叫LoggerFactory.getLogger 方法所得到的永遠都是同一個logger物件的引用。

有效級別與級別繼承

Logger 可以被分配級別。級別包括:TRACEDEBUGINFOWARN  ERROR,定義於ch.qos.logback.classic.Level類。如果 logger沒有被分配級別,那麼它將從有被分配級別的最近的祖先那裡繼承級別。root logger 預設級別是 DEBUG

列印方法與基本選擇規則

列印方法決定記錄請求的級別。例如,如果 L 是一個 logger 例項,那麼,語句 L.info("..")是一條級別為 INFO 的記錄語句。記錄請求的級別在高於或等於其 logger 的有效級別時被稱為被啟用,否則,稱為被禁用。

記錄請求級別為 p,其 logger的有效級別為 q,只有則當 p>=q時,該請求才會被執行。

該規則是 logback 的核心。級別排序為: TRACE < DEBUG < INFO <WARN < ERROR

LoggerAppenderslayouts的關係

一個 logger 可以被關聯多個 appender。方法 addAppender() 為指定的 logger 新增一個appender。對於 logger 的每個啟用了的記錄請求,都將被髮送到 logger 裡的全部 appender 及更高等級的 appender。換句話說,appender疊加性地繼承了 logger 的層次等級。

Logger L的記錄語句的輸出會發送給 L及其祖先的全部 appender。如果 logger L的某個祖先 P設定疊加性標識為 false,那麼,L的輸出會發送給 P之間(含P)的所有 appender,但不會發送給P的任何祖先的appender

Logger 的疊加性預設為 true。如果希望定製輸出格式。這時為 appender 關聯一個 layout 即可。Layout負責根據使用者意願對記錄請求進行格式化,appender 負責將格式化化後的輸出傳送到目的地。

例如,轉換模式"%-4relative[%thread] %-5level %logger{32} - %msg%n" PatternLayout裡會輸出形如:

176 [main] DEBUGmanual.architecture.HelloWorld2 - Hello world.

第一個欄位是自程式啟動以來的逝去時間,單位是毫秒。

第二個地段發出記錄請求的執行緒。

第三個欄位是記錄請求的級別。

第四個欄位是與記錄請求關聯的 logger 的名稱。

"-"之後是請求的訊息文字。

Logback的預設配置

如果配置檔案 logback-test.xml  logback.xml 都不存在,那麼 logback 預設地會呼叫BasicConfigurator ,建立一個最小化配置。最小化配置由一個關聯到根 logger ConsoleAppender組成。輸出用模式為%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n PatternLayoutEncoder 進行格式化。rootlogger 預設級別是 DEBUG

logback配置檔案

Logback 配置檔案的語法非常靈活。正因為靈活,所以無法用 DTD  XML schema 進行定義。儘管如此,可以這樣描述配置檔案的基本結構:以<configuration>開頭,後面有零個或多個<appender>元素,有零個或多個<logger>元素,有最多一個<root>元素。

Logback預設配置的採用的步驟

1. 嘗試在 classpath 下查詢檔案 logback-test.xml

2. 如果檔案不存在,則查詢檔案 logback.xml

3. 如果兩個檔案都不存在,logback  Bas icConfigurator 自動對自己進行配置,這會導致記錄輸出到控制檯。

假設配置檔案 logback-test.xml  logback.xml 都不存在,那麼 logback 預設地會呼叫BasicConfigurator ,建立一個最小化配置。最小化配置由一個關聯到根 logger ConsoleAppender組成。輸出用模式為%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n PatternLayoutEncoder 進行格式化。還有,根 logger 預設級別是 DEBUG

最簡單的配置方法就是使用預設配置。以下是logbackBasicConfigurator 配置的簡單例子:

package com.ttpod.chapters.configuration;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

publicclass MyApp1 {

finalstatic Logger logger = LoggerFactory.getLogger(MyApp1.class);

publicstaticvoid main(String[] args) {

logger.info("Entering application.");    //進行另一個application

Foo foo = new Foo();

foo.doIt();        //執行其它中的日誌輸出方法

logger.info("Exiting application.");    //退出另一個application

}

}

該類定義了一個靜態變數 logger,然後例項化一個 Foo 物件。Foo 類如下

package com.ttpod.chapters.configuration;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

publicclass Foo {

staticfinal Logger logger = LoggerFactory.getLogger(Foo.class);

publicvoid doIt() {

logger.debug("Did it again!");    //定義一個debug級別的日誌輸出

}

    …………

}

自動列印警告和錯誤訊息

當解析配置檔案有警告或出錯時,logback 會在控制檯上自動列印狀態資料。如果沒有警告或錯誤,還是想檢查logback 的內部狀態的話,可以呼叫 StatusPrinter  print()方法。示例如下:

finalstatic Logger logger = LoggerFactory.getLogger(MyApp2.class);

publicstaticvoid main(String[] args) {

// 在當前環境中假設 SLF4J 已經被繫結到logback

LoggerContextlc = (LoggerContext) LoggerFactory.getILoggerFactory();

// 列印logback的內部狀態

StatusPrinter.print(lc);

…………

}

}

對應的配置檔案:

<?xmlversion="1.0"encoding="UTF-8"?>

<configuration>

<!--定義一個名為STDOUTappender,並將其關聯到ch.qos.logback.core.ConsoleAppender-->

<appendername="STDOUT"

class="ch.qos.logback.core.ConsoleAppender">

<!-- encoders 作用是將logger事件轉換成位元組陣列,並將位元組陣列寫入到輸出流-->

<encoder>

<!--格式化輸出:%d表示日期,%thread表示執行緒名,%-5level:級別從左顯示5個字元寬度

%msg:日誌訊息,%n是換行符-->

<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>

</encoder>

</appender>

<rootlevel="debug">    <!-- root logger,定義級別為debug-->

<appender-refref="STDOUT"/>    <!--將名為STDOUTappender新增到root logger-->

</root>

</configuration>

控制檯輸出結果如下:

…………

20:12:33,359|-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT findresource [logback.groovy]

20:12:33,359|-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT findresource [logback-test.xml]

20:12:33,359|-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource[logback.xml] at[file:/D:/Workspaces/MyEclipse%208.5/logback_test/WebRoot/WEB-INF/classes/logback.xml]

20:12:33,484|-INFO in ch.qos.logback.core.joran.action.AppenderAction - About toinstantiate appender of type [ch.qos.logback.core.ConsoleAppender]

20:12:33,484|-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as[STDOUT]

20:12:33,500|-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assumingdefault type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for[encoder] property

20:12:33,593|-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting levelof ROOT logger to DEBUG

20:12:33,593|-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attachingappender named [STDOUT] to Logger[ROOT]

20:12:33,593|-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End ofconfiguration.

20:12:33,593|-INFO in [email protected] - Registeringcurrent configuration as safe fallback point

…………

Logback自定義配置

配置root logger

<root>元素配置根 logger。該元素有一個 level屬性。沒有 name 屬性,因為已經被命名為"ROOT"Level 屬性的值大小寫無關,其值為下面其中一個字串:TRACEDEBUGINFOWARNERRORALLOFF。注意不能設定為"INHERITED" "NULL" <logger>元素可以包含零個或多個<appender-ref>元素。<logger>元素類似,宣告<root>元素後,會先關閉然後移除全部當前 appender,只引用聲明瞭的appender。如果 root 元素沒有引用任何 appender,就會失去所有 appender

假設我們不想看到"com.ttpod.file"包裡的任何元件的任何 DEBUG 資訊,可以設定如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<configuration>

<appendername="STDOUT"class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>

%d{HH:mm:ss.SSS}[%thread] %-5level %logger{36} - %msg%n

     </pattern>

</encoder>

    </appender>

    <!-- 設定configuration下的logger的級別為INFO,預設是繼承root loggerdebug級別 -->

    <loggername="chapters.configuration"level="INFO"/>

    <!-- 嚴格來說, root logger level屬性沒有必要設定,因為 -->

    <!-- root logger的級別被預設設定為DEBUG -->

    <rootlevel="DEBUG">

        <!--

root標籤內沒有引入chapters.configuration,所有在此包下不會

顯示任何元件的任何 DEBUG 資訊

        -->

        <appender-refref="STDOUT"/>    <!-- appender引入到root logger-->

    </root>

</configuration>

注意:由名為"chapters.configuration.Foo" logger 生成的 DEBUG 級別的資訊都被遮蔽了.同樣,也可以為任意數量的 logger 設定級別。

配置 Appenders

Appender <appender>元素配置,該元素必要屬性 name  class name 屬性指定 appender 的名稱,class 屬性指定 appender 類的全限定名。 <appender>元素可以包含零個或多個<layout>元素、零個或多個<encoder>元素和零個或多個<filter>元素。除了這三個常用元素之外,還可以包含 appender 類的任意數量的 javabean

屬性。下圖演示了常用結構,注意對 javabean 屬性的支援在圖中不可見。

記錄輸出到多個 appender 很簡單,先定義各種 appender,然後在 logger 裡進行引用,就行了。如下面的配置檔案所示:

<configuration>

    <appendername="FILE"class="ch.qos.logback.core.FileAppender">

        <file>myApp.log</file>

<!-- encodersare assigned by default the type

ch.qos.logback.classic.encoder.PatternLayoutEncoder-->

<encoder>

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

</encoder>

    </appender>

    <appendername="STDOUT"class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>%msg%n</pattern>

</encoder>

    </appender>

    <rootlevel="debug">

        <appender-refref="FILE"/>

        <appender-refref="STDOUT"/>

    </root>

</configuration>

該配置檔案定義了兩個 appender,分別是"FILE"和"STDOUT"。"FILE"這個 appender 把記錄輸出到檔案"myapp.log ",它的 encoder PatternLayoutEncoder,輸出了日期、級別、執行緒名、logger 名、檔名及記錄請求的行號、訊息和行分隔符。"STDOUT"這個 appender 把記錄輸出到控制檯,它的 encoder 只是輸出訊息和行分隔符。 myApp.log檔案內容如下:

2011-12-2516:56:48,593 INFO [main] c.t.c.c.MyApp3 [MyApp3.java:48] Entering application.

2011-12-2516:56:48,593 DEBUG [main] c.t.c.c.Foo [Foo.java:24] Did it again!

2011-12-2516:56:48,593 INFO [main] c.t.c.c.MyApp3 [MyApp3.java:52] Exiting application.

注意每個 appender 都有自己的 encoderEncoder 通常不能被多個 appender 共享,layout也是。所以,logback 的配置檔案裡沒有共享 encoder  layout 的語法。

Appender累積

預設情況下,appender 是可累積的:logger 會把記錄輸出到它自身的 appender 和它所有祖先的appender。因此,把同一 appender 關聯到多個 logger 會導致重複輸出,如下面的配置檔案會導致重複的輸出:

<configuration>

    <appendername="STDOUT"

class="ch.qos.logback.core.ConsoleAppender">

        <encoder>

            <pattern>

                %d{HH:mm:ss.SSS}[%thread] %-5level %logger{36} - %msg%n

            </pattern>

</encoder>

    </appender>

    <loggername="chapters.configuration">

        <appender-refref="STDOUT"/>

    </logger>

    <rootlevel="debug">

        <appender-refref="STDOUT"/> <!—這會導致重複輸出-->

    </root>

</configuration>

輸出結果如下:

20:53:29.328[main] INFO c.t.chapters.configuration.MyApp2 - Entering application.

20:53:29.328[main] INFO c.t.chapters.configuration.MyApp2 - Entering application.

20:53:29.328[main] DEBUG com.ttpod.chapters.configuration.Foo - Did it again!

20:53:29.328[main] DEBUG com.ttpod.chapters.configuration.Foo - Did it again!

20:53:29.328[main] INFO c.t.chapters.configuration.MyApp2 - Exiting application.

20:53:29.328[main] INFO c.t.chapters.configuration.MyApp2 - Exiting application.

覆蓋預設的累積行為

如果你覺得預設的累積行為不合適,可以設定疊加性標識為 false 以關閉它。這樣的話,logger 樹裡的某個分支可以輸出到與其他 logger 不同的 appender

示例:疊加性標識

<configuration>

    …………

    <loggername="com.ttpod.chapters.configuration.Foo"additivity="false">

        <appender-refref="FILE"/>

    </logger>

    <rootlevel="debug">

        <appender-refref="STDOUT"/>

    </root>

</configuration>

輸出結果:

Enteringapplication.

Exitingapplication.

此例中,logger"chapters.configuration.Foo"關聯 appender"FILE",它的疊加性標記為false,這樣它的記錄輸出僅會被髮送到 appender"FILE",不會被髮送到更高 logger 等級關聯的 appender。其他logger 不受此影響。用 additivityFlag.xml 配置 MyApp3,執行後,控制檯上由輸出由"chapters.configuration.MyApp3"產生的記錄。而 logger"chapters.configuration.Foo"將且僅僅將輸出到檔案 foo.log

Layout格式化輸出日誌

配置自定義 layout

 MySampleLayout LayoutWrappingEncoder 例項傳遞給FileAppender。下面是配置檔案:

它和C語言的printf方法非常類似。格式轉換由普通字元和轉換字元組合而成。轉換字元由%開始,緊跟著的是可選的格式修飾符和轉換字元標示。使用%字首的表示符號將被轉換到實際的內容。如name, level, date, thread name.可用的轉換符有:

轉換符

描述

呼叫日誌事件的所在記錄器的名字,如一個logger的名字是my.test.bbb.ccc,呼叫的是WARN級別的日誌輸出,那麼輸出的是輸出my.test.bbb.ccc,可以在其右邊指定了精度,如%c{2}那麼輸出的是bbb.ccc

呼叫日誌事件的所在的類名,和c轉換符一樣,可以在右邊指定寬度,如%C{2}輸出%C{2}

日誌呼叫所發生的時間,日期格式在其後跟著的大括號內的格式指定如%d{yyyy-MM-dd HH:mm:ss},我現在輸出的結果是2011-07-11 21:05:22,推薦使用的是log4j本身提供的日期格式,如%d{ISO8601},%d{ABSOLUTE},%d{DATE}

所處所在檔名,如上面說C轉換符的例子,輸出結果是LayoutTest.java

是的日誌事件發生的