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