zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Spring 全家桶之 Spring Boot 2.6.4(三)- Logging

SpringBoot 全家 2.6 logging
2023-06-13 09:11:25 时间

一、Spring Boot的日志框架

首先来看Spring Boot官网关于Logging的介绍

Spring Boot uses Commons Logging for all internal logging but leaves the underlying log implementation open. Default configurations are provided for Java Util LoggingLog4J2, and Logback. In each case, loggers are pre-configured to use console output with optional file output also available. By default, if you use the “Starters”, Logback is used for logging. Appropriate Logback routing is also included to ensure that dependent libraries that use Java Util Logging, Commons Logging, Log4J, or SLF4J all work correctly.

Spring Boot对所有的内部日志使用Commons Logging,但是对底层的日志实现是开放的。提供了Java Util Logging、Log4J2和Logback的默认配置。并且会预先配置使用控制台输出,也可以选择文件保存日志记录

默认情况下,如果使用Spring Boot 的 ”Starters”,则使用Logback进行日志记录。还包括了适当的Logback路由,以确保使用Java Util Logging、Commons Logging、Log4J或SLF4J的依赖库都能正常工作。

二、日志框架统筹认识

日志框架的选择 日志规范/接口:

  • JCL:既Jakarta Commons Logging,由Apache 开发,artifactId是commons-logging,它提供了一套通用的日志接口。Spring Core所依赖的就是spring-jcl, Spring Boot的默认日志接口也是JCL也就是官网中所说的Commons Logging。
  • SLF4J:既Simple Logging Facade For(4) Java,由log4j的作者Ceki Gülcü开发,作用类似JCL,也是提供一套日志接口,还开发出logback,是一个日志实现,比log4j拥有更高的性能,目的就是为了替代log4j。
  • jboss-logging:作用类似SLF4J,是一套日志规范

日志实现

  • Log4j:是基于Java开发的日志,被其作者Ceki Gülcü捐献给了Apache
  • JUL:既java.util.logging,SUN公司拒绝log4j加入到jdk中,于是jdk1.4版本后增加了JUL(java.util.logging)
  • logback:作者Ceki Gülcü开发,比log4j拥有更高的性能
  • log4j2:参考了logback,并做了一系列优化,推出了log4j2,2015年9月,Apache软件基金业宣布,Log4j不在维护,建议所有相关项目升级到Log4j2。

目前推荐的日志接口是JCL和slf4j,推荐的有高性能的日志实现是logback和log4j,

2.1 - 查看Spring Boot所依赖的日志框架

在了解了Spring Boog官网关于日志的介绍以及现有的日志规范和日志实现之后,可以通过Spring Boot 的 spring-boot-starter-web来查看具体的日志依赖。 在pom.xml文件中选择Diagrams->Show Dependencies查看依赖关系图

  • Spring框架依赖的日志规范是JCL
  • Spring Boot 使用的日志“Starters”默认使用的是logback记录日志既使用的是logback日志实现,slf4j作为日志接口
  • jul-to-slf4j,log4j-to-slf4j是将jul日志和log4j转换为slf4j的。

2.2 - 不同框架拥有不同的日志实现

推荐使用的日志规范和实现是slf4j和logback,都是由同一个作者开发而且性能较高,而针对不同框架本身拥有不同的日志实现的情况下,作者Ceki Gülcü也在官网中给出了一些解决方案,就是使用中间包来替换原有的日志实现同时导入slf4j的日志规范,具体可以参看官网的使用手册

三、Spring Boot日志的使用

3.1 - Spring Boot 日志使用以及配置

在使用日志记录方法调用过程时,不应该使用日志实现而应该使用日志的抽象接口,在确定增加了Spring Boot的Web Starter之后,可以直接使用slf4j的接口来实现记录日志

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class LogApplicationTests {

    @Test
    public void testLog(){
        Logger logger = LoggerFactory.getLogger(LogApplicationTests.class);

        // 日志级别由低到高
        // 设置日志级别以后,只会输出该日志级别及以上级别的日志
        logger.trace("TRACE log");
        logger.debug("DEBUG log");
        logger.info("INFO log");
        logger.warn("WARN log");
        logger.error("ERROR log");
    }
}

需要注意的是一定要import slf4j相关的包,其他包中也存在同名的Logger和LoggerFactory这两个类,使用IDEA的默认导包很容易导错。

在pom.xml文件中有lombok依赖的情况下,也可以使用@Slf4j注解来简化

