-------------------------------------------------------
與spring的配置:
貌似官網上沒有介紹,但是作者在github上建立了一個擴展項目用于logback與spring結合。
目前最新版本是0.1.2,很多maven公開庫里已經有了。
maven配置:
<dependency>
<groupId>org.logback-extensions</groupId>
<artifactId>logback-ext-spring</artifactId>
<version>0.1.2</version>
</dependency>
web.xml配置日志框架啟動監聽器:
<!-- logback配置文件 -->
<context-param>
<param-name>logbackConfigLocation</param-name>
<param-value>/WEB-INF/classes/logback.xml</param-value>
</context-param>
<!-- logback加載監聽器 -->
<listener>
<listener-class>
ch.qos.logback.ext.spring.web.LogbackConfigListener
</listener-class>
</listener>
-------------------------------------------------------
logback中的配置:
可以用java程序配置,也可以用xml或者groovy腳本配置。
使用 http://logback.qos.ch/translator/ 可以把log4j的配置自動轉換過來。
logback內部查找配置的過程:
1,在classpath查找“logback.groovy”
2,在classpath查找“logback-test.xml”
3,在classpath查找“logback.xml”
4,使用自身的BasicConfigurator做基本配置,所有日志被輸出到控制臺。
—— 一般把“logback-test.xml”放到maven的測試路徑,把“logback.xml”放到maven的正式路徑,前者優先級更高。
logback的狀態,加載配置文件的過程:
代碼打印:
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);
配置文件形式打印:
<configuration debug="true">
...
</configuration>
也可以通過設置StatusListener來監聽logback的啟動和打印狀態——在生產環境挺有用,因為配置文件路徑挺深。
通過在系統變量里加入"logback.configurationFile"指定logback配置文件路徑:
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1
設置自動掃描和遇到變更時重新加載配置文件(不指定周期的話默認每1分鐘):
<configuration scan="true" scanPeriod="30 seconds">
...
</configuration>
每當N個(logback會自動調節)日志請求,logback會檢查一下掃描周期是否已經到達,如到達再檢查配置文件。
通過web訪問狀態信息:
在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>
然后訪問:http://host/yourWebapp/lbClassicStatus
注冊控制臺狀態監聽器:
java代碼方式:
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
StatusManager statusManager = lc.getStatusManager();
OnConsoleStatusListener onConsoleListener = new OnConsoleStatusListener();
statusManager.add(onConsoleListener);
用配置文件方式:
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
...
</configuration>
系統變量方式:
java -Dlogback.statusListenerClass=ch.qos.logback.core.status.OnConsoleStatusListener
停止logback:
java代碼方式:
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.stop();
web應用:
ServletContextListener.contextDestroyed()會自動調用上面的stop方法。
-------------------------------------------------------
配置文件格式:
最外層是<configuration>元素,里面有<appender><logger><root>元素
<logger>元素:
level屬性可以這些值:TRACE, DEBUG, INFO, WARN, ERROR, ALL, OFF,也可以明確指定繼承:INHERITED或者NULL
包含若干<appender-ref>元素,指定appender的名字。
從DEBUG改為INFO級別:
<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>
<logger name="chapters.configuration" level="INFO"/>
<!-- Strictly speaking, the level attribute is not necessary since -->
<!-- the level of the root level is set to DEBUG by default. -->
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
-------------------------------------------------------
配置Appender:
name和class屬性
內嵌0個或1個layout元素,0個或多個encoder元素,0個或多個filter元素。還可以內嵌任意數量的appdenter類的屬性(例如自定義的appender類)。
layout元素應該內嵌具體的layout類,但是默認就是PatternLayoutEncoder。
Appender的累加性:
logger會記錄在所有綁定在它自身的appender,同時也會記錄在該logger祖先的appender上,所以有可能重復記錄!
配置Logger Context(可以用在“多個項目寫入同一個日志文件”這種情況):
<configuration>
<contextName>myAppName</contextName>
...
</configuration>
-------------------------------------------------------
變量替換:
<configuration>
<property name="USER_HOME" value="/home/sebastien" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
...
</appender>
...
</configuration>
——上面的變量定義在系統屬性里也可以:java -DUSER_HOME="/home/sebastien" MyApp2
變量也可以定義在文件里:
<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>
...
</appender>
...
</configuration>
——對應路徑的文件里應該加入“USER_HOME=/home/sebastien”
(這路徑挺詭異啊,是maven的結構,那打包后豈不是不能用了?)
像這樣引用classpath的還靠譜些:
<property resource="resource1.properties" />
變量可以指定作用域:local,context,system
變量可以相互引用:
USER_HOME=/home/sebastien
fileName=myApp.log
destination=${USER_HOME}/${fileName}
命名引用:如果"userid"會被替換為"alice",那么"${${userid}.password}"會被替換為"alice.password"對應的值。
變量可以指定默認值:${aName:-golden} ——這就指定了默認值golden
變量的默認值也可以引用變量: "${id:-${userid}}
預置變量:HOSTNAME,CONTEXT_NAME
可以通過timestamp元素定義一個當前的日期和時間的動態元素。
可以自己繼承PropertyDefiner實現動態生成屬性,現在內置了2個動態屬性生成器:
FileExistsPropertyDefiner 如果指定路徑文件存在,則將指定屬性設為“true”,反之亦然
ResourceExistsPropertyDefiner 如果指定資源存在,則將指定屬性設為“true”,反之亦然
條件語句:
<!-- 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>
判斷條件只支持context變量和system變量,用property()或者p()來引用——如果沒有設定對應變量,這兩個方法會返回空串(而不是null)
isDefine()和isNull()分別判斷變量是否設置和變量是否為空。
<if condition='property("HOSTNAME").contains("torino")'>
...
</if>
可以從JNDI讀取變量值(作用域為local)。也可以將從JNDI讀取的變量存入另一個不同作用域的變量。
<configuration>
<insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" />
...
</configuration>
-------------------------------------------------------
文件包含(可以使用相對路徑。當前路徑已經在當前項目中定義,所以沒必要與配置文件路徑關聯):
<configuration>
<include file="src/main/java/chapters/configuration/includedConfig.xml"/>
...
</configuration>
被包含的文件必須用<include>標簽包裹:
<included>
<appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>"%d - %m%n"</pattern>
</encoder>
</appender>
</included>
還可以關聯資源(例如classpath下的某個文件):
<include resource="includedConfig.xml"/>
還可以關聯URL:
<include url="http://some.host.com/includedConfig.xml"/>
可以指定此次文件包含為“可選的”:
<include optional="true" ..../>
-------------------------------------------------------
LoggerContextListener
其中一個實現LevelChangePropagator會監聽日志環境的合適的生命周期,并把日志級別的變化傳播給JUL,這樣JUL關閉的日志不會再傳遞給slf4j,用這種方式對性能沖擊較小,適合jul-to-slf4j的橋接包。