飞道的博客

Logback入门教程学习笔记

318人阅读  评论(0)

1 概述

Logback是在java社区广泛使用的日志框架之一,它是Log4j的替代品。Logback提供了比Log4j更快的实现,更多可选择的配置,以及归档log文件更大的灵活性。

2 Logback的架构

包括三个类:Logger,Appender和Layout

  • Logger, 是log信息的上下文,是跟应用交互以生成log信息之用;
  • Appender,负责日志输出的组件;
  • Layout,用来格式化日志信息等。

3 例子

这里创建一个springboot工程,添加以下依赖

3.1 Maven依赖

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

3.2 基本的配置和代码demo

在resources下面创建logback.xml文件,添加以下配置:

<?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>

    <root level="debug">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

创建一个Example:

@Slf4j
public class Example {
    public static void main(String[] args) {
        log.info("Example log from {}", Example.class.getSimpleName());
    }
}

运行得到以下结果:
09:59:36.226 [main] INFO com.logback.demo.Example - Example log from Example。

4 Logger context

@Slf4j是来自lombok的注解,相当于如下代码:

private static final Logger log = LoggerFactory.getLogger(Example.class);

可以从编译后的class文件,反编译后看到。

4.1 logger继承结构

Logger context的继承类似于java的继承。

  • 所有的logger都是root logger的后代;
  • 如果一个logger没有指定level,那么它的level将继承上一个祖先logger.
  • root logger的默认level是DEBUG。

注意:日志级别分为5种,从小到大依次是TRACE, DEBUG, INFO, WARN 和ERROR。低于指定级别的日志将不打印,例如我们指定日志级别是INFO,那么低于INFO的TRACE和DEBUG都不打印。

上代码:

public class LoggerHierarchyExample {

    @Test
    public void testLoggerHierarchy() {
        // 祖先logger,未指定级别,它将继承root logger的级别,root logger默认debug
        // SLF4J's的抽象logger是没有实现setLevel方法,这里是用ch.qos.logback.classic.Logger
        Logger ancestorLogger = (Logger) LoggerFactory.getLogger("com");
        // 父logger,指定级别为info,不继承祖先logger的级别
        Logger parentLogger = (Logger) LoggerFactory.getLogger("com.logback");
        parentLogger.setLevel(Level.INFO);
        // 子logger,未指定级别,继承最近的父logger的日志级别,为info。
        Logger childLogger = (Logger) LoggerFactory.getLogger("com.logback.demo");

        ancestorLogger.debug("This message is logged because debug == debug");
        ancestorLogger.trace("This message is not logged because trace < debug");
        parentLogger.warn("This message is logged because WARN > INFO.");
        parentLogger.debug("This message is not logged because DEBUG < INFO.");
        childLogger.info("INFO == INFO");
        childLogger.debug("DEBUG < INFO");
        
    }


    @Test
    public void testRootLogger() {
        // 没有指定level,继承root logger的level为debug
        Logger logger = (Logger) LoggerFactory.getLogger("com.logback");
        logger.debug("Hi there!");

        // root logger,重新设定level为error
        Logger rootLogger = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
        logger.debug("This message is logged because DEBUG == DEBUG.");
        rootLogger.setLevel(Level.ERROR);

        logger.warn("This message is not logged because WARN < ERROR.");
        logger.error("This is logged.");
    }
}

testLoggerHierarchy()结果为:

10:49:16.713 [main] DEBUG com - This message is logged because debug == debug
10:49:16.715 [main] WARN  com.logback - This message is logged because WARN > INFO.
10:49:16.715 [main] INFO  com.logback.demo - INFO == INFO

testRootLogger() 结果为:

10:50:06.087 [main] DEBUG com.logback - Hi there!
10:50:06.089 [main] DEBUG com.logback - This message is logged because DEBUG == DEBUG.
10:50:06.089 [main] ERROR com.logback - This is logged.

4.2 参数化打印日志

实际编码中,看到很多如下日志打印方式:

log.debug("Current count is " + count);

这种方式的弊端:即使日志打印level设定为info,都会执行字符串的拼接,无疑会白白的损耗性能。

以下方式也不可取,虽然不执行拼接,但仍然做了一次判断。

if(log.isDebugEnabled()) { 
  log.debug("Current count is " + count);
}

更好的方式是使用占位符的方式 , 避免字符串拼接,避免日志level的判断。

log.debug("Current count is {}" , count);

占位符{}允许接收任何object,并且调用其toString方法来记录日志。

@Slf4j
public class ParameterizedExample {

    @Test
    public void testParameterizedExample() {
        String message = "This is a String";
        Integer zero = 0;
        User user = new User().setId("123").setName("Tim");
        try {
            log.debug("Logging message: {}", message);
            log.debug("Going to divide {} by {}", 42, zero);
            log.debug("user is {}", user);
            int result = 42 / zero;
        } catch (Exception e) {
            log.error("Error dividing {} by {} ", 42, zero, e);
        }
    }
}

@Data
@Accessors(chain = true)
public class User {
    private String id;
    private String name;
}

5 详细配置


转载:https://blog.csdn.net/qq_39530821/article/details/105464515
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场