内容简介:本文记录 SpringBoot 与 Logback 是如何工作的,即记录 SpringBoot 中 Logback 是怎么一步一步初始化的。用以测试的 SpringBoot 版本是 1.5.16, 而非最新的 SpringBoot 2。关于 SpringBoot 日志的官方文档在SpringBoot 默认使用 Slf4J + Logback 来记录日志,对于一个基本的依赖于的项目,它依赖了 spring-boot-starter-logging 组件,而该组件引入了以下几个依赖
本文记录 SpringBoot 与 Logback 是如何工作的,即记录 SpringBoot 中 Logback 是怎么一步一步初始化的。用以测试的 SpringBoot 版本是 1.5.16, 而非最新的 SpringBoot 2。关于 SpringBoot 日志的官方文档在 Logging , 但不太详细或透彻。本文不承诺说理解得更有深度,只是为官方文档提供更多方面的参考。
SpringBoot 默认使用 Slf4J + Logback 来记录日志,对于一个基本的依赖于
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
的项目,它依赖了 spring-boot-starter-logging 组件,而该组件引入了以下几个依赖
- logback-classic: 依赖了 Slf4J
- jcl-over-slf4j
- jul-to-slf4j
- log4j-over-slf4j
相当于把其他的日志框架全桥接到了 Slf4J + Logback 上去了。
那么 SpringBoot Web 项目是怎么样子的呢?spring-boot-starter-web 依赖于 spring-boot-starter,所以日志框架选用上就没有一点区别了。
SpringBoot 应用默认日志输出
从一个最简单的 SpringBoot 应用程序来感受它的配置日志输出,一个 Maven 项目,最基本的配置是
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.16.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> </dependencies>
注意: spring-boot-starter-parent 的 pom.xml 文件值得瞧一瞧的。
application.properties 文件为空,并且没有任何的 logback 配置文件在 resources 目录中。
来个最简单的程序
@SpringBootApplication public class Application { private static final Logger logger = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { logger.info("aaa"); SpringApplication.run(Application.class, args); logger.info("bbb"); } }
在 SpringApplication.run(...) 前后各调用 logger.info(...) 输出信息
前面 logger.info("aaa") 和 logger.info("bbb") 的输出用红线标示出来了,可以非常感性的认识到
- 它们输出样式不同,所以使用了不同的日志配置
- logger.info("aaa") 发生在 Spring 上下文初始化之前,以 Logback 的默认行为初始化的 LoggerFactory
- logger.info("bbb") 发生在 Spring 上下文初始化之后,因此 SpringBoot 又重新配置了 Logback 的 LoggerFactory
- #2 不是我们这里探讨的范畴,它和普通 Java 应用使用 Logback 是一致的,主要看 #3 怎么来的,并且默认的 Log 是怎么样的配置
SpringBoot 是如何初始化 Logback 的
在 Logging 一文中提到了 Spring Boot 有一个 LoggingSystem
抽象来负责配置日志系统,并且 Logback 是首选。 LoggingSystem
是一个抽象类,它的实现层次如下
既然说 Logback 是首先,那么 SpringBoot 最终是要用到 LogbackLoggingSystem
这个类的,那我们从源代码跟踪一下 SpringBoot 的 Spring 上下文是如何与 Logback 衔接起来的。
能与 Spring 上下文进行交互的一般来说是 ApplicationEvent, 这里是 org.springframework.boot.logging.LoggingApplicationListener
, 它实现了 ApplicationListener
, 看 LoggingApplicationListener
的事件方法
@Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ApplicationStartingEvent) { onApplicationStartingEvent((ApplicationStartingEvent) event); // #1 } else if (event instanceof ApplicationEnvironmentPreparedEvent) { onApplicationEnvironmentPreparedEvent( // #2 (ApplicationEnvironmentPreparedEvent) event); } else if (event instanceof ApplicationPreparedEvent) { onApplicationPreparedEvent((ApplicationPreparedEvent) event); // #3 } ......
#1 找到 LoggingSystem
的实现类,在 LoggingSystem.get(classloader)
方法中,如果配置了系统属性 org.springframework.boot.logging.LoggingSystem
对应的实现类的话,就用它,指定为 none
值就用 NoOpLogginSystem
实现,即没有任何日志输出。如果没有指定 org.springframework.boot.logging.LoggingSystem
系统属性, LoggingSystem
则尝试以下的顺序找实现类
- ch.qos.logback.core.Appender => org.springframework.boot.logging.logback.LogbackLoggingSystem
- ora.apache.logging.log4j.core.impl.Log4jContextFactory => org.springframework.boot.logging.log4j2.Log4J2LoggingSystem
- java.util.logging.LogManager => org.springframework.boot.logging.java.JavaLoggingSystem
而显然 LogbackLoggingSystem 对应的类 ch.qos.logback.core.Appender
是存在于 springboot starter 中的,所以在 #1 中可以确定是用 LogbackLoggingSystem
实现
#3 先说这最后一步,如果初始化好,把 LoggingSystem
的实例(此处为 LogbackLoggingSystem 实例) 注册名为 springBootLogginSystem
的 Spring Bean
#2 对日志进行配置,具体实现在 LoggingApplicationListener.initialize(environment, classLoader)
和 LogbackLoggingSystem.initialize(...)
方法中。不列出实际代码来了,只解翻译一下过程
- 试图从 Spring 属性(包括配置在 Spring 属性文件,--logging.file= 或 -Dlogging.file= 这样的配置)读出配置的
logging.file
和logging.path
值,如果有的话,分别映射为LOG_FILE
和LOG_PATH
系统属性值,这可以在 logback.xml 的配置中用 ${LOG_FILE} 引用到 - 初始日志级别的设置,如果 spring 属性中配置了
debug=true
则为 LogLevel.DEBUG, 如果配置了trace=true
则为 LogLevel.TRACE。后面还会专为某些包预设一些日志级别,并且最后的日志级别可在 Spring 属性中用logging.level.logger_name=DEBUG
来配置,如logging.level.org.springframework=DEBUG
- 如果用 Spring 属性
logging.config
指定了配置文件,则使用该配置文件初始化 Logback 的 LoggerFactory,否则LogbackLoggingSystem
将会以下面的顺序来查找 Logback 配置文件logback-test.groovy, logback-test.xml, logback.groovy, logback.xml
logback-test-spring.xml, logback-test-spring.xml, logback-spring.groovy, logback-spring.xml (AbstractLoggingSystem.getSpringConfigLocations() 方法)
注意:SpringBoot 会忽略掉普通 Logback 应用的系统属性
logback.configurationFile
设定配置文件的方法if (StringUtils.hasText(System.getProperty(CONFIGURATION_FILE_PROPERTY))) { getLogger(LogbackLoggingSystem.class.getName()).warn( "Ignoring '" + CONFIGURATION_FILE_PROPERTY + "' system property. " + "Please use 'logging.config' instead."); }
- 如果检查了以上八个文件都不存在的话,就要调用
LogbackLoggingSystem.loadDefaults(initializationContext, logFile)
来配置默认的日志。
SpringBoot 没有任何日志配置文件时配置
这块其实是上面步骤 #2 中的一个子步骤,因其重要才将其单独列出,来看看 SpringBoot 在没有加载到任何的配置文件时如何配置默认 Logback 的 LoggerFactory。入口就是 LogbackLoggingSystem.loadDefaults(initializationContext, logFile)
。
首先,默认显示日志级别的格式是: ${logging.pattern.level:${LOG_LEVEL_PATTERN:%5p}}
, 可用 Spring 属性 logging.pattern.level
或系统属性 LOG_LEVEL_PATTERN
,默认为 %5p
。
其他的默认配置就要参考类 org.springframework.boot.logging.logback.DefaultLogbackConfiguation
不管有没有配置 logging.file
或 logging.path
,SpringBoot 都会初始化 consoleAppender, 并且默认的输出模式是
private static final String CONSOLE_LOG_PATTERN = "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} " + "%clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} " + "%clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} " + "%clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}";
该模式可用 Spring 属性 logging.pattern.console
进行覆盖设置。注意,SpringBoot 还为我们定义了 clr
, wEx
这两个 Converter
。
如果配置了 Spring 属性 logging.file
和 logging.path
其中一个或两个,就会在 consoleAppender
的基础上再加一个 fileAppender
, 它的输出模式是
private static final String FILE_LOG_PATTERN = "%d{yyyy-MM-dd HH:mm:ss.SSS} " + "${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}";
该模式可以用 Spring 属性 logging.pattern.file
进行覆盖。
日志文件是 10MB
大小不断滚动的,不会删除旧文件。
日志文件路径如何决定的
- 如果只设置了 Spring 属性
logging.file
, 就是logging.file
所指定的文件,文件名可以是绝对文件路径,或者相对路径 - 如果只设置了 Spring 属性
logging.path
, 那么日志文件是logging.path
下的spring.log
文件 - 如果以上两个属性同时指定了,则只有
logging.file
是有用的,与 #1 同
无论是对于 consoleAppender
还是 fileAppender
, 都是设置 INFO 为默认日志级别,并且预设了一些 logger 的日志输出级别。
简单的 SpringBoot 日志文件配置
理解了 SpringBoot 是如何初始化 Logback 日志配置后,我们来看一下项目中几种最简的日志配置方式。
日志同时输出到控制台和文件
依据 SpringBoot 加载 Logback 配置文件的顺序,我们可以在 classpath 下放 logback-spring.xml
或 logback.xml
, 注意是 logback.xml
被优先选择。内容如下
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml"/> <logger name="org.springframework.web" level="DEBUG"/> </configuration>
设置 Spring 属性 logging.file
或系统属性 LOG_FILE
来指定日志输出文件名。或者用 Spring 属性 logging.path
或系统属性 LOG_PATH
指定 spring.log
的路径。
日志只输出到文件
<?xml version="1.0" encoding="UTF-8"?> <configuration> <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/file-appender.xml" /> <root level="INFO"> <appender-ref ref="FILE" /> </root> </configuration>
用上面相同的方式指定日志文件的路径。
只输出到控制台
就更简单了,可以什么配置文件也不要,并且不要配置 logging.file
和 logging.path
。而且效果与下面的配置是一样的。
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/defaults.xml" /> <include resource="org/springframework/boot/logging/logback/console-appender.xml" /> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> </configuration>
小结:
- SpringBoot 基础的依赖于 starter 的项目默认采用 Slf4J + Logback 来输出日志
- 没有任何配置文件,也没有配置 Spring 属性
logging.file
,logging.path
或系统属性LOG_FILE
,LOG_PATH
的情况下只会输出日志到控制台 - 没有任何配置文件,且有配置 #2 中任何一个属性的情况下将会同时输出日志到控制台与文件,文件以 10MB 大小滚动,不删除旧文件
- 不采用外部配置文件的情况下,可以用一些 Spring 属些来进行简单的日志配置,如
logging.pattern.file
等 - 可以设置 Spring 属性
logging.config
来指定外部 logback 配置文件,但忽略 Logback 默认用系统属性logback.configurationFile
指定配置文件的方式 - 以上叙述的 Spring 属性,可用多种设置方式,如 Spring 属性
abc
,有四种方式:1) application.properties 文件中的abc=xxx
, 2)环境变量export abc=xxx
, 3) 启动参数--abc=xxx
,4) 系统属性-Dabc=xxx
- 类路径下的配置文件可以用
logback-spring.xml
或logback.xml
,但是logback.xml
优先加载,并未遵循先特殊再普通的原则。(Logback 1.3.0 之后由于支持 Java 9,但是 Groovy 与 Java 9 未处理好关系,所以 Logback 1.3.0 不能支持 .groovy 的配置文件) - 为更精细化的控制 Logback 的输出,我们通常都会在类路径下旋转
logback.xml
或logback-spring.xml
配置文件,二选一了。我没发现这两个文件有什么不同。
以上所述就是小编给大家介绍的《SpringBoot 与 Logback 日志配置》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- springboot 默认日志配置
- Nginx的log日志配置
- SpringBoot 实战 (七) | 默认日志配置
- 第一讲:Git分区,配置与日志
- Spring/SpringMVC 项目 apollo 支持日志配置
- Redis的Errorlog或者启动日志的配置
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTTP Essentials
Stephen A. Thomas、Stephen Thomas / Wiley / 2001-03-08 / USD 34.99
The first complete reference guide to the essential Web protocol As applications and services converge and Web technologies not only assume HTTP but require developers to manipulate it, it is be......一起来看看 《HTTP Essentials》 这本书的介绍吧!