日志框架-logback配置
logback配置
配置加载顺序
logback可以通过程序配置,也可以通过xml或者groovy文件配置。如果之前使用log4j.properties配置,可以通过log4j.properties Translator转换成logback.xml配置。
配置优先级顺序:
- 通过SPI机制,从classpath的
META-INF\services\ch.qos.logback.classic.spi.Configurator(内容为实现类的全限定名)文件中获取Configurator的实现。 - 如果没有自定义
Configurator,将使用DefaultJoranConfigurator作为默认配置类。DefaultJoranConfigurator也需要通过SPI方式提供。 - 尝试查找classpath下的
logback-test.xml文件 - 尝试查找classpath下的
logback.xml文件 - 如果以上均未成功,使用
BasicConfigurator,将日志输出到控制台。
自定义配置文件位置
通过指定系统属性logback.configurationFile 的值,可以自定义配置文件的位置。该值可以是一个url,或者是classpath路径下的资源文件,或者是应用的之外的文件。
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1
当然也可以通过程序指定
import ch.qos.logback.classic.util.ContextInitializer;
public class ServerMain {
public static void main(String args[]) throws IOException, InterruptedException {
// must be set before the first call to LoggerFactory.getLogger();
// ContextInitializer.CONFIG_FILE_PROPERTY is set to "logback.configurationFile"
System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, "/path/to/config.xml");
...
}
}
日志等级
trace<debug<info<warn<error
等级继承规则
通常logger都会被分配等级(TRACE, DEBUG, INFO, WARN and ERROR)。如果没有指定,那么会从它最近的父级继承一个指定的等级。
logger命名的层次结构
一个父级的logger它的name后加上’.’是子logger的name前缀。
简单选择规则
一次日志记录请求(通过logger实体调用info,debug等方法)是否有效取决于记录的日志等级是否高于或等于logger的有效等级。因此会有下图所示的结果:

按照文章一开始的xml配置,在com.nikola 程序包中增加如下代码。会看到debug和info的日志记录有效,trace无效。
logger.trace("here is trace");
logger.debug("here is debug");
logger.info("here is info");
xml配置方式
logback.xml可以参考如下配置:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration scan="true" scanPeriod="60 seconds" >
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<property name="LOG_HOME" value="/logs/be-kami/spring-test"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow} %-5level [%thread] %clr(%logger{15}){blue} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/spring-demo.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${LOG_HOME}/spring-demo-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
<maxFileSize>100MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
<logger name="com.nikola" level="debug" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</logger>
</configuration>
配置文件语法
logback不提供像DTD或者schema这样的语法文件规范,官方说配置非常灵活,但实际上很难找到比较全的配置规则。。。配置文件格式如下图所示,最外层为configuration标签,内部包含0或多个appender 标签,0或多个logger 标签,最多一个root标签。从0.9.17版本之后,标签不再区分大小写(但是xml标签前后对应的规则还是必须满足的)。

configuration
| 属性 | 值 | 描述 |
|---|---|---|
| scan | true/false | 是否扫描配置文件变更,扫描周期默认一分钟。 |
| scanPeriod | 单位为:milliseconds, seconds, minutes or hours。 | 配置文件扫描周期 |
| like: 30 seconds |
如果不设置扫描时间单位,则默认使用milliseconds 。这种规则通常不合理,因此修改扫描时间切勿忘记时间单位。
使用该属性会启用ReconfigureOnChangeTask ,该任务会在单独的线程中运行,检测你的配置文件是否发生变更。如果配置文件包含xml语法错误,会自动回退到上一次没有错误的配置。
| 属性 | 值 | 描述 |
|---|---|---|
| packagingData | true/false | 是否包含包信息 |
当程序出错的时候,启动packagingData 会打印报错的堆栈所在的包信息。
shutdownHook
安装JVM关机钩子是关闭logback和释放相关资源的一种便捷方式。(通过class 属性,可以自定义shutdown hook)
DefaultShutdownHook 是默认的shutdown hook,停止jvm时在指定的延迟(默认0)之后停止logback上下文。添加shutdown hook,允许后台运行的日志文件压缩任务30秒之内完成。
在web服务中,会自动添加webShutdownHook,不用额外增加<shutdownHook/> 。
LogbackServletContainerInitializer 是ServletContainerInitializer 接口的实现。这个初始化器会依次实例化LogbackServletContextListener 。监听器在web应用停止或重启时会停止日志上下文。
通过设置logbackDisableServletContainerInitializer 属性值为true,可以停止LogbackServletContextListener 的自动装载。该属性也可以通过设置系统属性的方式配置。
<web-app>
<context-param>
<param-name>logbackDisableServletContainerInitializer</param-name>
<param-value>true</param-value>
</context-param>
....
</web-app>
contextName
每个日志配置都有一个对应的上下文名称,该名称可以通contextName 标签进行配置。如果不进行配置,默认名称使用default。
下面的使用方法,会将上下文名称打印到日志中,用于区分不同的环境。
<configuration>
<contextName>myAppName</contextName>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %contextName [%t] %level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
logger配置
logger标签必须含有一个name属性,一个可选的level 属性,一个可选的additivity属性。
| 属性 | 值 | 含义 |
|---|---|---|
| name | logger命名,参考命名的层次结构 | |
| level | TRACE, DEBUG, INFO, WARN, ERROR, ALL, OFF, INHERITED, NULL (大小写均可) | 当前logger的日志等级 |
| additivity | true/false |
日志级别INHERITED或其同义词NULL,将强制logger的级别从层次结构中更高的地方继承过来。
logger标签包含0个或者多个appender-ref标签元素,这样引用的每个appender都会被添加到命名的logger中。注意,与log4j不同的是,logback-classic在配置一个给定的logger时,不会关闭或删除任何先前引用的appender。
root标签配置
root只有一个level属性,并且该属性值不能为INHERITED,NULL 。
和logger一样root也包含0或多个appender-ref 子元素标签。
appender配置
包含两个必须的属性name,class。name属性特指appender的名称,而class属性特指appender类的全限定名,用于实例化该类。
appender包含最多一个layout标签,0或多个encoder,filter标签

