Spring Boot logback日志

slf4j和log4j、log4j2、logback 之间的关系

  • log4j出来时就得到了广泛的应用,是Java日志事实上的标准,并成为了Apache的项目
  • Apache要求把log4j并入到JDK,SUN拒绝,并在jdk1.4版本后增加了JUL(java.util.logging)
  • 毕竟是JDK自带的,JUL也有很多人用。同时还有其他日志组件,如SimpleLog等。这时如果有人想换成其他日志组件,如log4j换成JUL,因为api完全不同,就需要改动代码。
  • Apache见此,开发了JCL(Jakarta Commons Logging),即commons-logging-xx.jar。它只提供一套通用的日志接口api,并不提供日志的实现。这样应用程序可以在运行时选择自己想要的日志实现组件。
  • 这样看上去也挺美好的,但是log4j的作者觉得JCL不好用,自己开发出slf4j,它跟JCL类似,本身不替供日志具体实现,只对外提供接口或门面。目的就是为了替代JCL。同时,还开发出logback,一个比log4j拥有更高性能的组件,目的是为了替代log4j。
  • Apache参考了logback,并做了一系列优化,推出了log4j2。

所以目前我们主要用到的日志框架为logback和log4j2。而且二者都支持slf4j规范。比如我们的spring boot就是使用slf4j+logback作为默认的日志方案。

logback简介

本文只做logback的常用功能讨论,更多需求请查看logback官方参考文档
logback 分为三个模块,logback-core、logback-classic 和 logback-access。Logback-classic 原生实现了SLF4J API。logback有如下几个重要的组件。

Appender

我们可以叫他记录器。负责输出日志。通常我们会为它配置Layout或Encoder

  1. ConsoleAppender 输出到控制台的记录器
  2. FileAppender 输出到文件的记录器,但我们通常会使用它的子类RollingFileAppender
  3. RollingFileAppender 滚动日志记录器。可以指定每个日志文件的最大大小以及定期的日志删除策略。

输出到控制台示例

其实spring Boot 默认就配置了logback日志的,而且控制台打印出来还有颜色,而且布局也很整齐。这个我们后面再说,我们先来个示例看看。
在resource目录新建logback-spring.xml配置文件如下:



<configuration debug="true">

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

    
    <logger name="com.yyoo" level="DEBUG" />

    
    <root level="OFF">
        <appender-ref ref="STDOUT" />
    root>

configuration>

注:使用logback-spring.xml而不是logback.xml。因为logback-spring.xml支持很多Spring boot的扩展,而logback.xml加载过早,导致无法支持这些扩展。

启动日志如下

16:10:14,916 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
16:10:14,918 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
16:10:14,922 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
16:10:14,936 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger [com.yyoo] to DEBUG
16:10:14,937 |-INFO in ch.qos.logback.classic.jul.LevelChangePropagator@2b4bac49 - Propagating DEBUG level on Logger[com.yyoo] onto the JUL framework
16:10:14,938 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to OFF
16:10:14,938 |-INFO in ch.qos.logback.classic.jul.LevelChangePropagator@2b4bac49 - Propagating OFF level on Logger[ROOT] onto the JUL framework
16:10:14,938 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
16:10:14,938 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
16:10:14,938 |-INFO in org.springframework.boot.logging.logback.SpringBootJoranConfigurator@4470f8a6 - Registering current configuration as safe fallback point

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.1)

16:10:14.994 [main] INFO  com.yyoo.springmvc.Appliction - Starting Appliction using Java 1.8.0_181 on ZHOU with PID 13028 (D:\work\code\mytest\springmvc\target\classes started by zhou in D:\work\code\mytest\springmvc)
16:10:14.996 [main] DEBUG com.yyoo.springmvc.Appliction - Running with Spring Boot v2.6.1, Spring v5.3.13
16:10:14.996 [main] INFO  com.yyoo.springmvc.Appliction - No active profile set, falling back to default profiles: default
16:10:16.033 [main] INFO  com.yyoo.springmvc.Appliction - Started Appliction in 1.364 seconds (JVM running for 1.941)

到此你会发现,现在打印没有颜色了,而且日志格式好像也不太整齐了,别着急,我们来看看spring Boot中的logback默认的日志文件。

在spring-boot.x.x.x.jar包中可以找到spring对logback的功能增强的配置
Spring Boot logback日志_第1张图片
其中defaults.xml中就配置了支持在控制台打印有颜色的日志。我们不用重新定义或者拷贝,直接include即可。(注意:其实如果我们没有自定义配置logback-spring.xml那么springboot默认就使用的如下的配置)



<configuration debug="false">
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                ${CONSOLE_LOG_PATTERN}
            pattern>
        encoder>
    appender>

    
    <logger name="com.yyoo" level="DEBUG" />

    
    <root level="OFF">
        <appender-ref ref="STDOUT" />
    root>

