参考资料
一、基本规则
使用
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
//logger定义
package org.slf4j;
public interface Logger {
public void trace(String message);
public void debug(String message);
public void info(String message);
public void warn(String message);
public void error(String message);
}
logger打印规则
如果一条的日志的打印级别大于 logger 的有效级别,该条日志才可以被打印出来。这条规则总结如下:
日志的打印级别为 p,Logger 实例的级别为 q,如果 p >= q,则该条日志可以打印出来。
这条规则是 logbakc 的核心。各级别的排序为:TRACE < DEBUG < INFO < WARN < ERROR。
举例
ch.qos.logback.classic.Logger logger =
(ch.qos.logback.classic.Logger)LoggerFactory.getLogger("com.foo");
// 设置 logger 的级别为 INFO
logger.setLevel(Level.INFO);
// 这条日志可以打印,因为 WARN >= INFO
logger.warn("警告信息");
// 这条日志不会打印,因为 DEBUG < INFO
logger.debug("调试信息");
appender叠加规则
如果 root logger 添加了一个 console appender,所有允许输出的日志至少会在控制台打印出来。如果再给一个叫做 L 的 logger 添加了一个 file appender,那么 L 以及 L 的子级 logger 都可以在文件和控制台打印日志。可以通过设置 additivity = false 来改写默认的设置,这样 appender 将不再具有叠加性。
提前判定,避免损耗
if(logger.isDebugEnabled()) {
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}
更优的日志格式化
下面两行输出的结果是一样的,但是一旦禁止日志打印,第二个变量的性能至少比第一个变量好上 30 倍。
logger.debug("The new entry is " + entry + "."); //不推荐
logger.debug("The new entry is {}", entry);
logger.debug("The new entry is {}, It replaces {}.", entry, oldEntry);//使用两个参数的例子
Object[] paramArray = {newVal, below, above};
logger.debug("Value {} was inserted between {} and {}.", paramArray);//使用三个或三个以上的参数
一、配置相关
自动化配置logback.xml
以下是 logback 的初始化步骤:
- logback 会在类路径下寻找名为 logback-test.xml 的文件。
- 如果没有找到,logback 会继续寻找名为 logback.groovy 的文件。
- 如果没有找到,logback 会继续寻找名为 logback.xml 的文件。
- 如果没有找到,将会通过 JDK 提供的 ServiceLoader 工具在类路径下寻找文件 META-INFO/services/ch.qos.logback.classic.spi.Configurator,该文件的内容为实现了
Configurator
接口的实现类的全限定类名。- 如果以上都没有成功,logback 会通过BasicConfigurator为自己进行配置,并且日志将会全部在控制台打印出来。
最后一步的目的是为了保证在所有的配置文件都没有被找到的情况下,提供一个默认的(但是是非常基础的)配置。
下面的配置等同于通过 BasicConfigurator进行配置
<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>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
在警告或错误的情况下自动打印状态信息
编码方式实现
LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);
配置方式实现,增加debug="true"
<configuration debug="true"></configuration>
等效配置
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<!-- 剩下的配置跟之前的相同 -->
</configuration>
区别:
但是,如果配置文件没有被找到,logback 不会打印它的内部状态信息,因为没有检测到错误。通过编码方式调用 StatusPrinter.print() 方法会在任何情况下都打印状态信息。
当配置文件更改时,自动加载
<!-- 默认情况下,一分钟扫描一次配置文件,看是否有更改。通过 <configuration> 标签上的 scanPeriod 属性可以指定扫描周期。扫描周期的时间单位可以是毫秒、秒、分钟或者小时-->
<configuration scan="true" scanPeriod="30 seconds">
</configuration>
当设置了 scan="true"
,会新建一个 ReconfigureOnChangeTask 任务用于监视配置文件是否变化。ReconfigureOnChangeTask
也会自动监视外部文件的变化。
查看内部状态信息
logback-classic 包含一个名叫 ViewStatusMessagesServlet 的 servlet。这个 servlet 打印当前 LoggerContext 的 StatusManager 的内容,通过 html 进行输出。
在 WEB-INF/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 进行访问。
配置 <logger> 标签
【must】 name 属性
【option】 level 属性
【option】 additivity 属性
【0-n】<appender-ref> 元素
配置<root> 元素
【option】 level 属性
【0-n】<appender-ref> 元素
<logger name="chapters.configuration" level="INFO" />
<logger name="chapters.configuration.Foo" level="DEBUG" />
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
与 log4j 不同的是,logbakc-classic 不会关闭或移除任何之前在 logger 上定义好的的 appender。
配置<appender> 元素
【must】 name】、class 属性
【0-n】<layout>、<filter>、<encoder> 元素
<layout>
元素强制一个 class 属性去指定一个类的全限定名,用于实例化。与<appender>
元素一样,<layout>
元素也可以包含与 layout 实例相关的属性。如果 layout 的 class 是PatternLayout
,那么 class 属性可以被隐藏掉(参考:默认类映射),因为这个很常见。.
<encoder
元素强制一个 class 属性去指定一个类的全限定名,用于实例化。如果 encoder 的 class 是PatternLayoutEncoder
,那么基于默认类映射,class 属性可以被隐藏。
错误示范,会导致重复打印chapters.configuration包下的类容
<?xml version="1.0" encoding="UTF-8"?>
<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>
设置 context 的名字
默认这个 logger context 的名字为 "default"。但是你可以通过 <contextName> 设置其它的名字。
<configuration>
<contextName>myAppName</contextName>
</configuration>
变量的定义
<configuration>
<!-- 定义方式一 -->
<property name="USER_NAME" value="/data/logs" />
<!-- 定义方式二 -->
<property file="F:\project\logback-examples\src\main\resources\variables1.properties"/>
<!-- 定义方式三 -->
<property resource="resource1.properties" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_NAME}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
变量的作用域
属性的作用域分别为本地(local scope)、上下文(context scope)、系统(system scope)。默认为本地作用域。
在进行变量替换的时候,会先从本地范围去找,再从上下文去找,再从系统属性中去找,最后会去系统的环境变量中去找。
可以通过 <property>、<define>、<insertFromJNDI> 元素的 scope 属性来设置变量的作用范围。scope 属性可能的值为:local,context,system。如果没有指定,则默认为 local。
<property scope="context" name="nodeId" value="firstNode"/>
变量的默认值
。在 bash shell 中,默认值可以通过 ":-" 来指定。例如:假设变量 aName 没有被定义,"${aNme:-golden}" 会被解释成 "golden" 。
<file>${USER_NAME:-jack js}/myApp.log</file>
变量的嵌套
USER_HOME=/data/logs
fileName=myApp.log
destination=${USER_HOME}/${fileName}
系统预定义属性
<pattern>${HOSTNAME} - %msg%n</pattern>
<pattern>${CONTEXT_NAME} - %msg%n</pattern>
引入文件
通过 <include> 元素可以引入外部的配置文件。
<configuration>
<include file="src/main/resources/includedConfig.xml" />
<root level="DEBUG">
<appender-ref ref="includedConsole" />
</root>
</configuration>
目标文件必须是由 <included> 元素包裹的。
<included>
<appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d - %m%n</pattern>
</encoder>
</appender>
</included>
如果 logback 没有通过 include 元素找到指定的配置文件,会在控制台打印出内部状态信息。如果引入的外部配置文件是可选的,可以设置 optional=true。
<include optional="true" ..../>
网友评论