日志框架
一套能实现日志输出的工具包,能够描述系统运行状态的所有时间都可以算作日志框架。日志框架可以分为接口层与实现层,或者称为门面与实现包。实现包也可做为独立日志框架使用。
日志框架的能力
1.定制输出目标
2.定制输出格式
3.携带上下文信息
4.运行时选择性输出
5.灵活的配置
6.优异的性能
常见的日志框架
日志门面(接口层):
JCL:apache自带的common logging
SLF4j
jboss-logging
日志实现(实现层):
Log4j
Log4j2
Logback
JUL:JDK自带的log
为什么要使用SLF4J?
SLF4J 是一个日志接口,没有具体实现日志系统,只提供了一组标准的调用api,将调用和具体的日志实现分离,使用slf4j后有利于根据自己实际的需求更换具体的日志系统,例如,之前使用的具体的日志系统为log4j,想更换为logback时,只需要删除log4j相关的jar,然后加入logback相关的jar和日志配置文件即可,而不需要改动具体的日志输出方法,如果不采用这种方式,当你的系统中日志输出有成千上万条时,要更换日志系统将是多么庞大的一项工程。有利于其他开发人员在调用你的模块时保持和他系统中使用统一的日志输出。
SLF4J 提供了基于占位符的日志记录,通过删除检查(isDebugEnabled(),isInfoEnabled()等)来提高代码的可读性,临时字符串数量越少意味着垃圾收集器的工作量就越少,这意味着应用程序的吞吐量和性能会更好。
且SLF4J 为SpringBoot项目自带的日志框架,不需要额外导入日志实现包即可使用,当我们创建一个Springboot项目时,通过idea打开maven的show dependencies,会发现项目的整体依赖,其中spring-boot-starter-web会依赖spring-boot-starter,spring-boot-starter会依赖spring-boot-starter-logging,可以看出Spring Boot自动导入了SLF4J+Logback,并且额外导入了jul-to-slf4j和log4j-to-slf4j,并且Springboot对于日志框架有自己的默认配置。
如何使用
当什么都不配置时,日志输出的默认级别是info,低于info级别的log信息是不输出的,比如debug、trace。并且log信息只会在控制台输出,如果要想输出到文件,需要指定logging.path或者logging.file
1.如果使用SLF4J日志框架前使用过其他日志框架的话,需将其他日志框架的依赖删除并将以下依赖加入:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
<exclusion>
<artifactId>log4j-over-slf4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
2.通过@SLF4J注解使用:
2.1 添加依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2.2 在需要输出日志的类中加入@SLF4J注释,使用log调用对应的log信息级别方法,例如:
@SpringBootTest
@Slf4j
public class LoggerTest {
@Test
public void test1() {
log.trace("This is trace...");
log.debug("This is debug...");
log.info("This is info...");
log.warn("This is warn...");
log.error("This id error...");
}
}
2.3如果不能通过@SLF4J使用,则需要安装Lombok Plugin插件
3.通过调用log输出实现类使用:
3.1 通过SLF4J中的Logger接口调用LoggerFactory中的log输出实现方法:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Logger logger= LoggerFactory.getLogger(ManageApplicationTest.class);
3.2 在需要输出日志的类中添加上述代码,使用logger对象调用对应log信息级别方法即可,例如:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoggerTest {
Logger logger= LoggerFactory.getLogger(ManageApplicationTest.class);
@Test
public void test1() {
logger.trace("This is trace...");
logger.debug("This is debug...");
logger.info("This is info...");
logger.warn("This is warn...");
logger.error("This id error...");
}
}
4.打印变量:
4.1 使用连接字符串,例如:
String name = "zcy";
String password = "123456";
log.info("name:"+name+"password"+password);
4.2 使用占位符,例如:
String name = "zcy";
String password = "123456";
log.info("name: {}, password: {}", name, password);
4.3 slf4j日志输出时可以使用{}占位符的,而log4j则只能使用连接字符串的形式,前者要比后者在性能上更好,后者采用+连接字符串时就是new一个String字符串,在性能上就不如前者。
5.日志格式
5.1日志输出格式符号含义:
%d表示日期时间,
%thread表示线程名,
%‐5level:级别从左显示5个字符宽度
%logger{50} 表示logger名字最长50个字符,否则按照句点分割
%msg:日志消息
%n是换行符
5.2 Springboot默认的日志格式为:
"%d{yyyy-MM-dd HH:mm:ss.SSS} -%5p ${PID:-} [%15.15t] %-40.40logger{39} : %m%n"
6.配置日志框架
6.1 通过application.yml文件配置:
logging:
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} -%5p ${PID:-} [%15.15t] %-40.40logger{39} : %m%n" //设置日志输出格式
level:
root: info //设置root目录下的日志输出级别
com.suwo.auieo.manage: trace //可以指定某个包或者某个类的日志输出级别
file: log/springboot.log //日志生成文件地址以及自定义日志文件名称
path:log/ //日志生成文件地址,默认文件名spring.log(如果file属性和path属性同时使用的话,只有file属性生效!)
6.2 通过创建logback-spring.xml文件进行配置:
logback-spring.xml文件是直接由SpringBoot框架进行解析,所以在resources目录下创建后便能使用,但由于xml文件编写较为复杂,并不推荐使用
<?xml version="1.0" encoding="UTF-8"?>3
<configuration>
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
%d - %msg%n
</pattern>
</layout>
</appender>
<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
<encoder>
<pattern>
%msg%n
</pattern>
</encoder>
<!--滚动策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>/var/log/tomcat/sell/info.%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>
%msg%n
</pattern>
</encoder>
<!--滚动策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>/var/log/tomcat/sell/error.%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<root level="info">
<appender-ref ref="consoleLog"/>
<appender-ref ref="fileInfoLog"/>
<appender-ref ref="fileErrorLog"/>
</root>
</configuration>
SLF4J绑定其他日志框架使用
在分模块开发时,如果模块间使用的日志框架不同的话,引入进来的话就需要维护两个日志框架,而进行框架更改的话工程量太大,使用SLF4J就不需要考虑这些问题了。将两个日志框架绑定slf4j一起使用,调用slf4j的api来输入日志信息,具体使用与底层日志框架无关。而使用了slf4j就不同了,由于程序调用的抽象层的api,与底层日志框架是无关的,因此可以任意更换日志框架,只需要在pom.xml中的依赖将原来的日志框架替换成与其相对应的sf4j日志转换包就可以了。
总结
SLF4J是一个日志门面,实现了一些日志框架的标准通用的接口,而log4j、log4j2、logback则可认为是具体的框架,可与SLF4J配合使用也可单独使用,但遇到项目模块间,或是引入类库的日志框架不同时不好处理,配合SLF4J就可以不必改变原有日志框架。
SLF4J更像是将这些日志框架重新封装,提供了共通的接口供使用者调用,无论底层框架如何改变,只需要替换依赖即可,不需要再逐一更改排查项目何处调用了原日志系统的方法。