
SpringBoot3.x日志生产最佳实践原来是这样!
免责声明~
任何文章不要过度深思!
万事万物都经不起审视,因为世上没有同样的成长环境,也没有同样的认知水平,更「没有适用于所有人的解决方案」;
不要急着评判文章列出的观点,只需代入其中,适度审视一番自己即可,能「跳脱出来从外人的角度看看现在的自己处在什么样的阶段」才不为俗人。
怎么想、怎么做,全在乎自己「不断实践中寻找适合自己的大道」
0 前言
SpringBoot对日志的配置和加载进行了封装,让我们可以很方便地使用一些日志框架,只需要定义对应日志框架的配置文件,如LogBack、Log4j、Log4j2等,代码内部便可以直接使用。
如我们在resources目录下定义了一个logback xml文件,文件内容是logback相关配置,然后就可以直接在代码在使用Logger记录日志啦:
SpringBoot对日志功能的封装:
1 LoggingSystem内部结构
1.1 SpringBoot3.0默认支持的日志类型
- JDK内置的Log(JavaLoggingSystem)
- Log4j2(Log4J2LoggingSystem)
- Logback(LogbackLoggingSystem)
LoggingSystem是个抽象类,内部
1.2 API
- beforeInitialize:日志系统初始化之前需要处理的事。抽象方法
- initialize:初始化日志系统。默认不进行任何处理,需子类初始化
- cleanUp:日志系统的清除工作。默认不进行任何处理,需子类清除
- getShutdownHandler:返回一个Runnable,用于当JVM退出时处理日志系统关闭后需要进行的操作,默认null
- setLogLevel:抽象方法,设置对应logger级别
1.3 AbstractLoggingSystem抽象类
继承LoggingSystem抽象类进行扩展,实现beforeInitialize方法,但内部无任何处理。重点在initialize
重写initialize
① 指定日志文件
② 约定配置文件
以LogbackLoggingSystem.java为例,看具体的
1.4 初始化过程
根据AbstractLoggingSystem 使用logback日志库时,会查找classpath下是否存在这些文件:
- logback-test.groovy
- logback-test.xml
- logback.groovy
- logback.xml
- logback-test-spring.groovy
- logback-test-spring.xml
- logback-spring.groovy
- logback-spring.xml
2 LoggingSystem的初始化
LoggingApplicationListener是ApplicationListener接口的实现类,会被 SpringBoot 使用工厂加载机制加载。
2.1 spring.factories
spring-boot-3.0.0.jar/META-INF/spring.factories:
注意到LoggingApplicationListener,和 SpringBoot 启动流程关联点:
2.2 SpringApplication.java
2.3 LoggingApplicationListener.java
SpringApplication#run执行时触发该事件
spring-boot-starter模块内部会引用spring-boot-starter-logging模块,这starter-logging模块内部会引入logback相关依赖。这依赖会导致LoggingSystem的静态方法get获取LoggingSystem时得到LogbackLoggingSystem。
因此springboot程序使用logback作默认日志。前提都是以LogbackLoggingSystem作为日志系统。
2.4 FAQ
① 项目无任何日志配置
执行到AbstractLoggingSystem#initialize时,日志配置文件为null:
最后只能调loadDefaults进行加载,LogbackLoggingSystem#loadDefaults方法,由于logFile为null,所以最终只构造个ConsoleAppender。
所以项目没有任何日志配置时,默认就是在控制台打印了项目启动信息。
② 项目无任何logback配置,只有yaml中配置logging.file/path
logging.file和logging.path的配置在LogFile这个日志文件类中生效。
比如yaml配置如下(只定义了logging.file):
这配置导致调用initialize方法时候logFile存在,这样不止有ConsoleAppender,还有个FileAppender,这个FileAppender对应的文件就是LogFile文件,即 /tmp/temp.log日志文件。
如yaml配置如下(只定义了logging.path):
这时FileAppender对应file是/tmp/spring.log文件。
LogFile.java
所以若配置了logging.path/file,生效的只有logging.file配置。
③ resources下有logback.xml配置
相当于classpath下存在logback.xml文件。LogbackLoggingSystem#getStandardConfigLocations返回如下:
- logback-test.groovy或logback-test-spring.groovy
- logback-test.xml或logback-test-spring.xml
- logback.groovy或logback-spring.groovy
- logback.xml或logback-spring.xml
在resources目录下定义logback-spring.xml文件,内容如下:
这时logging.file配置失效,这是因为没有调用loadDefaults方法(loadDefaults方法内部会把LogFile构造成FileAppender),而是调用了loadConfiguration方法,该方法会根据logback.xml文件中的配置去构造Appender。
④ resources下有my-logback.xml配置
由于LogbackLoggingSystem中没有对my-logback.xml路径的解析,所有不会被识别,但是可以在yaml中配置logging.config配置:
这样配置就能识别my-logback.xml文件。
3 NoOpLoggingSystem
SpringBoot内部的NoOpLoggingSystem,这个日志系统内部什么都不做,构造过程:
加上启动参数:
即可构造NoOpLoggingSystem。
写在最后
公众号
:JavaEdge
专注分享软件开发全生态相关技术文章
、视频教程
资源、热点资讯等,如果喜欢我的分享,给 🐟🐟 点一个赞
👍 或者 ➕关注
都是对我最大的支持。
文章转载自公众号: JavaEdge
