logback.xml详解

时间:2022-10-16 14:10:23

介绍

之前博文有专门介绍过基于Log4j Appender 实现大数据平台组件日志的采集, 本篇主要对java项目中经常会接触到的logback.xml文件的配置做一个介绍和总结.

logback.xml 配置

下面是一个logback配置demo, 常用的配置都有, 一一介绍下每个配置的作用.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<property name="LOG_HOME" value="d:/opt/module/logs" />
	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
		    <pattern>%msg%n</pattern>
		</encoder>
	</appender>
	<appender name="rollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
	    <file>${LOG_HOME}/app.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
		     <fileNamePattern>${LOG_HOME}/app.%d{yyyy-MM-dd}.log</fileNamePattern>
		</rollingPolicy>
		<encoder>
		    <pattern>%msg%n</pattern>
		</encoder>
	</appender>
	<!-- 将某一个包下日志单独打印日志 -->
	<logger name="com.bigdata.logger.LoggerExample"
	level="INFO" additivity="false">
		<appender-ref ref="rollingFile" />
		<appender-ref ref="console" />
	</logger>
	<root level="error" additivity="false">
	    <appender-ref ref="console" />
	</root>
</configuration>

配置说明:

  • property
    定义属性,类似全局变量, 比如上面我们定义的LOG_HOME 日志写入路径文件路径, 下面的appender 可以直接引用

  • appender
    追加器,描述如何写入到文件中(写在哪,格式,文件的切分)
    ConsoleAppender--追加到控制台
    RollingFileAppender--滚动追加到文件
    encoder: 对日志进行格式化。
    rollingPolicy:当发生滚动时,决定RollingFileAppender的行为,涉及文件移动和重命名.TimeBasedRollingPolicy 是根据时间制定滚动策略,
    fileNamePattern:文件输出格式

  • logger
    控制器,描述如何选择追加器
    注意:要是单独为某个类指定的时候,要修改类的全限定名
    appender-ref: 引用前面定义的appender
    level="error": 定义输出的日志级别, 低于此日志级别的日志不会输出
    additivity="false": 这个稍微不太好理解, 下面我写个代码, 实操下.

  • 日志级别
    TRACE->DEBUG ->INFO -> WARN -> ERROR -> FATAL
    从左到右, 由到高

  • root
    根级别日志

实战code

项目结构:

logback.xml详解

maven 配置:

 <dependencies>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.6</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.6</version>
        </dependency>
    </dependencies>

测试代码:

public class LoggerExample {
    private static final Logger logger = LoggerFactory.getLogger(LoggerExample.class);
    public static void main(String[] args) {
        logger.info("Example log from {}", LoggerExample.class.getSimpleName());
        logger.error("Error log");
    }
}

直接运行的结果:

logback.xml详解
console和app.log文件的结果一样

修改 additivity="true

<logger name="com.bigdata.logger.LoggerExample" level="INFO" additivity="true">

再次运行结果:
logback.xml详解

logback.xml详解

可以看出app.log正常, 但是cosole 上打印了重复的日志, 说明命中了console appender两次, log和root 各一次, 但是奇怪的是, 第一条info日志为什么会重复, 因为root level="ERROR", 理论上info 日志级别比ERROR级别要低, 不应该在console里出现才对.

我们看下logback相关的源码是如何处理的.

https://github.dev/qos-ch/logback/blob/master/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java#L256


    /**
     * Invoke all the appenders of this logger.
     * 
     * @param event The event to log
     */
    public void callAppenders(ILoggingEvent event) {
        int writes = 0;
        for (Logger l = this; l != null; l = l.parent) {
            writes += l.appendLoopOnAppenders(event);
            if (!l.additive) {
                break;
            }
        }
        // No appenders in hierarchy
        if (writes == 0) {
            loggerContext.noAppenderDefinedWarning(this);
        }
    }

从代码我们可以看出, logback 的整个输出是从logger子节点开始往上遍历, 如果additive = false, 就直接break 循环直接结束, 如果break = true, 会继续往上寻找父节点,直到最终 l == null. 同时会记录writes, writes == 0,认为没有定义appender输出源

代码没有关于日志级别的控制. 所以以后如果只希望打印日志到子节点的appeder, 父节点的appender忽略, 就设置additivity = false, 默认值为true, 这样日志就不会重复了.

总结

主要对logback.xml 常用配置的作用介绍, 通过logback 的相关源码对additivity参数有了更深的认识. additivity 默认值为true, 如果不希望在某些场景下打印重复的日志, 可以设置为false, additivity 配置不受level配置的影响.