layout标签含有一个class必填属性,值为类的全限定名。layout可以含有其他元素,在layout类的实例化时作为属性填充。如果使用PatternLayout 那么属性可以通过默认映射进行指定,因此可以不用进行配置。
encoder 标签也含有一个class必填属性,值为类的全限定名。encoder也可以含有其他元素,在encoder类的实例化时作为属性填充。如果使用PatternLayoutEncoder那么属性可以通过默认映射进行指定,因此可以不用进行配置。
日志记录到多个appender很容易实现,直接定义多个appender,然后将他们指定到对应的logger就可以。
<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>
此处定义了FILE和STDOUT ,并将他们指定给root 。FILE将日志输出到myApp.log文件中,STDOUT会在控制台打印出日志。
默认类映射
在logback-classic模块中,有一些内部规则,将父类和属性名映射到默认的类。

以上映射规则可能发生改变,具体查看代码JoranConfigurator (qos.ch)中的addDefaultNestedComponentRegistryRules 方法。最终可以找到如下代码。

appender的累加性
默认情况下,appender是叠加的。如果logger和它的父级logger同时使用相同的appender,那么打印的日志将会出现重复。
如下代码在打印chapters.configuration 包下的日志时将会出现重复。
<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>
一般情况下,我们希望通过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>
<logger name="chapters.configuration">
<appender-ref ref="FILE" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
所有的日志通过控制台打印,chapters.configuration 下的日志将会额外打印到文件中。
通过设置logger标签的additivity属性为false可以禁止日志叠加。使用该属性,相应日志会通过logger自己的appender输出,即使存在父级logger也不会使用父级的appender输出日志。
<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>
按照如上配置chapters.configuration.Foo 中的日志将不会打印到控制台,即使存在root配置。
如果我们希望它输出到控制台,只需要在其下添加STDOUT 即可。
文件引入
Joran支持从其他文件中引入部分配置。通过include标签实现。
include的值可以是文件,资源或者是url。
引用文件,使用file属性
<configuration> <include file="src/main/java/chapters/configuration/includedConfig.xml"/> <root level="DEBUG"> <appender-ref ref="includedConsole" /> </root> </configuration>引用资源,使用resource属性
<include resource="includedConfig.xml"/>引用url,使用url属性
<include url="http://some.host.com/includedConfig.xml"/>
如果无法找到需要引用的文件,logback会打印异常信息,将optional 属性设置为true可以避免警告。
目标文件必须将它的标签嵌套在included标签中。
<included>
<appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>"%d - %m%n"</pattern>
</encoder>
</appender>
</included>
上下文监听器
[LoggerContextListener](https://logback.qos.ch/xref/ch/qos/logback/classic/spi/LoggerContextListener.html#LoggerContextListener) 接口的实现会监听logger上下文生命周期的各种事件。``
JMXConfigurator
允许通过JMX进行配置logback。
<configuration> <jmxConfigurator /> </configuration>LevelChangePropagator
可以将任何logback-classic日志记录器的级别变化传播到java.util.logging框架中(?)
Chapter 3: Configuration (qos.ch)
<configuration debug="true"> <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/> <!-- rest of the configuration file .... --> </configuration>SequenceNumberGenerator
Logback支持一个序列号字段,在事件创建时自动填充。这个字段是由连接到日志上下文的序列号生成器提供的。
<configuration> <sequenceNumberGenerator class="ch.qos.logback.core.spi.BasicSequenceNumberGenerator"/> <!-- rest of the configuration file .... --> </configuration>





