-------------------------------------------------------
与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的桥接包。