Spring Boot的日志管理

Spring Boot的日志管理,第1张

环境
  • *** 作系统:Ubuntu 20.04
  • 开发工具:IntelliJ IDEA 2022.1 (Community Edition)
  • JDK:17.0.1
准备工作

在 https://start.spring.io/ 创建项目 test0509_2 ,添加 Spring Web 依赖。

创建package controller ,并创建class HelloController 如下:

package com.example.test0509_2.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
public class HelloController {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @GetMapping("/test")
    public Map<String, String> test() {
        logger.trace("trace");
        logger.debug("debug");
        logger.info("info");
        logger.warn("warn");
        logger.error("error");

        return Map.of("key1", "value1");
    }
}

运行程序,然后打开浏览器,访问 http://localhost:8080/test ,最后查看命令行,结果如下:

2022-05-10 20:19:38.506  INFO 76371 --- [nio-8080-exec-3] c.e.t.controller.HelloController         : info
2022-05-10 20:19:38.507  WARN 76371 --- [nio-8080-exec-3] c.e.t.controller.HelloController         : warn
2022-05-10 20:19:38.508 ERROR 76371 --- [nio-8080-exec-3] c.e.t.controller.HelloController         : error

可见,默认的log级别是 INFO

Spring Boot默认使用 SLF4J + Logback 的组合:

  • SLF4J :log的门面(抽象);
  • Logback :log的实现;

项目的依赖关系如下:


可见, spring-boot-starter 包依赖于 spring-boot-starter-logging 包,所以我们可以在Spring Boot项目里直接使用log。而 spring-boot-starter-logging 包又依赖于 logbacklog4jjul (即Java Util Logging,JDK自带的log功能)这三个包,这是log的三种实现,Spring默认使用的是 Logback

设置Spring Boot的log级别

要设置整个Spring Boot应用的log级别,可以给应用程序添加命令行参数,或者通过配置文件来设置。比如,添加命令行参数 --trace (或者在 application.properties 文件中添加 trace=true ):


运行程序,可见命令行输出了很多 TRACEDEBUG 的log。

同理,也可以设置成 DEBUG 级别。

注意:当启用trace或者debug模式时,Spring Boot的核心log为 TRACE 或者 DEBUG 级别,但是应用程序的log级别并不受影响。刷新浏览器页面,命令行的输出仍然是 INFO 级别的log。

测试完毕,别忘了还原设置,以免影响到下面的测试。

设置应用程序的log级别

打开 application.properties 文件,添加内容如下:

logging.level.root=WARN

再次运行程序,刷新浏览器页面,可见命令行只有 WARNERROR 的log。

注意:该配置也会影响Spring Boot的核心log,Spring Boot启动时的 INFO log都不见了。

上面设置了应用程序整体的log级别,事实上也可以设置特定包或者类的log级别,如下:

# root log level
logging.level.root=WARN

# package(包含子) log level
logging.level.=WARN

# class log level
logging.level.<class全名>=WARN

......

测试完毕,别忘了还原设置,以免影响到下面的测试。

配置log格式
  • logging.pattern.console
  • logging.pattern.file

注意:只有使用Logback时才有效。

输出log到文件

可通过如下配置:

  • logging.file.name :文件名
  • logging.file.path :文件目录

注意:

  • 如果只指定 path ,不指定 name ,则默认文件名为 spring.log
  • 如果只指定 name ,不指定 path ,则在当前目录下生成log文件;

注:参见上面图片中的 Working directory 设置,当前目录是项目的根目录。

例如:

logging.file.path=.
logging.file.name=mylog.log

当使用 Logback 时,可配置如下参数:

  • logging.logback.rollingpolicy.max-file-size :设置文件大小,默认为10MB;
  • logging.logback.rollingpolicy.max-history :设置保留天数,默认为7天;
  • ……

对于其它log实现,则需要修改对应的配置文件,比如 Log4j ,就需要修改 log4j.xml / log4j-spring.xml 文件进行配置。

运行程序,可见当前目录(即项目的根目录)里面的 mylog.log 文件生效了,同时命令行log仍然生效。

Log group

配置 logging.group ,把多个package和class放到一个group里统一设置级别,方便管理。例如:

logging.group.=xxx,xxx,......
logging.level.=trace
显式指定log实现(关闭log)

Spring Boot默认使用Logback作为log实现。可以通过系统属性 org.springframework.boot.logging.LoggingSystem 显式指定log实现。其值可以是 LoggingSystem 实现类的全名,也可以指定为 none ,关闭log。

我们来尝试关闭log。 Run -> Edit Configurations... ,在 VM options 处,添加 -Dorg.springframework.boot.logging.LoggingSystem=none ,如下图:


注意:默认并没有显示 VM options 编辑框,需要点击 Modify options ,然后勾选 Add VM Options

注意: VM options 即系统属性(System Property),可以理解为JVM的环境变量,通过 -D= 来设置。

运行程序,我测试的效果为:

  • 文件log确实关闭了(Spring Boot核心log和应用程序log都关闭了);
  • 命令行log不但没有关闭,反而级别变成了 DEBUG (Spring Boot核心log和应用程序log都变成 DEBUG 级别了);

