SpringBoot 日志管理
目录
一、简介
二、默认日志格式
三、修改日志显示格式
四、日志显示级别
4.1 基本原则
4.2 修改默认显示级别
五、日志分组
六、输出到文件
七、日志归档与切割
7.1 说明
7.2 规则
八、自定义日志配置
九、切换日志组合
一、简介
先说明:项目中不要写System.out.println(),应该用日志记录信息!
而关于日志的演变也是非常久远的。JDK1.4 开始,通过 java.util.logging 提供日志功能。虽然是官方自带的log lib,JUL的使用确不广泛。原因其实简单:就是那个时候做的真的很烂,也非常不好用。所以后面逐渐涌现出来像Log4j、Logback等优秀的日志框架。
今天,我们不会去深度探讨这其中的关系,重在讲解Springboot应用中的主要用法。如果对这方面感兴趣,可以参考这篇文章https://pdai.tech/md/develop/package/dev-package-x-log.html
好,正篇开始!
Spring使用commons-logging作为内部日志,但底层日志实现是开放的。可对接其他日志框架。
在Spring5以后,common-logging被spring直接自己写了。
Spring Boot默认使用Logback作为其日志框架。
Spring boot的每个starter场景,都会引入一个核心场景spring-boot-starter
这个spring-boot-starter下就引入了这个spring-boot-starter-logging这个日志依赖。
我们再进去看一下,就看到了logback-classic依赖。
而日志是利用监听器机制配置好的,和其他的自动装配不太一样,因为日志需要一启动就要运行,具体的我们后面再细说。
另外,日志是所有配置都可以通过修改配置文件实现。以logging开头的所有配置。
二、默认日志格式
启动springboot项目,我们可以看到控制台打印的日志信息,如下所示:
2025-06-12 17:34:27.683 INFO 35252 --- [ main] com.cisdi.info.Application : Starting Application on pps with PID 35252 (E:\project\workspace\work\zk_new\heat_optimize_app\target\classes started by hssym in E:\project\workspace\work\zk_new\heat_optimize_app)
2025-06-12 17:34:27.684 INFO 35252 --- [ main] com.cisdi.info.Application : The following profiles are active: test
2025-06-12 17:34:28.673 INFO 35252 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2025-06-12 17:34:28.675 INFO 35252 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2025-06-12 17:34:28.734 INFO 35252 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 45ms. Found 0 Redis repository interfaces.
2025-06-12 17:34:29.023 WARN 35252 --- [ main] o.m.s.mapper.ClassPathMapperScanner : No MyBatis mapper was found in '[com.cisdi.info.mapper]' package. Please check your configuration.
2025-06-12 17:34:30.309 INFO 35252 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.datasource.dynamic-com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties' of type [com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
默认的日志格式从左到右由这几部分组成:
- 日期时间: 精确到毫秒级别 2025-06-12 17:34:27.683
- 日志级别: TRACE、DEBUG、INFO、WARN、ERROR等 INFO
- 进程ID 35252
- ---: 消息分隔符
- 线程名: 用[]包含起来 [ main]
- Logger名: 通常是产生日志的类名 com.cisdi.info.Application
- 消息: 日志记录的内容 Starting Application on pps with PID 35252
注意:logback 没有FATAL级别, 对应的是ERROR。
三、修改日志显示格式
在springboot的底层,spring-boot包下就定义好了日志的配置信息
这里就不带大家细看了,感兴趣的可以自行研究。
如果要修改日志的显示格式,主要用到 logging.pattern 开头的配置,直接在配置文件修改即可。
例如:logging.pattern.dateformat=yyyy年MM月dd日 HH:mm:ss.SSS
四、日志显示级别
4.1 基本原则
日志级别从低到高分别是
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
系统只会打印指定级别及以上级别的日志
举例说明
springboot默认的日志显示级别是INFO
换句话说:默认是可以打印出来INFO、WARN、ERROR级别的日志信息。
4.2 修改默认显示级别
Springboot可以更改默认日志级别,甚至X能精确到某个包、某个类。
配置文件中配置logging.level.<logger-name>=<level>指定日志级别。
level可取值范围:TRACE 、DEBUG 、 INFO 、 WARN 、ERROR
更改Springboot下所有日志的级别
logging.level.root=debug
更改某个包的日志级别
logging.level.com.hssy.info.controller=debug
更改某个类的日志级别
logging.level.com.cisdi.info.controller.TestController=debug
五、日志分组
如果我们想批量调整某些包下或者某些类的日志级别,当然可以像前面讲解的那样些。
随着修改的日志规则越多,这种方式显然比较麻烦。那么我们就可以对日志进行分组。
logging.group.<自定义组名>
上述就可以替换成如下所示
这么做的好处是可以对日志进行分组批量管理。对日志规则复杂一点的,分组的优势是很明显的。
Springboot底层也提供了几个默认的分组:
Name | Loggers |
web | org.springframework.core.codec org.springframework.http org.springframework.web org.springframework.boot.actuate.endpoint.web org.springframework.boot.web.servlet.ServletContextInitializerBeans |
sql | org.springframework.jdbc.core org.hibernate.SQL org.jooq.tools.LoggerListener |
六、输出到文件
Spring默认将日志输出到控制台,但是一般情况下,应用上线到生产环境后,我们希望将它输出到文件中。
这样做的好处是一旦应用出现什么问题,我们也可以通过日志文件进行定位排查。相当于对日志进行了持久化操作。
log.file.name=(路径)名称
- 只写名称,如果不指定路径,那么日志文件默认放在和项目下。
- 路径 + 名称, 那么日志文件就存放在指定的路径下。
(了解)logging.file.path=路径
通过这种方式,只能写路径,不能写名称。系统会自动生成一个叫spring.log的日志文件。
如果这两种方式你都写了,那么只有logging.file.name会生效。
因此,建议用logging.file.name的方式!
七、日志归档与切割
7.1 说明
如果将日志都放在同一个文件下,那么随着时间的推移,这个文件肯定会越来越大,最后面临的问题是这个日志文件根本无法查阅,甚至还会降低系统的性能。
因此,我们建议是按日期对日志进行归档。
比如每天的日志都放在一个文件中,这样项目的日志文件就会被分散到各天的日志文件里。
但是这样还有一个问题,假如某天并发量很高,又或者频繁出现故障,打印超多的日志信息。那么依然会面临大文件的问题。
所以,这里有提出了日志切割的想法。
我们可以将同一天的日志切割成不同的文件,又进行分别存储。比如文件超过10MB,就切割成另外一个文件进行存储。
7.2 规则
如果使用的logback(springboot默认整合),可以通过 application.properties文件指定日志滚动规则。
如果是其他日志系统,需要自行配置(添加log4j2.xml 或 log4j2-spring.xml)。
支持的滚动规则如下:
配置项 | 描述 |
logging.logback.rollingpolicy.file-name-pattern | 日志存档的文件名格式 默认值:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz |
logging.logback.rollingpolicy.clean-history-on-start | 应用启动时是否清除以前存档 默认值:false |
logging.logback.rollingpolicy.max-file-size | 存档前,每个日志文件的最大大小 默认值:10MB |
logging.logback.rollingpolicy.max-history | 日志文件保存的最大天数 默认值:7 |
logging.logback.rollingpolicy.total-size-cap | 日志文件被删除之前,可以容纳的最大大小 默认值:0B 设置1GB则磁盘存储超过1GB日志后就会删除旧日志文件 |
注意
如果你发现,你的springboot配置文件没有这些配置项,请检查一下springboot的版本,我当前的版本是3.3.4版本。
像springboot 2.x的很多版本都没有这些配置,具体我也不清楚是从哪个版本出现的,建议参考我这个版本。
当然没有也不要慌,还有其他的配置项可以使用。如下所示:
默认值和配置名称几乎都一样,看一眼就清楚了。
只是不清楚为什么在SpringBoot3.3.4中过时了。不过这个不用管,用Spring2.x,只要还能用,那用就行了。
八、自定义日志配置
通常我们配置application.properties就够了。当然也可以自定义,比如:
日志系统 | 自定义 |
Logback | logback-spring.xml、logback-spring.groovy、logback.xmll、logback.groovy |
Log4j2 | log4j2-spring.xml、log4j2.xml |
如果可能,建议在日志配置中使用-spring命名(例如:logback-spring.xml 而不是 logback.xml)。如果不带-spring,那么spring无法完全控制日志的初始化。
这边给一个logback-spring.xml 案例,把它放在resources目录下,感兴趣的可以自行研究。
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds"><!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 --><!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true --><!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 --><!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 --><contextName>logback</contextName><!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 --><property name="log.path" value="D:/guli_log/edu" /><!-- 彩色日志 --><!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 --><!-- magenta:洋红 --><!-- boldMagenta:粗红--><!-- cyan:青色 --><!-- white:白色 --><!-- magenta:洋红 --><property name="CONSOLE_LOG_PATTERN"value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/><!--输出到控制台--><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息--><!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 --><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter><encoder><Pattern>${CONSOLE_LOG_PATTERN}</Pattern><!-- 设置字符集 --><charset>UTF-8</charset></encoder></appender><!--输出到文件--><!-- 时间滚动输出 level为 INFO 日志 --><appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_info.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 每天日志归档路径以及格式 --><fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录info级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>INFO</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 时间滚动输出 level为 WARN 日志 --><appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_warn.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset> <!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录warn级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>warn</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 时间滚动输出 level为 ERROR 日志 --><appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_error.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset> <!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录ERROR级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!--<logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。<logger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。name:用来指定受此logger约束的某一个包或者具体的某一个类。level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,如果未设置此属性,那么当前logger将会继承上级的级别。--><!--使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:--><!--开发环境:打印控制台--><springProfile name="dev"><!--可以输出项目中的debug日志,包括mybatis的sql日志--><logger name="com.guli" level="INFO" /><!--root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG可以包含零个或多个appender元素。--><root level="INFO"><appender-ref ref="CONSOLE" /><appender-ref ref="INFO_FILE" /><appender-ref ref="WARN_FILE" /><appender-ref ref="ERROR_FILE" /></root></springProfile><!--生产环境:输出到文件--><springProfile name="pro"><root level="INFO"><appender-ref ref="CONSOLE" /><appender-ref ref="DEBUG_FILE" /><appender-ref ref="INFO_FILE" /><appender-ref ref="ERROR_FILE" /><appender-ref ref="WARN_FILE" /></root></springProfile></configuration>
需要说明一点的是,通过application.yaml配置和xml文件两种方式,建议不要混用,如果两种都用的话,可能只会xml文件生效。
九、切换日志组合
如果我们不希望用springboot默认的logback日志框架,那么我们也可以改用其他的日志框架。
怎么做呢?
首先,在springboot的官方starter中,就提供了log4j2的依赖,叫spring-boot-starter-log4j2。
只不过默认的是spring-boot-starter-logging。
要切换也很简单。
在自己的pom.xml文件中,利用maven的就近原则,导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId>
</dependency>
这还没完,需要排除默认的 spring-boot-starter-logging 依赖。然后再引入spring-boot-starter-log4j2。
所以就应该是这样:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
使用log4j2后,配置文件的方式设置日志参数依旧一样,可以不用动。但如果是自定义的日志xml文件,则不一样了,需要替换掉。这里也给出一个log4j2-spring.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!-- status="WARN"是Log4j2框架的日志级别,当框架启动有问题,会根据此配置来打印日志-->
<Configuration status="WARN" monitorInterval="30"><!-- 定义变量 --><Properties><Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Property><Property name="LOG_DIR">logs</Property><Property name="LOG_FILE_NAME">app.log</Property></Properties><!-- 定义输出器(Appenders) --><Appenders><!-- 控制台输出 --><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="${LOG_PATTERN}"/></Console><!-- 滚动文件输出 --><RollingFile name="RollingFile" fileName="${LOG_DIR}/${LOG_FILE_NAME}"filePattern="${LOG_DIR}/app-%d{yyyy-MM-dd}-%i.log.gz"><PatternLayout pattern="${LOG_PATTERN}"/><Policies><!-- 按时间滚动(每天) --><TimeBasedTriggeringPolicy interval="1" modulate="true"/><!-- 按文件大小滚动(最大 100MB) --><SizeBasedTriggeringPolicy size="100 MB"/></Policies><!-- 最多保留 30 天或 10 个文件 --><DefaultRolloverStrategy max="10"/></RollingFile><!-- 异步日志(提升性能) --><Async name="AsyncAppender" bufferSize="1024"><AppenderRef ref="RollingFile"/></Async></Appenders><!-- 定义日志记录器(Loggers) --><Loggers><!-- Spring 框架日志(INFO 级别) --><Logger name="org.springframework" level="INFO" additivity="false"><AppenderRef ref="Console"/></Logger><!-- MyBatis SQL 日志(DEBUG 级别) --><Logger name="com.example.mapper" level="DEBUG" additivity="false"><AppenderRef ref="Console"/><AppenderRef ref="AsyncAppender"/></Logger><!-- 根日志记录器(全局默认),level="INFO"是应用程序的日志级别 --><Root level="INFO"><AppenderRef ref="Console"/><AppenderRef ref="AsyncAppender"/></Root></Loggers>
</Configuration>