1 日志简介
Spring Boot使用Commons Logging记录所有内部日志,但是它将底层日志实现打开,为Java.Util.Logging,Log4J2和Logback提供默认配置。 在每个案例中,loggers都预先配置,以使用控制台输出,同时还提供可选的文件输出。
默认情况下,如果你使用“starters”,Logback将会被用于记录日志。还包括占用Logback路由,以确保使用Java Util Logging、Commons logging、Log4J或SLF4J的依赖库都能正常工作。
2 默认日志logback
2.1 logback日志简介
SLF4J——Simple Logging Facade For Java,它是一个针对于各类Java日志框架的统一Facade抽象。Java日志框架众多——常用的有java.util.logging
, log4j
, logback
,commons-logging
, Spring框架使用的是Jakarta Commons Logging API (JCL)。而SLF4J定义了统一的日志抽象接口,而真正的日志实现则是在运行时决定的——它提供了各类日志框架的绑定。
Logback是log4j框架的作者开发的新一代日志框架,它效率更高、能够适应诸多的运行环境,同时天然支持SLF4J。
默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台。在运行应用程序和其他例子时,可以看到很多INFO级别的日志。
从上图可以看到,日志输出内容元素具体如下:
- 时间日期:精确到毫秒
- 日志级别:ERROR, WARN, INFO, DEBUG or TRACE
- 进程ID
- 分隔符:
---
标识实际日志的开始 - 线程名:方括号括起来(可能会截断控制台输出)
- Logger名:通常使用源代码的类名
- 日志内容
用Logback来记录日志,需添加日志依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
实际开发中我们不需要直接添加该依赖,你会发现spring-boot-starter其中包含了spring-boot-starter-logging,该依赖内容就是 Spring Boot 默认的日志框架 logback。
2.2 application.properties配置中的日志相关属性
2.2.1 控制台输出
日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出。Spring Boot中默认配置ERROR
、WARN
和INFO
级别的日志输出到控制台。您还可以通过启动您的应用程序–debug标志来启用“调试”模式(开发的时候推荐开启),以下两种方式皆可:
- 在运行命令后加入
--debug
标志,如:$ java -jar springTest.jar --debug
- 在
application.properties
中配置debug=true
,该属性置为true的时候,核心Loggers(包含嵌入式容器、hibernate、spring)会输出更多内容,启用debug模式并不会使用debug级别配置您的应用程序来记录所有信息。
或者,您可以通过在应用程序中使用-trace标志(或在application.properties中配置trace=true)启动应用程序来启用“跟踪”模式。
2.2.2 文件输出
默认情况下,Spring Boot将日志输出到控制台,不会写到日志文件。如果要编写除控制台输出之外的日志文件,则需在application.properties中设置logging.file或logging.path属性。
- logging.file,设置指定的日志文件,可以是绝对路径,也可以是相对路径。如:
logging.file=my.log
- logging.path,设置指定的目录,会在该目录下创建spring.log文件,并写入日志内容,如:
logging.path=/var/log
默认情况下,日志文件的大小达到10MB时会切分一次,产生新的日志文件,默认级别为:ERROR、WARN、INFO
日志系统在应用程序生命周期的早期被初始化,并且在通过@propertysource注解加载的属性文件中不会找到这样的日志属性。
日志属性与实际的日志基础结构无关。因此,特定的配置键(例如logback中的
logback.configurationFile
)不是由spring boot管理的。
2.2.3 彩色日志输出
省略...
2.2.4 日志级别
所有支持日志记录的系统都可以在Spring环境中设置记录级别(例如在application.properties中)
格式为:’logging.level.* = LEVEL’
logging.level
:日志级别控制前缀,*
为包名或Logger名LEVEL
:选项TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
root日志可以使用 logging.level.root
配置,application.properties实例:
logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
默认情况下,Spring boot对 Thymeleaf
INFO
消息进行了重新映射,使它们在调试级别上被记录,这有助于减少标准日志输出中的噪声。有关如何在自己的配置中应用重新映射的详细信息,请参阅LevelRemappingAppender。
2.2.5 自定义日志配置
可以通过在classpath中包含适当的库来激活各种日志系统,并通过在classpath根目录提供适当的配置进行定制。或者在适当的位置提供spring 环境属性logging.config。
还可以强制spring boot使用特定的日志系统通过使用 org.springframework.boot.logging.LoggingSystem
系统属性。 该值应该是一个 LoggingSystem
实现的完全限定类名。 您还可以使用none值完全禁用Spring boot的日志记录配置。
由于日志是在应用程序applicationContext上下文创建之前初始化的,所以不可能在Spring @configuration注解文件中控制来自@propertySource的日志记录。系统属性和常规的Spring boot外部配置文件已经工作得很好。
根据不同的日志系统,你可以按如下规则组织配置文件名,就能被正确加载:
- Logback:
logback-spring.xml
,logback-spring.groovy
,logback.xml
,logback.groovy
- Log4j2:
log4j2-spring.xml
,log4j2.xml
- JDK (Java Util Logging):
logging.properties
在可能的情况下,我们建议您使用-spring变体来进行日志配置( 如使用logback-spring.xml
,而不是logback.xml
)。如果使用标准配置logback.xml
,Spring无法完全控制日志初始化。 Spring boot包含许多对Logback的扩展,可以帮助高级配置,您可以在您的logback-spring.xml文件中使用这些扩展。在标准配置logback.xml中不能使用这些扩展因为它太早被加载,当然如果一定要使用,需定义一个 logging.config
属性。
注:这些扩展不能与Logback的配置扫描一起使用。如果您尝试这样做,对配置文件进行更改将导致类似于以下日志记录之一的错误:
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]] ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]
3 logback日志介绍与配置
3.1 logback介绍
Logback是由log4j创始人设计的又一个开源日志组件。logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个 改良版本。此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。logback-access访问模块与Servlet容器集成提供通过Http来访问日志的功能。 Logback是要与SLF4J结合起来用两个组件的官方网站如下:
logback的官方网站: http://logback.qos.ch
SLF4J的官方网站:http://www.slf4j.org
3.2 logback取代log4j的理由
Logback和log4j是非常相似的,如果你对log4j很熟悉,那对logback很快就会得心应手。下面列了logback相对于log4j的一些优点:
- 更快的实现 Logback的内核重写,在一些关键执行路径上性能提升10倍以上。而且logback不仅性能提升,初始化内存加载也更小。
- 非常充分的测试 Logback经过了几年,数不清小时的测试,Logback的测试完全不同级别的。在作者的观点,这是简单重要的原因选择logback而不是log4j。
- Logback-classic非常自然实现了SLF4j 因为logback-classic非常自然地实现了SLF4J, 所 以切换到log4j或者其他,非常容易,只需要提供成另一个jar包就OK,根本不需要去动那些通过SLF4JAPI实现的代码。
- 非常充分的文档 官方网站有两百多页的文档。
- 自动重新加载配置文件 当配置文件修改,Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。
- Lilith Lilith是log事件的观察者,和log4j的chainsaw类似。而lilith还能处理大数量的log数据 。
- 谨慎的模式和非常友好的恢复 在谨慎模式下,多个FileAppender实例跑在多个JVM下,能 够安全地写道同一个日志文件,RollingFileAppender会有些限制。Logback的FileAppender和它的子类包括 RollingFileAppender能够非常友好地从I/O异常中恢复。
- 配置文件可以处理不同的情况 开发人员经常需要判断不同的Logback配置文件在不同的环境下(开发,测试,生产)。
- Filters(过滤器) 有些时候,需要诊断一个问题,需要打出日志。在log4j,只有降低日志级别,不过这样会打出大量的日志,会影响应用性能。在Logback,你可以继续 保持那个日志级别而除掉某种特殊情况,如alice这个用户登录,她的日志将打在DEBUG级别而其他用户可以继续打在WARN级别。要实现这个功能只需 加4行XML配置。可以参考MDCFIlter 。
- SiftingAppender(一个非常多功能的Appender) 它可以用来分割日志文件根据任何一个给定的运行参数。如,SiftingAppender能够区别日志事件跟进用户的Session,然后每个用户会有一个日志文件。
- 自动压缩已经打出来的log RollingFileAppender在产生新文件的时候,会自动压缩已经打出来的日志文件。压缩是个异步过程,所以甚至对于大的日志文件,在压缩过程中应用不会受任何影响。
- 堆栈树带有包版本 Logback在打出堆栈树日志时,会带上包的数据。
- 自动去除旧的日志文件 通过设置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory属性,你可以控制已经产生日志文件的最大数量。
总之,logback比log4j优秀。
3.3 logback配置
Logback 配置文件的语法非常灵活。正因为灵活,所以无法用 DTD 或 XML schema 进行定义。尽管如此,可以这样描述配置文件的基本结构:以<configuration>开头,后面有零个或多个<appender>元素,有零个或多个<logger>元素,有最多一个<root>元素。
logback配置文件实例:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="/home" />
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--myibatis log configure-->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>