本文属于原创,转载注明出处,欢迎关注微信小程序 小白AI博客 微信公众号 小白AI 或者网站 https://xiaobaiai.net
[TOC]
本篇文章主要对Spring Boot的日志记录进行详细讲解,包括流行的开源日志标准接口以及流行的日志记录器在Spring Boot中是如何配置及应用的,以及在生产环境中,我们所需要的配置是否都能够满足?
相关背景知识我们还是需要了解的,有助于对正文内容的理解。
| 名词术语 | 释义 |
|---|---|
| Apache Common Logging | Apache下开源项目,commons-logging的目的是为“所有的Java日志实现”提供一个统一的接口,使项目与日志实现工具解耦;commons-logging和log4j都是Apache下的开源项目。commons-logging的目的是为“所有的Java日志实现”提供一个统一的接口,使项目与日志实现工具解耦,它自身的日志功能比较弱(只有一个简单的 SimpleLog),所以一般不会单独使用它。 |
| Log4j / Log4j 2 | Apache下的开源项目,Log4j的功能非常强大,是目前最主流的java日志工具。Log4j 2.0 引入了新的插件系统、对 properties 的支持、对基于 JSON 配置的支持和配置的自动化重载。相比之前Log4j 的1.x 版本有了很大的性能提升。它支持很多已有的日志框架,包括 SLF4J、Commons Logging、Apache Flum、Log4j 1.x,并提供了新的程序员 API。 |
| Java Util Logging | Java 的原生日志记录基础组件 |
| Logback | 是一个日志框架,旨在取代Log4j,Log4j的改良版本,比Log4j拥有更多的特性,同时也带来很大性能提升。不过性能上没有Log4j 2好。 |
| SLF4J | 跟Apache Common Logging一样,也是一套接口,现在流行的日志框架和接口组合就是Commons Logging加Log4j 、SLF4J加Logback、slf4j + log4j2 |
| Mockito | Mockito是一个通用的模拟框架,可用于单元测试,尤其是考虑到依赖注入而设计的类。Mockito也可以用来测试Spring Controller,但不是针对性的支持。 |
| MockMVC | MockMVC是Spring框架的配套产品,有助于测试Spring Controllers。MockMVC更加具体,与Mockito相比,通用性可能要差得多,不过对于测试Spring MVC 中Restful API是比较好的。 |
Spring Boot 使用 Apache Commons Logging 接口记录所有内部日志记录。 Spring Boot 的默认配置对 Java Util Logging , Log4j2 和 Logback 日志记录器的使用都提供了支持。如果你使用的是 Spring Boot Starters ,默认使用的 Logback 就为日志记录提供很好的支持。 下面我们分几部分对如何做日志记录以及配置不同的日志记录器做说明,在 Spring Boot 中只需要通过一些简单的配置即可支持各种日志记录。
默认启动日志记录是由 spring-boot-starter-logging 依赖项决定的,并且它是自动配置的,该自动配置可根据提供的配置启用任何受支持的日志记录器(Java Util Logging,Log4J2和Logback),虽然我们不提供任何日志相关的配置,但是我们仍然能够在控制台上看到日志打印,这是因为 Spring boot 使用了 Logback 提供了默认的日志记录支持。但是我们上一篇文章里为啥没有看到 pom.xml 文件里有导入 spring-boot-starter-logging 这个依赖项呢?
Spring Boot 的内部日志记录是使用 Apache Commons Logging 接口编写的,因此它是唯一的强制性依赖项。在 Spring boot1.x 的时候我们还需要手动导入,但是到了 Spring boot2.x ,它是间接导入的,即我们依赖了 spring-boot-starter-web 这个依赖项时,它就依赖了 spring-boot-starter-logging ,这个时候就导入了日志记录功能。从 STS 的pom.xml文件依赖展开就可以看到:
因此, Spring boot 自动配置提供使用 Logback 的默认日志记录,并且这些配置文件中提供了默认日志记录的参数配置。从 Spring Boot 的日志记录源码就可以看到( https://github.com/spring-pro... ) 。
在应用程序代码中添加日志记录语句,我们使用 SLF4J 接口中的 org.slf4j.Logger 和 org.slf4j.LoggerFactory 。它提供了许多有用的日志记录方法,也使日志记录实现与应用程序相分离。
注意:日志接口是很多,这里我们选择了SLF4J API。还有apache.logging/java.util.logging等
// 使用Log4j2则使用apache logging接口
// import org.apache.logging.log4j.LogManager;
// import org.apache.logging.log4j.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application
{
private static final Logger LOGGER=LoggerFactory.getLogger(Test02HelloworldApplication.class);
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
LOGGER.info("简单的日志记录测试 : {} + {} = {}", 1, 2, 3);
}
}
控制台打印如下:
2019-10-29 21:37:39.818 INFO 16244 --- [ main] c.xiaobaiai.Test02HelloworldApplication : 简单的日志记录测试 : 1 + 2 = 3
Logback 支持设置 ERROR , WARN , INFO , DEBUG 、 TRACE 或 OFF 作为日志记录级别,按日志抑制优先级从高到低。默认情况下,日志记录级别设置为 INFO 。这意味着 DEBUG 和 TRACE 消息不可见。
要启用 DEBUG 或 TRACE 日志记录级别,我们可以在 application.properties 文件中设置日志记录级别。另外,我们也可以在启动应用程序时在命令行上传递 --debug 或 --trace 参数。
# In application.properties file # 方法一: 该属性置为true的时候,核心Logger(包含嵌入式容器、hibernate、spring)会输出更多内容,但是你自己应用的日志并不会输出DEBUG级别的日志 debug=true # 方法二:将日志记录级别应用于特定的软件包。 logging.level.com.xiaobaiai=DEBUG logging.level.org.springframework=ERROR logging.level.root=DEBUG # In Console $ java -jar target/xx-app-0.0.1-SNAPSHOT.jar --trace
注意: 如果使用不同的日志级别多次定义了软件包的日志级别,则将使用最低级别。TRACE最低,ERROR最高。
默认的日志记录格式在 Spring Boot 日志记录器 Logback 源码文件 default.xml 中可以看到:
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-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}}"/>
<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
日志最后输出如下信息:
---
要定义日志最后的输出格式,使用 logging.pattern.console 和 logging.pattern.file 属性。
# Logging pattern for the console
# 不支持JDK Logger
logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} - %logger{36} - %msg%n
# Logging pattern for file
# 不支持JDK Logger
logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%
默认情况下, Spring boot 日志仅记录到控制台。如果要启用文件日志记录,则可以使用简单的属性 logging.file 或 logging.path 轻松实现。
# 输出到指定路径,默认文件名为spring.log
logging.file.path=C://Work//sts4//test_02_helloworld//logs
# 文件名设置,使用了该项配置,则会覆盖path设置,直接在工程当前目录下生成日志
logging.file.name=logfilename.log
# 路径与文件名结合(该配置项已被遗弃)
logging.file=${logging.file.path}/log.log
# 输出到文件最大内容限制大小,达到最大后,会截断
# 默认是10M,而且该设置项只对默认的Logback有效,单位GB/MB/KB等
logging.file.max-size = 10MB
如果你的终端支持ANSI,设置彩色输出会让日志更具可读性。通过在 application.properties 中设置 spring.output.ansi.enabled 参数来支持。
# NEVER:禁用ANSI-colored输出(默认项) # DETECT:会检查终端是否支持ANSI,是的话就采用彩色输出(推荐项) # ALWAYS:总是使用ANSI-colored格式输出,若终端不支持的时候,会有很多干扰信息,不推荐使用 spring.output.ansi.enabled=DETECT
根据不同的日志系统,你可以按如下规则组织配置文件名,就能被正确加载:
Logback : logback-spring.xml , logback-spring.groovy , logback.xml , logback.groovy , logback-spring-xxx.xml Log4j : log4j-spring.properties , log4j-spring.xml , log4j.properties , log4j.xml Log4j2 : log4j2-spring.xml , log4j2.xml JDK (Java Util Logging) : logging.properties Spring Boot官方推荐优先使用带有 -spring 的文件名作为你的日志配置(如使用 logback-spring.xml ,而不是 logback.xml ),命名为 logback-spring.xml 的日志配置文件,Spring boot可以为它添加一些 Spring boot 特有的配置项。
上面是默认的命名规则,并且放在 src/main/resources 下面即可。
如果你即想完全掌控日志配置,但又不想用 logback.xml 作为Logback配置的名字,可以在 application.properties 配置文件里面通过 logging.config 属性指定自定义的名字:
logging.config=classpath:logging-config.xml
这里简单讲述 Logback 的一个自定义配置,具体的可以参见官方文档 http://logback.qos.ch/manual/configuration.html
配置文件主要实现的功能有:
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
当scan为true时,此属性生效。默认的时间间隔为1分钟。 debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="60 seconds"
debug="false">
<!-- 每个logger都关联到logger上下文,默认上下文名称为“default”。 但可以使用contextName标签设置成其他名字,用于区分不同应用程序的记录,如打印日志如下中xiaobaiai
10:39:28.964 xiaobaiai [main] DEBUG c.x.Test02HelloworldApplication - 简单的日志记录测试
: 1 + 2 = 3 -->
<contextName>xiaobaiai</contextName>
<!-- property用来定义变量值的标签,property标签有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值
这里定义了log.path这个变量,下面会有引用这个变量 -->
<property name="log.path"
value="/Users/Ethanm/Documents/spring-log" />
<!--输出到控制台 -->
<appender name="console"
class="ch.qos.logback.core.ConsoleAppender">
<!-- 定义过滤器,ERROR级别 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n</pattern>
</encoder>
</appender>
<!--输出到文件 -->
<appender name="file"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 最新的log文件 -->
<file>${log.path}/log_newest.log</file>
<encoder>
<!-- %d-以SimpleDateFormat允许的格式输出日志消息发生的时间 %thread-输出发生日志消息的线程的名称。 $-5level-输出日志消息的日志记录级别。
%logger{36}-输出发生日志消息的包+类名。括号内的数字表示包+类名的最大长度。 %M-输出发生日志消息的方法的名称(性能较差,不建议生成环境使用)
%msg-输出实际的日志消息 %magenta()-将括号中包含的输出的颜色设置为洋红色(其他颜色可用)。 %highlight()-将括号中包含的输出颜色设置为取决于日志记录级别(例如ERROR
= red) -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n</pattern>
</encoder>
<!-- 日志文件分割设置 -->
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>
${log.path}/log_%d{yyyy-MM-dd}_%i.log
</fileNamePattern>
<maxFileSize>3KB</maxFileSize>
<!-- 只保存最近10天日志 -->
<maxHistory>10</maxHistory>
<!-- 定义日志文件上限,如果所有日志超过这个大小,则会删除旧的日志 -->
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- root是根logger,不能有name和additivity属性,是有一个level -->
<!-- appender是一个日志打印的组件,这里组件里面定义了打印过滤的条件、打印输出方式、滚动策略、编码方式、打印格式等 如果我们不使用一个logger或者root的appender-ref指定某个具体的appender时,它就不会生效 -->
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<!-- logger标记用来设置某一个包或者具体的某一个类的日志打印级别以及指定appender -->
<logger name="com.xiaobaiai" level="WARN" additivity="false">
<appender-ref ref="console" />
</logger>
</configuration>
默认日志记录使用了 Logback ,首先我们需要在 pom.xml 中去掉 Logback ,引入 Log4j2 。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- 用exclusion排除掉默认日志记录器Logback -->
<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>
与 Logback 类似,在资源文件夹下(resources)添加如下形式的配置文件,都可以被扫描到:
配置文件设置与 Logback 大同小异:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
<Properties>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} %p %m%n</Property>
<Property name="APP_LOG_ROOT">c:/temp</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}" />
</Console>
<RollingFile name="file"
fileName="${APP_LOG_ROOT}/SpringBoot2App/application.log"
filePattern="${APP_LOG_ROOT}/SpringBoot2App/application-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${LOG_PATTERN}" />
<Policies>
<SizeBasedTriggeringPolicy size="19500KB" />
</Policies>
<DefaultRolloverStrategy max="1" />
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="console" />
<AppenderRef ref="file" />
</Root>
</Loggers>
</Configuration>
这里就不展开了,到了实际使用的时候,再来详细了解。
#tomcat server.tomcat.basedir=C:/temp/logs server.tomcat.accesslog.enabled=true server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms) logging.level.org.apache.tomcat=DEBUG logging.level.org.apache.catalina=DEBUG #undertow server.undertow.accesslog.directory=C:/temp/logs server.undertow.accesslog.enabled=true server.undertow.accesslog.pattern=%t %a "%r" %s (%D ms) logging.level.io.undertow.server=DEBUG logging.level.io.undertow.websockets=DEBUG #jetty server.jetty.accesslog.filename=/var/log/jetty-access.log server.jetty.accesslog.enabled=true logging.level.org.eclipse.jetty=INFO logging.level.org.eclipse.jetty.websocket=DEBUG
本篇文章让我们对主流的日志接口 Apache common logging 和 SLF4J 有了个了解, Logback 是 Spring boot 中默认配置的日志记录器,我们对如何在 application.properties 中配置日志相关配置做了详细说明,并对如何自定义 Logback 配置也作出了详细说明,最后介绍了如何切换日志记录器到 Log4j2 以及如何配置 Log4j2 给出了示例。扩展部分对内嵌WEB服务器的日志配置也给出了个简单的示例。总之,我们对 Spring boot 的日志这一块应该不会再陌生了。
本文属于原创,转载注明出处,欢迎关注CSDN freeape 或微信小程序 小白AI博客 微信公众号 小白AI 或者网站 https://xiaobaiai.net