程序代码:
package logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogbackDemo {
private static Logger log = LoggerFactory.getLogger(LogbackDemo.class);
public static void main(String[] args) {
log.trace("======trace");
log.debug("======debug");
log.info("======info");
log.warn("======warn");
log.error("======error");
}
}
logback-test.xml
<configuration scan="false">
<property name="module_name" value="test" />
<timestamp key="time_pattern" datePattern="yyyy-MM-dd HH:mm:ss" />
<contextName>${module_name}-${time_pattern}</contextName>
<appender name="FILE_1" class="ch.qos.logback.core.FileAppender">
<file>logs/file1.log</file>
<append>false</append>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE_2" class="ch.qos.logback.core.FileAppender">
<file>logs/file2.log</file>
<append>false</append>
<encoder>
<pattern>%d [%-5level] %file,%line - %msg%n</pattern>
</encoder>
</appender>
<logger name="logback" level="DEBUG">
<appender-ref ref="FILE_2" />
</logger>
<root level="INFO">
<appender-ref ref="FILE_1" />
</root>
</configuration>
日志输出结果:
file1.log
15:29:44.306 [main] DEBUG logback.LogbackDemo - ======debug
15:29:44.308 [main] INFO logback.LogbackDemo - ======info
15:29:44.308 [main] WARN logback.LogbackDemo - ======warn
15:29:44.309 [main] ERROR logback.LogbackDemo - ======error
file2.log
2016-06-15 15:29:44,306 [DEBUG] LogbackDemo.java,12 - ======debug
2016-06-15 15:29:44,308 [INFO ] LogbackDemo.java,13 - ======info
2016-06-15 15:29:44,308 [WARN ] LogbackDemo.java,14 - ======warn
2016-06-15 15:29:44,309 [ERROR] LogbackDemo.java,15 - ======error
问题: LogbackDemo类输入logback包,所以logger (logback) 输出DEBUG所有信息,这个好理解,但是ROOT level是INFO,却输出了DEBUG级别的所有日志,这个有些费解?
要找到问题的答案,首先要看看logback的官方文档。以下时重点部分:
- Named Hierarchy
A logger is said to be an ancestor of another logger ifits name followed by a dot is a prefix of the descendantlogger name. A logger is said to be a parent of a childlogger if there are no ancestors between itself and thedescendant logger.
- Logger Hierarchy
The effective level for a given logger L, is equalto the first non-null level in its hierarchy, starting atL itself and proceeding upwards in the hierarchytowards the root logger.
- Logging request selection
A log request of level p issued to a logger havingan effective level q, is enabled ifp >= q.
-
AppenderAdditivity
The output of a log statement of logger L will go toall the appenders inL and its ancestors. This is themeaning of the term "appender additivity".
However, if an ancestor of logger L, say P,has the additivity flag set to false, thenL's outputwill be directed to all the appenders inL and itsancestors up to and includingP but not the appenders inany of the ancestors ofP.
Loggers have their additivity flag set to true by default.
其中问题的重点就在第四项, appender additivity, 意思就是当前logger的appender additivity 若是没有显式设置为false,则默认把parent logger的appender加入到自己的appender列表里。
当前logger (logback.LogbackDemo) 没有显示设置level和additivity属性,那么继承parent logger (logback)的LEVEL 和 additivity 属性, LEVEL = DEBUG, additivity = true, 那么logger (logback) 的appender有哪些呢? 除了自己设定的file1, 因为additivity = true,还包含ROOT的appender file2, 所以logger (logback.LogbackDemo) 继承自父类 logger level = DEBUG, appender= file1, file2;
结果就是上面的样子了。