用命令行运行 java -jar -Dorg.springframework.boot.logging.LoggingSystem=none ./target/test0509_2-0.0.1-SNAPSHOT.jar 也是同样效果。

注:为何要通过系统属性,而不能通过 application.properties 文件来配置 org.springframework.boot.logging.LoggingSystem 呢?Spring Boot的官方文档(https://docs.spring.io/spring-boot/docs/2.6.7/reference/htmlsingle/#features.logging.custom-log-configuration)如是说:

Logging在ApplicationContext创建之前就初始化了,因此无法通过Spring的 @Configuration 文件的 @PropertySources 来控制logging。改变或者关闭logging system的唯一方法是通过系统属性。

我测试过,如果清空 VM options ,同时把 org.springframework.boot.logging.LoggingSystem=none 添加到 application.properties 文件里,确实命令行log和文件log都不生效。

Log实现的配置文件

前面的测试都没有涉及log实现的配置文件。事实上Logback,Log4j2等log实现,也支持配置文件。Spring Boot默认从类加载路径的根路径下加载log配置文件。Spring Boot自动识别并加载的配置文件如下:

  • Logback: logback-spring.xmllogback.xml
  • Log4j2: log4j2-spring.xmllog4j2.xml
  • JUL: logging.properties

注:Spring Boot推荐使用带 -spring 后缀的配置文件。

可以通过 logging.config 系统属性来指定log配置文件。

比如,我们创建 logback-spring.xml 文件,内容如下:


<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>

注: :- 是Logback语法,用来作为属性名和默认值之间的分隔符。本例中 LOG_FILE 的设置,我没仔细研究其作用。看起来貌似并不影响log:如果 application.properties 里设置了 logging.file.name ,就会用指定的命名,否则就用默认值 spring.log 命名。

注意,配置文件指定了log级别为 INFO ,且只用文件log(没有命令行log)。至于Log文件的路径和命名,在 application.properties 文件中指定(参见上面的配置)。

logback-spring.xml 文件复制到任意目录,比如项目的根目录下。

由于该文件不在类加载路径的根路径下,我们需要显式告诉Spring Boot来加载它。指定 VM options-Dlogging.config=logback-spring.xml 。运行程序,项目的根目录(即当前目录)里面的 logback-spring.xml 配置文件就会生效。该配置文件配置了log级别为 INFO ,且只用文件log。

可以看到,命令行确实没有输出了,同时项目的根目录(即当前目录)里面的 mylog.log 文件生效了。

同样的问题:能否不使用系统属性,而使用 application.properties 文件来配置呢?我测试过,如果清空 VM options ,同时把 logging.config=logback-spring.xml 添加到 application.properties 文件里,它仍然生效:命令行log没有了,同时 mylog.log 文件生效了。

Spring Boot属性 VS. 系统属性

具体对应关系,参见Spring官网: https://docs.spring.io/spring-boot/docs/2.6.7/reference/htmlsingle/#features.logging.custom-log-configuration

隐式指定log实现

前面提到,可以通过系统属性 org.springframework.boot.logging.LoggingSystem 来显式指定log实现。如果不指定,则Spring Boot默认会根据依赖关系,自动选取log实现。

在本文开头的项目依赖关系图里,我们看到 spring-boot-starter-logging 包依赖于 logbacklog4jjul ,即log的三种实现,其中 Logback 优先级较高,所以Spring默认使用的是 Logback

下面我们来尝试通过改变依赖关系来指定log实现。修改 pom.xml 文件,在 spring-boot-starter 下添加 exclusion ,排除对 spring-boot-starter-logging 的依赖,同时添加对 spring-boot-starter-log4j2 的依赖,如下:

		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starterartifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.bootgroupId>
					<artifactId>spring-boot-starter-loggingartifactId>
				exclusion>
			exclusions>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-log4j2artifactId>
		dependency>

注:添加对 spring-boot-starter-log4j2 的依赖,就会自动传递对 SLF4J 的依赖。

刷新Maven依赖关系,如下图:


可见已经没有对 Logback 的依赖了。

Maven -> Compile ,重新编译项目,然后去掉所有logging相关的配置,只保留 application.properties 文件里的log文件配置:

logging.file.path=.
logging.file.name=mylog.log

运行程序,可见和Logback的log并没什么区别,在命令行和 mylog.log 文件都输出了 INFO 级别的log。

可以在debug模式下设置断点观察Logger:


可见这是 Log4jLogger

补一张之前使用 Logback 时的图:

可见这是Logback的Logger。

注意:如果使用了其它log实现,就不要再指定跟Logback相关的配置,否则会有问题。比如,在 application.properties 文件中添加如下配置:

logging.config=logback-spring.xml

运行程序,则命令行只有 ERROR 级别的log,而文件log无效了。不知道为啥,但总之,如果使用某种log实现,就不要再指定其它log实现的配置了,以免产生不必要的问题。

参考
  • https://docs.spring.io/spring-boot/docs/2.6.7/reference/htmlsingle/

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/917793.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存