Spring Boot 中 Logback 和 Log4j2 的扩展

1、概览

日志是系统中的一个重要组件。Spring Boot 支持 LogbackLog4j2 日志框架,并且提供了一些扩展,可用于高级配置。

在本教程中,我将带你学习如何在 Spring Boot 中使用 Logback 和 Log4j2 的扩展进行高级的日志配置。

2、Logback 扩展

Spring Boot 默认使用 Logback 进行日志记录。在本节中,我们将了解 Logback 的一些扩展,以进行高级配置。

注意:Spring Boot 建议使用 logback-spring.xml 作为 Logback 的配置文件名称,而不是默认的 logback.xml。因为 logback.xml 配置文件会被 Logback 默认加载,它会比 Spring 更早地加载进系统,所以我们不能在标准的 logback.xml 中使用扩展,

2.1、Maven 依赖

要使用 Logback,我们需要在 pom.xml 中添加 logback-classic 依赖项。

spring-boot-starter-web 依赖已经包含了它,所以不需要额外导入 logback-classic

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2.2、基本日志

首先,在 Spring Boot main 类中输出一些示例日志:

@SpringBootApplication
public class SpringBootLogbackExtensionsApplication {

    private static final Logger logger = LoggerFactory.getLogger(SpringBootLogbackExtensionsApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(SpringBootLogbackExtensionsApplication.class, args);

        logger.debug("Debug log message");
        logger.info("Info log message");
        logger.error("Error log message");
        logger.warn("Warn log message");
        logger.trace("Trace log message");
    }
}

2.3、Profile 设置

Spring profile 提供了一种根据激活的 profile 调整应用配置的机制。

例如,我们可以为 “development” 和 “production” 等不同环境定义不同的 Logback 配置文件。如果我们只想使用一个 Logback 配置文件,那么可以在 logback-spring.xml 中使用 springProfile 元素。

使用 springProfile 元素,我们可以根据激活的 profile 选择性地包含或排除某些配置。通过 name 属性来指定当前节点下的配置在哪个 profile 被激活时生效。

默认情况下,Spring Boot 只把日志输出到控制台。现在,假设我们想在 “production” profile 下把日志输出到文件,而在 “development” profile 下输出到控制台。使用 springProfile 元素可以轻松实现。

创建 logback-spring.xml 文件:

<springProfile name="development">
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </layout>
    </appender>
    <root level="info">
        <appender-ref ref="Console" />
    </root>
</springProfile>

<springProfile name="production">
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS}/spring-boot-logger.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOGS}/archived/spring-boot-logger-%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
    </appender>
    <root level="info">
        <appender-ref ref="RollingFile" />
    </root>
</springProfile>

然后,我们可以使用 JVM 系统参数 -Dspring.profiles.active=development-Dspring.profiles.active=production 来设置激活的 profile。

现在,如果我们在 development profile 下运行 Spring Boot 应用程序,控制台中将显示以下日志输出:

10:31:13.766 [main] INFO  c.b.e.SpringBootLogbackExtensionsApplication - Info log message
10:31:13.766 [main] ERROR c.b.e.SpringBootLogbackExtensionsApplication - Error log message
10:31:13.766 [main] WARN  c.b.e.SpringBootLogbackExtensionsApplication - Warn log message

name 属性还支持表达式,用于描述更复杂的 profile 逻辑。例如,我们希望在 “staging” profile 或 “production” profile 任意被激活时包含一些配置,那么可以使用 | 表达式:

<springProfile name="production | staging">
    <!-- configuration -->
</springProfile>

上述配置在 “production” profile 或 “production” profile 处于激活状态时启用。

2.4、读取 Environment Properties

有时,我们需要在日志配置中访问 application.properties 中的属性值。在这种情况下,我们使用 Logback 配置中的 springProperty 元素。

SpringProperty 元素与 Logback 标准的 property 元素类似。不过,它具有一个 source 属性,该属性值来自 application properties。如果环境中没有设置该属性,它将从 defaultValue 属性中获取默认值。此外,我们需要为 name 属性设置一个值,以便在配置中的其他元素中引用该属性。

最后,我们可以设置 scope 属性值为 context。scope 为 context 的属性是 context 的一部分,可以在所有日志事件中使用。

假设我们想使用 application name 作为日志文件名。首先,我们在 application.properties 文件中定义 application name:

spring.application.name=logback-extension

然后,我们在 logback-spring.xml 中公开 application name:

