在 Spring Boot 中使用 Logback 和 Log4j2 记录日志

日志系统对应用程序的重要性不言而喻。Spring Boot 为应用程序的日志记录提供了强大的支持,并提供了各种自定义选项。在本教程中,你将学习如何在 Spring Boot 应用程序中使用 LogbackLog4j2 实现日志记录

Spring Boot 中默认的的日志支持

当你创建一个添加了任何 starter 的 Spring Boot 应用程序时,它们都依赖于 spring-boot-starter,而 spring-boot-starter 又依赖于 spring-boot-starter-logging,这就为日志记录添加了 logback 依赖。

Spring Boot 默认日志配置已在 spring-boot-starter 中通过 CONSOLE appender 进行了配置。你可以在 org/springframework/boot/logging/logback 包下查看打包在 spring-boot.jar 中的默认配置文件(defaults.xmlbase.xmlconsole-appender.xmlfile-appender.xml)。

因此,默认情况下,Spring Boot 配置了 Slf4j 和 Logback 来记录日志,你可以在应用程序中按如下方式记录日志:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
class CustomerService {
    private static final Logger log = LoggerFactory.getLogger(CustomerService.class);
    
    public Customer findById(Long id) {
        log.info("Fetching customer by id: {}", id);
        ...
    }
}

这将在你的 CONSOLE 中产生一个 INFO 级别的日志,类似于下面的内容:

2023-07-26T19:44:04.492+05:30  INFO 69881 --- [nio-8080-exec-1] c.s.demo.CustomerService      : Fetching customer by id: : 1

自定义日志级别

默认情况下,Spring Boot 的 root 日志级别设置为 INFO。你可以在 src/main/resources/application.properties 中为 root 或任何指定的包配置日志级别,如下所示:

logging.level.root=WARN
logging.level.com.sivalabs=DEBUG
logging.level.org.springframework=INFO
logging.level.org.hibernate.validator=DEBUG

使用 File Appender

Spring Boot 已经配置了 RollingFileAppender,但默认是禁用的。只需在 application.properties 中配置 logging.file.namelogging.file.path 属性,即可启用 File Appender,具体如下:

# 相对于当前目录
logging.file.name=product-service.log

# 绝对路径
logging.file.name=/var/log/product-service.log

# 把日志写入到 /var/log/product-service/spring.log 文件
logging.file.path=/var/log/product-service

请注意,当你配置 logging.file.namelogging.file.path 属性时,将同时启用 ConsoleFile Appender。如果你想禁用 Console appender 并仅启用 File appender,或者你想对 logback 配置进行更多控制,你可以创建 src/main/resources/logback.xml 文件,并根据你的需求进行日志配置。

自定义 Logback 配置

如果通过 logging.* 属性进行的 Spring Boot 日志配置不能满足需求,那可以创建自己的 src/main/resources/logback.xml 文件,Spring Boot 将根据此配置来配置日志。

不过,Spring Boot 提供了一些 logback 扩展,可帮助你使用高级配置选项。为了使用这些扩展,需要创建名为 logback-spring.xml 而非 logback.xml 的配置文件。

logback-spring.xml 文件示例如下:

<?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="FILE" />
    </root>
    <logger name="org.springframework" level="WARN"/>
    <logger name="com.sivalabs" level="DEBUG"/>

</configuration>

如果你想在配置中读取 Spring Boot properties 或根据 Spring profile 定义日志配置,Spring Boot Logback 扩展就会派上用场。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <springProperty scope="context" 
                    name="logstashHost" 
                    source="logstash.host"
                    defaultValue="localhost"/>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />

    <springProfile name="docker">
        <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
        <property name="LOG_FILE" value="/var/logs/myapp.log"/>

        <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
            <destination>${logstashHost}</destination>
            ...
            ...
        </appender>
        
        <root level="INFO">
            <appender-ref ref="FILE" />
            <appender-ref ref="logstash" />
        </root>
    </springProfile>
    
    <springProfile name="!docker">
        <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
        </root>
    </springProfile>
    
    <logger name="com.sivalabs" level="DEBUG"/>
    <logger name="org.springframework" level="INFO"/>

</configuration>

在上述配置中,我们根据 Spring profile 启用 appender。如果启用了 docker profile,则使用 FILELogstash appender。反之,则仅使用 CONSOLE appender。此外,请注意我们通过定义 <springProperty .../> 来获取到 logstash.host 属性值,来指定 Logstash 主机。

使用 Log4j2 代替 Logback

如果你更喜欢使用 Log4j2 而不是 Logback,可以从 spring-boot-starter 中排除 spring-boot-starter-logging,并在 pom.xml 中添加 spring-boot-starter-log4j2 依赖,如下所示。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <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>

如果使用的是 Gradle,可以按如下方式配置使用 log4j2 而不是 logback:

configurations.all {
    exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-log4j2')
    ...
    ...
}

Spring Boot 默认在 org/springframework/boot/logging/log4j2/log4j2.xml 中包含 log4j2.xml 配置文件。但如果你想提供自定义配置,则可以创建 src/main/resources/log4j2-spring.xml 文件,如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Properties>
        <Property name="LOG_PATTERN">
            %d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %c{1}:%L - %m%n
        </Property>
    </Properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT" follow="true">
            <PatternLayout pattern="${LOG_PATTERN}"/>
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="com.sivalabs" level="debug" additivity="false">
            <AppenderRef ref="Console" />
        </Logger>

        <Root level="info">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

如果使用 slf4j API 创建 logger 对象,则无需修改任何代码。slf4j API 会将实际日志记录委托给 log4j2。

总结

Spring Boot 通过提供默认的配置(可自定义),使实现日志记录变得简单。在本教程中,我们学习了如何在 Spring Boot 中使用 Slf4J 和 Logback 记录日志,以及自定义日志配置。然后,我们探讨了如何使用 Log4j2 替代默认的 Logback 实现。


参考:https://www.sivalabs.in/spring-boot-logging-tutorial/