@SpringBootTest
@Slf4j
public class LogApplicationTests {
    @Test
    public void testLog(){
        log.trace("TRACE log");
        log.debug("DEBUG log");
        log.info("INFO log");
        log.warn("WARN log");
        log.error("ERROR log");
    }
}

执行testLog方法

Spring Boot 日志配置

日志级别配置

根据控制台的输出可以确定Spring Boot默认的日志级别是info级别,Spring Boot支持选择包进行日志级别的设置

logging.level.com.lilith.log=trace

再次执行testLog方法进行测试

trace及以上级别的日志都进行了输出。

日志保存配置

logging.file

logging.path

示例

具体表现

不指定

不指定

不设置

只在控制台进行输出

指定保存的文件

不指定

logging.file.name=lilith.log

输出日志到lilith.log文件中

指定保存的文件

指定保存的路径

logging.file.path=lilith

输出到lilith目录下的spring.log文件中

logging.file.name=lilith.log

执行测试

指定路径,不指定文件名的情况

logging.file.path=lilith

执行测试

Spring Boot默认log文件名为spring.log

日志输出格式配置

Spring Boot支持配置日志在文件中和控制台的输出格式

# 日志在控制台的输出格式
logging.pattern.console=
# 日志在文件中的格式
logging.pattern.file=

也支持自定义的日志格式配置文件,官方文档Custom Log Configuration有关于自定义日志配置文件的说明。

Logging System

Customization

Logback

logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy

Log4j2

log4j2-spring.xml or log4j2.xml

JDK (Java Util Logging)

logging.properties

自定义的logback日志实现的配置文件可以命名为logback.xml或者logback-spring.xml。

在resources目录下增加logback-spring.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" scanPeriod="60 seconds" debug="false">
    <!-- 定义日志的根目录 -->
    <property name="LOG_HOME" value="lilith/log" />
    <!-- 定义日志文件名称 -->
    <property name="appName" value="lilith-springboot"></property>
    <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <layout>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern>
        </layout>
    </appender>

    <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->  
    <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 指定日志文件的名称 -->
        <file>${LOG_HOME}/${appName}.log</file>
        <!--
        当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
        TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
        -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--
            滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动 
            %i:当文件大小超过maxFileSize时,按照i进行文件滚动
            -->
            <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <!-- 
            可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
            且maxHistory是365,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
            那些为了归档而创建的目录也会被删除。
            -->
            <MaxHistory>365</MaxHistory>
            <!-- 
            当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
            -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 日志输出格式: -->     
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
        </layout>
    </appender>
    <!-- hibernate logger -->
    <logger name="com.lilith" level="debug" />
    <!-- Spring framework logger -->
    <logger name="org.springframework" level="debug" additivity="false"></logger>
    <!-- 
    root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
    要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。 
    -->
    <root level="info">
        <appender-ref ref="stdout" />
        <appender-ref ref="appLogAppender" />
    </root>
</configuration> 

configuration标签的属性

  • scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认true。
  • scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
  • debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。

日志输出格式

  • %d:表示日期时间,
  • %thread:表示线程名,
  • %-5level:级别从左显示5个字符宽度
  • %logger{50}:表示logger名字最长50个字符,否则按照句点分割。
  • %msg:日志消息,
  • %n:换行符

logger标签主要用于存放日志对象,也可以定义日志类型、级别

  • name:表示匹配的logger类型前缀,也就是包的前半部分
  • level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
  • additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,
  • false/true:表示只用当前logger的appender-ref,true表示当前logger的appender-ref和rootLogger的appender-ref都有效

logback-spring.xml可以读取配置文件中激活了哪个环境,根据环境不同输出不同的日志。

<!--增加关于激活环境的依赖,不同的环境使用不同的格式输出-->
<layout class="ch.qos.logback.classic.PatternLayout">
    <!--application.properties配置文件中spring.profile.active=dev时输出日志的格式-->
    <springProfile name="dev">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} --DEV环境日志输出格式-- [%thread] ---> %-5level %logger{50} - %msg%n</pattern>
    </springProfile>
    <!--application.properties配置文件中spring.profile.active!=dev时输出日志的格式-->
    <springProfile name="!dev">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==非DEV环境日志输出格式== [%thread] ==== %-5level %logger{50} - %msg%n</pattern>
    </springProfile>
</layout>

配置文件添加

# 定义环境
spring.profiles.active=dev

执行测试

注释application.properites中激活环境的配置 再次执行测试

日志输出格式改变,自定义配置生效。