从零开始 Spring Boot 34:日志 II
图源:简书 (jianshu.com)
在从零开始 Spring Boot 10:日志 - 红茶的个人站点 (icexmoon.cn)中,我简单介绍过如何在Spring Boot中整合SLF4J日志。实际上,如果没有特殊需求,完全可以不使用第三方日志,就使用Spring Boot的默认日志功能,这样在配置上会省很多事。下面介绍Spring Boot默认使用的 logback 日志功能。
日志格式
Spring Boot的默认的日志输出格式类似于下面的例子:
2023-03-03T21:18:18.827+08:00 INFO 19388 --- [ main] o.s.b.d.f.s.MyApplication : Starting MyApplication using Java 17 with PID 19388 (/opt/apps/myapp.jar started by myuser in /opt/apps/)
2023-03-03T21:18:18.834+08:00 INFO 19388 --- [ main] o.s.b.d.f.s.MyApplication : No active profile set, falling back to 1 default profile: "default"
2023-03-03T21:18:20.439+08:00 INFO 19388 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2023-03-03T21:18:20.461+08:00 INFO 19388 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-03-03T21:18:20.461+08:00 INFO 19388 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.5]
2023-03-03T21:18:20.600+08:00 INFO 19388 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-03-03T21:18:20.602+08:00 INFO 19388 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1685 ms
2023-03-03T21:18:21.078+08:00 INFO 19388 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2023-03-03T21:18:21.093+08:00 INFO 19388 --- [ main] o.s.b.d.f.s.MyApplication : Started MyApplication in 2.998 seconds (process running for 3.601)
输出内容包含以下项目:
- Date和时Time:精确到毫秒,易于排序。
- 日志级别:
ERROR
,WARN
,INFO
,DEBUG
, 或TRACE
. - 进程ID。
- 一个
---
分隔符,以区分实际日志信息的开始。 - 线程名称:包含在方括号中(对于控制台输出可能会被截断)。
- 记录器名称:这通常是源类的名称(通常是缩写)。
- 日志消息。
控制台输出
默认情况下,日志会输出 ERROR
、WARN
和 INFO
级别的消息到控制台。 你也可以通过用 --debug
标志启动你的应用程序,来启用 debug
模式。
$ java -jar myapp.jar --debug
你也可以在你的
application.properties
中指定debug=true
。
另外,你可以通过在启动应用程序时使用 --trace
标志(或在 application.properties
中使用 trace=true
)来启用 “trace” 模式。 这样做可以对一些核心记录器(嵌入式容器、Hibernate schema生成和整个Spring组合)进行跟踪记录。
在实际工作中,通常会选择在开发环境尽可能多输出信息,所以可以选择在
application-dev.properties
中配置:debug=true trace=true
在
application-test.properties
中配置:debug=true
多环境部署的内容可以参考从零开始 Sping Boot 20:多环境部署 - 红茶的个人站点 (icexmoon.cn)。
彩色输出
默认情况下,Spring Boot会检测控制台是否支持ANSI进行彩色输出,如果支持,输出到控制台的日志就是彩色的。这种行为可以通过配置项spring.output.ansi.enabled
进行修改:
spring.output.ansi.enabled=always
,总是输出ANSI彩色信息。spring.output.ansi.enabled=never
,不输出彩色信息。spring.output.ansi.enabled=detect
,自动检测。
要说明的是,这种行为不会影响到IDE,即使设置了spring.output.ansi.enabled=never
,你依然会看到彩色输出。但通过控制台运行应用(java -jar xxx
)时,控制台会受到影响:
输出到文件
默认情况下Spring Boot不会输出日志到文件,可以通过以下配置项开启:
logging.file.path=logs
这样设置以后日志会保存在当前工作目录下的logs
目录下。当然你也可以指定绝对路径,比如/var/xxx/log
。
日志文件在达到10MB时就会轮换,与控制台输出一样,默认情况下会记录 ERROR
、WARN
级和 INFO
级别的信息。
文件轮换(滚动日志)
默认情况下,日志文件会在达到10MB的时候进行分割,分割后的日志文件会被打包成.gz
文件保存:
可以通过以下配置来修改分割日志文件时的大小:
logging.logback.rollingpolicy.max-file-size=1KB
单位可以是KB\MB\GB等。
默认情况下日志轮转发生在每天的午夜时分(24:00),可以通过以下属性控制日志轮转后保留的历史日志文件数目:
logging.logback.rollingpolicy.max-history=5
- 默认是
7
。- 分割日志不等同于日志轮转,实际测试发现分割日志时并不会触发轮转,比如当你设置轮转时最大文件大小为
1KB
,当日志文件超过1KB
时,就会分割文件,但此时并不会进行轮转,所以max-history
属性是失效的,分割的日志文件数量会无限增长,直到午夜时分进行轮转以清除历史日志文件。
理论上可以通过设置轮转日志文件命名规则来设置轮转触发时间,比如:
logging.logback.rollingpolicy.file-name-pattern=logs/rollingpolicy/myapplication.%d{yyyy-MM}.log
logback可以识别file-name-pattern
中的%d{yyyy-MM}
,所以示例中的轮转会以月为单位触发(默认是%d{yyyy-MM-dd}
,因此以日为单位轮转)。
之所以说是“理论上”,是因为我实际测试发现只要设置了file-name-pattern
属性,整个Spring Boot的日志输出都会失效,不会再产生任何日志文件。我不清楚这是否是某个版本的bug,翻阅了logback的相关网页后并没有找到解决方案。
- 关于logback的
file-name-pattern
属性,可以参考Chapter 4: Appenders (qos.ch)。- 实际上我们也并不是只能借助
file-name-pattern
来整理和归档日志,如果服务是部署在Linux服务器,完全可以自己编写Shell脚本来对日志进行归档和处理,这样归档的时间、存放目录结构以及打包和压缩都可以很自由地进行定制。Shell脚本的编写可以参考Linux 之旅 10:Shell 脚本 - 红茶的个人站点 (icexmoon.cn)。
日志级别
可以使用logging.level.<logger-name>=<level>
的方式设置包的日志级别,比如:
logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.com.example.log=debug
可以设置的日志级别包括:TRACE
, DEBUG
, INFO
, WARN
, ERROR
, FATAL
, 或 OFF
。
示例中的logging.level.root
是根记录器(root logger)。
日志组
有时候我们希望一次性设置多个包的日志级别,这时候就可以使用日志组(log group),将这多个包设置为一个日志组,然后针对这个日志组设置日志级别,比如:
logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
logging.level.tomcat=trace
Spring Boot 已经预定义了一些日志组:
组名 | 组中的logger |
---|---|
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 |
扩展日志
如果需要对日志进行更高级别的设置,可以选择扩展Logback或者Log4j2,具体方式可以参考:
- Logback 扩展 (springdoc.cn)
- Log4j2 扩展 (springdoc.cn)
- 从零开始 Spring Boot 10:日志 - 红茶的个人站点 (icexmoon.cn)
The End,谢谢阅读。
本文的完整示例可以通过learn_spring_boot/ch34/log · GitHub获取。
参考资料
- 从零开始 Sping Boot 20:多环境部署 - 红茶的个人站点 (icexmoon.cn)
- 日志 (springdoc.cn)
- Chapter 4: Appenders — 第四章:附录 (qos.ch)
- SpringBoot Logback 日志配置 - 知乎 (zhihu.com)