configuration>

CONSOLE_LOG_PATTERN是defaults.xml里配置的名称,你如果需要修改,就自行配置把。

输出到文件

上图file-appender.xml就是默认的spring配置输出到文件,如果我们没有特殊的需要,我们可以直接include使用即可。这个这里就不说了。

Spring中直接配置

默认配置已经支持大部分都情况了,意味着其实我们可以不用自定义配置的,而且spring Boot默认的配置是支持我们在properties文件中配置的,对应的配置属性如下

properties配置 logback中的配置项 说明
logging.exception-conversion-word LOG_EXCEPTION_CONVERSION_WORD 记录异常时使用的转换字。
logging.file.name LOG_FILE 如果定义,则在默认日志配置中使用。
logging.file.path LOG_PATH 如果定义,则在默认日志配置中使用。
logging.pattern.console CONSOLE_LOG_PATTERN 要在控制台 (stdout) 上使用的日志模式。
logging.pattern.dateformat LOG_DATEFORMAT_PATTERN 日志日期格式的 Appender 模式。
logging.charset.console CONSOLE_LOG_CHARSET 用于控制台日志记录的字符集。
logging.pattern.file FILE_LOG_PATTERN 要在文件中使用的日志模式(如果LOG_FILE已启用)。
logging.charset.file FILE_LOG_CHARSET 用于文件记录的字符集(如果LOG_FILE已启用)。
logging.pattern.level LOG_LEVEL_PATTERN 呈现日志级别时使用的格式(默认%5p)。

以下是使用logback日志特有的配置

properties配置 logback中的配置项 说明
logging.logback.rollingpolicy.file-name-pattern LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN 滚动日志文件名的模式(默认${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz)。此配置会影响后面的滚动删除策略,请搞清楚了再自定义配置。比如%i会影响归档文件的数量。日期格式会也会影响。
logging.logback.rollingpolicy.clean-history-on-start LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START 是否在启动时清除存档日志文件,默认false。此配置不影响下面的最大归档和总大小删除策略。
logging.logback.rollingpolicy.max-file-size LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE 最大日志文件大小。默认无限制
logging.logback.rollingpolicy.total-size-cap LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP 要保留的日志备份的总大小。默认无限制
logging.logback.rollingpolicy.max-history LOGBACK_ROLLINGPOLICY_MAX_HISTORY 要保留的最大归档日志文件数。默认无限制

springProfile标签

在配置中,我们可以添加springProfile标签来区分不同的部署环境使用不同的日志配置。

<springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
        root>
    springProfile>

    <springProfile name="test">
        <root level="INFO">
            <appender-ref ref="FILE" />
        root>
    springProfile>

如上表示,dev环境只打印到控制台,test环境只打印到日志文件。

注意springProfile要结合profile的配置。而springBoot的profile还可以结合maven打包。请查看maven的profile和Spring boot 的profile整合

总结

综上,我们可以自定义一个logback-spring.xml文件,即可以使用spring Boot增强的带颜色打印到控制台的功能,又能够自己扩展一些配置。



<configuration debug="false">
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
    <include resource="org/springframework/boot/logging/logback/file-appender.xml" />

    
    <logger name="org.apache.ibatis" 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="com.yyoo" level="DEBUG" />

    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
        root>
    springProfile>

    <springProfile name="test">
        <root level="INFO">
            <appender-ref ref="FILE" />
        root>
    springProfile>

configuration>

文件大部分拷贝上面图中的base.xml文件。

默认情况下,Spring Boot 只记录到控制台,不写入日志文件。如果你想在控制台输出之外写入日志文件,你需要配置properties文件属性logging.file.name和logging.file.path

slf4j API的使用

建议在代码中使用slf4j的api,这有助于我们在之后更换其他日志框架时可以不用修改代码,前面已经提到slf4j是日志门面,我们也可以认为是日志的标准接口,logback和log4j2等常用的日志框架都适配了该接口门面。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("logback")
public class DemoController {

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

    @RequestMapping("test1")
    public void test1(){
        try{
            int a = 1/0;
        }catch (Exception e){
            log.debug("出现异常{},打印日志","参数1",e);
        }
    }

}

示例中debug方法的参数有多个,第一个为消息模板,{}为占位符,按顺序第二个参数对应第一个占位符,如果要传Exception对象,那么该对象必须是最后一个参数。

以上的log对象每次都要在对应的类中定义,比较麻烦。但是如果定义一个公共的log类,日志打印出来的记录位置都是同一个地址,不方便排查。此时我们可以使用Lombok的@Slf4j注解来解决关于Lombok我们将在后面介绍。

上一篇:Spring Boot配置绑定
下一篇:Spring Boot 任务调度

你可能感兴趣的:(人在江湖之SpringBoot,spring,boot,logback,打印颜色,logback配置,分环境配置)