在Java世界里, 日志框架通常有 logback
和 log4j
。两个日志框架都是同一个作者写的,其中 logback 是后浪,可以看作是 log4j 的改良版本,因此在性能上 logback 要好过 log4j 。目前主要分为3个模块
logback-core
:核心代码模块logback-classic
:log4j的一个改良版本,同时实现了slf4j
的接口,这样你如果之后要切换其他日志组件也是一件很容易的事logback-access
:访问模块与Servlet容器集成提供通过Http来访问日志的功能
平时在搭建项目时少不了要配置日志框架,xml配置文件一时难以找到一个可用的模板,故本文会介绍logback的使用、配置属性详解、以及logback简单原理,最后提供一个详细的配置文件模板。这里简单讲一下 logback,log4j 和 slf4j 的关系,我在一开始使用日志框架的时候不清楚它们的关系,所以当别人问我用什么日志框架时,我说用 slf4j (哈哈,这就出洋相了。。),slf4j 全称 Simple Logging Facade for Java,是日志框架的一种抽象。简单理解为,slf4j 定义了日志框架的标准接口,logback和log4j都是slf4j的实现,我们在使用日志框架时是可以随意切换log4j和logback的,因为对外的接口都是slf4j提供的。在slf4j中,从小到大的日志级别依旧是trace、debug、info、warn、error
。
logback的引入
maven依赖
<!--这个依赖直接包含了 logback-core 以及 slf4j-api的依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
然后就可以直接在代码中使用slf4j的接口获取Logger输出日志了。下面是一个简单的使用demo
//这是slf4j的接口,由于我们引入了logback-classic依赖,所以底层实现是logback
private static final Logger LOGGER = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) throws InterruptedException {
LOGGER.info("hello world");
}
logback.xml配置详解
下面是配置的模板,每一项配置有详细说明,拿过去根据自己的需求删删改改就能用,对于spring boot 我们需要在resources目录下建立一个xml文件,叫做logback-spring.xml
,为什么要起这个名字呢,因为起这个名字springboot会自己去找该文件。如果不叫logback-spring.xml
,那么需要在 spring boot 的 application.yml中指定自定义的日志配置文件的路径
logging:
config: classpath:my-logback.xml
logback.xml配置内容如下
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 文件输出格式 -->
<!-- 1格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<property name="FILE_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}: %msg%n"/>
<!-- 日志最大保存数量 -->
<property name="MAX_HISTORY" value="10"/>
<!-- 日志文件大小 -->
<property name="FILE_SIZE" value="10MB"/>
<!-- 日志文件存放路径 -->
<property name="FILE_PATH" value="${log.path}/log_file/"/>
<!-- audit文件,记录info级别日志 -->
<appender name="AUDIT-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 实时输出的日志文件 -->
<file>${FILE_PATH}/audit.log</file>
<append>true</append>
<!-- 历史日志分块,配置滚动的策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志名称的格式 -->
<fileNamePattern>${LOG_HOME}/audit.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 保存的最长时间:天数 -->
<MaxHistory>${MAX_HISTORY}</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_PATTERN}</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>${FILE_SIZE}</MaxFileSize>
</triggeringPolicy>
<!-- 过滤掉非info的日志,即此日志文件中只会输出info日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMissmatch>DENY</onMissmatch>
</filter>
</appender>
<!-- error文件,记录error级别日志 -->
<appender name="ERROR-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 实时输出的日志文件 -->
<file>${FILE_PATH}/audit.log</file>
<append>true</append>
<!-- 历史日志分块,配置滚动的策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志名称的格式 -->
<fileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 保存的最长时间:天数 -->
<MaxHistory>${MAX_HISTORY}</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_PATTERN}</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>${FILE_SIZE}</MaxFileSize>
</triggeringPolicy>
<!-- 过滤掉非error的日志,即此日志文件中只会输出error日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMissmatch>DENY</onMissmatch>
</filter>
</appender>
<!-- debug文件,记录debug级别日志 -->
<appender name="DEBUG-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 实时输出的日志文件 -->
<file>${FILE_PATH}/debug.log</file>
<append>true</append>
<!-- 历史日志分块,配置滚动的策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志名称的格式 -->
<fileNamePattern>${LOG_HOME}/debug.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 保存的最长时间:天数 -->
<MaxHistory>${MAX_HISTORY}</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_PATTERN}</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>${FILE_SIZE}</MaxFileSize>
</triggeringPolicy>
<!-- 过滤掉非debug的日志,即此日志文件中只会输出debug日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMissmatch>DENY</onMissmatch>
</filter>
</appender>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_PATTERN}</pattern>
</encoder>
</appender>
<!-- 打印 Spring 在启动的时候初始化各个 Bean 的信息 -->
<logger name="org.springframework.web" level="DEBUG"/>
<!--mybatis日志 mapper包所在路径-->
<!-- 以下这一句至关重要如果没有,就无法输出 sql 语句 -->
<!--注意:在 spring boot 中,想在控制台打印 mybatis 的 sql 语句,只需要配置下边这一句就好了。-->
<!--如果想要记录更详细的 SQL 日志,只需要把下面的日志级别改成 TRACE 就可以了-->
<!--即将 mapper 接口打入 logger 就行。-->
<logger name="com.test.dao" level="DEBUG"></logger>
<!--mybatis 日志打印如果在 ssm 中,可能就需要下面的配置-->
<!--<logger name="jdbc.sqltiming" level="debug"/>-->
<!--<logger name="com.ibatis" level="debug"/>-->
<!--<logger name="com.ibatis.common.jdbc.SimpleDataSource" level="debug"/>-->
<!--<logger name="com.ibatis.common.jdbc.ScriptRunner" level="debug"/>-->
<!--<logger name="com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate" level="debug"/>-->
<!--<logger name="java.sql.Connection" level="debug"/>-->
<!--<logger name="java.sql.Statement" level="debug"/>-->
<!--<logger name="java.sql.PreparedStatement" level="debug"/>-->
<!--<logger name="java.sql.ResultSet" level="debug"/>-->
<!-- 相当于logger元素,只是name值已经确定为root了 -->
<root level="DEBUG">
<appender-ref ref="AUDIT" />
<appender-ref ref="ERROR" />
<appender-ref ref="DEBUG" />
<appender-ref ref="STDOUT" />
</root>
</configuration>