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岛都。
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的配置文件位置
- 在system property中指定
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1
- 在代碼中設(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>