第一次配置日志,还是花了很长时间。记录一下slf4j疑惑
一、slf4j是什么
slf4j是一套日志框架(日志门面,抽象层),但是它并不真正实现日志写入功能。java的日志实现框架有很多例如:log4j、log4j2、logback等,但各种日志使用规则不尽相同,为了更好的体验,slf4j在日志实现框架上进行了一层封装。即:不关心底层日志实现,只需要使用slf4j简单接口即可。
log4j、logback、slf4j是同一个人写的。最早开发出log4j,但是性能不太好,所以开发出logback。但是为了兼容日志系统,这个大神又开发出了slf4j,用于日志门面。
log4j2是apache团队开发的。
二、配置
创建一个maven空工程,pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>log-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
slf4j可以对接多中日志实现框架,这里罗列一下常用框架配置,以便后面使用。如果通过idea运行,默认目录是工程的根目录。
2.1、对接log4j
在pom文件中添加依赖,自动导入slf4j-api和log4j依赖:
<dependencies>
<!-- 使用slf4j && log4j日志系统 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
</dependencies>
在resource目录下面创建,log4j.properties配置文件:
### set log levels ###
log4j.rootLogger = debug,stdout,D,E
### 输出到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} %p [%c] %m%n
### 输出到日志文件 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 保存异常信息到单独文件 ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File = logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### logger ###
# 设置后com.xiaofan路径下的日志将只输出ERROR日志
#log4j.logger.com.xiaofan=ERROR
log4j.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{yyyy-MM-dd HH:mm:ss,SSS\} %-5p] %c{2\} [%t] - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="debug" />
<param name="levelMax" value="error" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
<appender name="ERROR" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logs/error.log" />
<param name="Append" value="true" />
<param name="threshold" value="error" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%p (%c:%L)- %m%n" />
</layout>
</appender>
<appender name="INFO" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="logs/log.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{MMdd HH:mm:ss SSS\} %-5p] [%t] %c{3\} - %m%n" />
</layout>
</appender>
<logger name="mylogger" additivity="true">
<level value="debug" />
<appender-ref ref="INFO" />
</logger>
<root>
<priority value ="debug"/>
<appender-ref ref="INFO"/>
<appender-ref ref="ERROR" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
java源码实现:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @Describe TODO
* @Author xuxiaobing
* @Date 2021/7/12
* @Copyright didiglobal.com
*/
public class HelloLog {
private final static Logger log = LoggerFactory.getLogger(HelloLog.class);
public static void main(String[] args) {
log.info("hello log");
}
}
2.2、对接logback
依赖,自动导入依赖slf4j-api:
<!-- 使用slf4j && logback日志系统 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
logback.xml配置:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定义参数常量 -->
<!-- TRACE < DEBUG < INFO < WARN < ERROR -->
<!-- logger.trace("msg") -->
<property name="log.dir" value="/tmp/logs"/> <!-- 指定日志输出目录 -->
<property name="log.level" value="info"/>
<property name="log.maxHistory" value="30"/>
<property name="log.filePath" value="${log.dir:-logs}"/>
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{55} - %msg%n"/>
<!-- 控制台设置 -->
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- DEBUG -->
<appender name="debugAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<file>${log.filePath}/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${log.filePath}/debug/debug.%d{yyy-MM-dd}.log.gz</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMissMatch>DENY</onMissMatch>
</filter>
</appender>
<!-- INFO -->
<appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<file>${log.filePath}/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${log.filePath}/info/info.%d{yyy-MM-dd}.log.gz</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMissMatch>DENY</onMissMatch>
</filter>
</appender>
<!-- ERROR -->
<appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<file>${log.filePath}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${log.filePath}/error/error.%d{yyy-MM-dd}.log.gz</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMissMatch>DENY</onMissMatch>
</filter>
</appender>
<!-- 设置包com.xx.abc打印级别为debug -->
<logger name="com.xx.abc" level="DEBUG"/>
<root level="INFO">
<appender-ref ref="infoAppender"/>
</root>
</configuration>
三、springboot结合
如果结合springboot,配置就大大简化了,后续再详细介绍。