<property name="LOGS" value="./logs" />
<springProperty scope="context" name="application.name" source="spring.application.name" />
<springProfile name="production">
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS}/${application.name}.log</file>
        <!-- configuration -->
    </appender>
</springProfile>

在上述配置中,我们将 springProperty 元素的 source 属性设置为 spring.application.name 属性。此外,我们还使用 ${application.name} 来引用该属性。

下一节,我们将讨论 Spring Boot 应用中 Log4j2 的扩展。

3、Log4j2 扩展

Log4j2 扩展与 Logback 扩展类似。我们不能在标准的 log4j2.xml 配置文件中使用扩展,因为它会被 Log4j2 提前加载。

Spring Boot 推荐的方法是将 Log4j2 配置存储在名为 log4j2-spring.xml 的单独文件中。如果存在其他 Log4j2 配置,Spring Boot 将在加载该配置之前加载它。

3.1、Maven 依赖

要使用 Log4j2 库而不是默认的 Logback,我们需要将 Logback 从 starter 依赖中排除:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

此外,我们还需要在 pom.xml 文件中添加 spring-boot-starter-log4j2log4j-spring-boot 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-spring-boot</artifactId>
</dependency>

我们在应用中加入了 log4j-spring-boot 库,以便在 Log4j2 设置中支持 Spring Boot profile。如果没有这个依赖,我们将看到以下 ERROR 信息:

2023-01-21 15:56:12,473 main ERROR Error processing element SpringProfile ([Loggers: null]): CLASS_NOT_FOUND

3.2、Profile 设置

与 Logback 类似,我们可以使用 SpringProfile 元素来为不同的 Profile 定义配置。

log4j2-spring.xml

<SpringProfile name="development">
    <Logger name="com.baeldung.extensions" level="debug"></Logger>
</SpringProfile>

<SpringProfile name="production">
    <Logger name="com.baeldung.extensions" level="error"></Logger>
</SpringProfile>

如上配置,如果我们激活 production Profile 运行应用,你就只能看到 com.baeldung.extensions 包中 ERROR 级别的日志。

2023-01-22T11:19:52,885 ERROR [main] c.b.e.SpringBootLog4j2ExtensionsApplication: Error log message
2023-01-22T11:19:52,885 FATAL [main] c.b.e.SpringBootLog4j2ExtensionsApplication: Fatal log message

<SpringProfile> 支持配置在 <configuration> 元素内的任何地方。

3.3、Environment Properties 查询

Log4j2 Lookup 提供了一种在配置文件中,读取应用配置值的方式。

我们可以使用 Log4j2 的 Lookup 功能从 application.properties 文件中获取值,并在 Log4j2 配置中使用它们。此外,我们还可以使用激活和默认 Profile 的值。为了实现这一点,在 Log4j2 配置中,我们可以使用以 spring 为前缀的 Lookup。

让我们在 application.properties 文件中设置 spring.application.name=log4j2-extension。然后,我们从 Spring Environment 中读取 spring.application.name 的值:

<Console name="Console-Extensions" target="SYSTEM_OUT">
    <PatternLayout
        pattern="%d %p %c{1.} [%t] ${spring:spring.application.name} %m%n" />
</Console>

在上述配置中,我们使用 spring 前缀查找设置了 spring.application.name。运行后,应用将在控制台输出以下日志信息:

2023-01-22 16:17:30,301 ERROR c.b.e.SpringBootLog4j2ExtensionsApplication [main] log4j2-extension Error log message
2023-01-22 16:17:30,301 FATAL c.b.e.SpringBootLog4j2ExtensionsApplication [main] log4j2-extension Fatal log message

3.4、Log4j2 System Properties

Log4j2 提供了多个 System Properties,可用于配置各个方面。我们可以将这些配置添加到 log4j2.system.properties 文件中。

例如,添加 log4j2.debug=true 属性。此时 log4j2 会将所有内部日志也打印到控制台:

TRACE StatusLogger Log4jLoggerFactory.getContext() found anchor class java.util.logging.Logger

我们也可以在 application.properties 文件中添加这些 System Properties,但是 log4j2.system.properties 文件中定义的属性优先级高于 application.properties 文件。

4、总结

Spring Boot 提供广泛的日志支持。在本教程中,我们学习了如何在 Spring Boot 中使用 Logback 和 Log4j2 的扩展进行高级的日志配置。


参考:https://www.baeldung.com/spring-boot-logback-log4j2