翻译自:https://springframework.guru/using-logback-spring-boot/
USING LOGBACK WITH SPRING BOOT
Logback 为企业应用程序制作了一个优秀的日志框架-它的速度快, 具有简单但功能强大的配置选项, 而且内存占用小。在我的入门帖子中已经介绍了 logback ,logback 介绍: 企业日志框架。在 Logback 的一系列帖子中, 我还讨论了如何使用 XML 和 Groovy 配置 Logback。这些帖子可用作 Logback 配置: 使用 XML 和 Logback 配置: 使用 Groovy。
在这篇文章中, 我将讨论在Spring Boot中如何使用 Logback。虽然 Java 有许多日志框架选项, 但 Spring boot选择了使用 Logback 作为默认记录器。像Spring boot 里的许多东西一样, 默认情况下, Logback 会使用合理的默认值进行配置。开箱即用, Spring Boot 使 Logback 易于使用。
Creating Loggers
在上一个帖子中, 我写了有关使用 Spring boot创建 web 应用程序的内容。我们将为这个应用程序配置 logback。该应用程序包含一个控制器, 加日志代码到IndexController控制器。IndexController的最终代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 1package guru.springframework.controllers;
2
3import guru.springframework.helpers.SpringLoggingHelper;
4import org.slf4j.Logger;
5import org.slf4j.LoggerFactory;
6import org.springframework.stereotype.Controller;
7import org.springframework.web.bind.annotation.RequestMapping;
8
9@Controller
10public class IndexController {
11 private final Logger logger = LoggerFactory.getLogger(this.getClass());
12 @RequestMapping("/")
13 String index(){
14 logger.debug("This is a debug message");
15 logger.info("This is an info message");
16 logger.warn("This is a warn message");
17 logger.error("This is an error message");
18 new SpringLoggingHelper().helpMethod();
19 return "index";
20 }
21}
22
让我们为应用程序添加一个具有日志代码的 SpringLoggingHelper 类。尽管此类除了发出日志记录语句之外什么都不做, 但它将帮助我们了解如何在不同的包中配置日志记录。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 1package guru.springframework.helpers;
2
3
4import org.slf4j.Logger;
5import org.slf4j.LoggerFactory;
6
7public class SpringLoggingHelper {
8 private final Logger logger = LoggerFactory.getLogger(this.getClass());
9 public void helpMethod(){
10 logger.debug("This is a debug message");
11 logger.info("This is an info message");
12 logger.warn("This is a warn message");
13 logger.error("This is an error message");
14
15 }
16}
17
在上面的两个类中, 我们编写了针对 SLF4J API 的日志记录代码。SLF4J 是通常使用的日志框架的门面, 例如 Java .Util.Logging、Log4J 2 和 Logback。通过对SLF4J的编写,我们的代码仍然与Logback分离,从而为我们提供了在不同的日志框架中切换的灵活性,如果以后需要的话修改其他日志框架,是很方便的
如果您想知道 SLF4J 和 Logback 依赖关系的话, 这将不需要指定任何内容。Spring Boot也包含它们。假设您使用 Maven 或 Gradle 管理 spring boot项目, 则必要的依赖项是 spring boot下的依赖项的一部分。运行 SpringBootWebApplication 主类。当应用程序启动时,使用 URL从浏览器访问**http://localhost:8080,**IntelliJ控制台上的日志记录输出为:
我们还没有为 Logback 写任何配置。IndexController 和 SpringLoggingHelper 类的输出都来自 logback 根记录器。请注意, DEBUG消息未被记录。默认情况下, Logback 将记录DEBUG级别消息。但是, spring boot团队为我们提供了在 spring 启动默认 Logback 配置文件 (base.xml) 。此外, Spring boot提供了两个预配置的附加目的地通过console-appender. xml 和文件file-appender.xml。base.xml 文件引用它们。
以下是从git上找到spring-boot用的base.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 1<?xml version="1.0" encoding="UTF-8"?>
2<!--
3Base logback configuration provided for compatibility with Spring Boot 1.1
4-->
5<included>
6 <include resource="org/springframework/boot/logging/logback/defaults.xml" />
7 <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
8 <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
9 <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
10 <root level="INFO">
11 <appender-ref ref="CONSOLE" />
12 <appender-ref ref="FILE" />
13 </root>
14</included>
15
16
17
在这里, 您可以看到 Spring boot已通过将根记录器设置为INFO来覆盖 Logback 的默认日志记录级别, 这是我们在上面的示例中没有看到调试消息的原因。正如我们在下一节中看到的, 在 Spring boot中更改日志级别非常简单
Configuration via Spring Boot’s application.properties File
在 Spring boot应用程序中, 可以将配置具体化为在不同环境中使用相同的应用程序代码。application.properties文件很可能是几种不同的方式来外部化 Spring boot配置属性的最流行的方法。在 Spring boot web 应用程序的默认结构中, 可以在 "Resources" 文件夹下定位application.properties文件。在application.properties文件中, 可以定义 Spring boot日志级别、应用日志日志级别、Hibernate日志级别、Thymeleaf 日志级别等。还可以定义一个日志文件, 以将日志消息写入到控制台之外。
下面是
application
.
properties文件的日志配置
1
2
3
4
5 1logging.level.org.springframework.web=INFO
2logging.level.guru.springframework.controllers=DEBUG
3logging.level.org.hibernate=ERROR
4logging.file=logs/spring-boot-logging.log
5
注意: 还有一个logging.path 属性, 用于指定记录文件的路径。如果使用它, Spring boot会在指定路径中创建一个 spring.log 文件。但是, 不能同时指定logging.file和logging.path属性。如果同时配置,Spring Boot将全部忽略。
当您现在运行main 类并访问应用程序时, 从 IndexController 和 SpringLoggingHelper 的日志消息将记录到控制台和logs/spring-boot-logging.log文件。
在输出中, 请注意, IndexController 的DEBUG和更高级别的消息被记录到控制台和文件中。这是因为在application.properties文件中, 我们指定了DEBUG作为 guru.springframework.controllers 包的日志级别, IndexController 是其中的一部分。由于我们没有显式配置 SpringLoggingHelper 类, 所以使用了base.xml 文件的默认配置。因此, 仅记录了 SpringLoggingHelper 的信息和更高级别的消息。
当需要为特定类或包获取更详细的日志消息时, 可以看到这是多么简单。
Logback Configuration through an External File
Logback通过application.properties文件对于许多 Spring boot应用程序来说都是足够的。但是, 大型企业应用程序可能具有更复杂的日志记录要求。正如我前面提到的, Logback 通过 XML 和 Groovy 配置文件支持高级日志记录配置。
在 Spring boot应用程序中, 可以在项目类路径中指定Logback配置文件 logback.xml或 logback-spring.xml。不过, spring boot团队建议使用 spring 变体来进行日志配置, logback-spring. xml 比 logback xml 更可取。如果使用标准 logback 配置, 则 Spring boot可能无法完全控制日志初始化。
下面是 logback-spring.xml文件的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 1
2<?xml version="1.0" encoding="UTF-8"?>
3<configuration>
4 <include resource="org/springframework/boot/logging/logback/base.xml"/>
5 <logger name="guru.springframework.controllers" level="WARN" additivity="false">
6 <appender-ref ref="CONSOLE"/>
7 <appender-ref ref="FILE"/>
8 </logger>
9 <logger name="guru.springframework.helpers" level="WARN" additivity="false">
10 <appender-ref ref="CONSOLE"/>
11 <appender-ref ref="FILE"/>
12 </logger>
13 </configuration>
14
15
16
在上面的配置代码中, 我们将base.xml文件在第三行引入, 注意到我们没有配置任何appenders。相反, 我们依赖于CONSOLE和FILE, 这些都是由 Spring boot提供的。
通过更新的 Spring boot Logback 配置, 我们的日志输出现在看起来像这样:
注意: spring boot期望 logback-spring.xml的配置文件放在类路径上。
但是
,
您
可以
将
其
存储
在
其他
位置
, 并
使用
应用程序
中
的
application
.
properties文件中指定logging.config
属性改变它
注意:如果
logback-spring.xml放在Spring boot resources目录,写法如下
1
2 1 logging.config=classpath:logback-spring.xml
2
Spring Boot Profiles in Logging
在本地计算机中开发时, 通常要将日志级别设置为 "DEBUG"。这将为您的开发使用提供详细的日志消息。在生产时, 其典型设置为WARN或以上的日志级别。这是为了避免在生产中运行时使用过多的调试信息和记录开销来填充日志。虽然日志记录非常有效, 但仍有成本。
spring boot通过将 logback 配置的 spring 配置文件扩展到 <springProfile> 元素来满足这些要求。在 logback 文件中使用此元素, 可以根据活动的 spring 配置文件选择包含或排除日志配置。
注意: 对 <springProfile> logback 配置的支持可从SpringBoot 1.3.0.M2里程碑开始。
下面是一个 XML 示例, 用于使用活动的 Spring 配置文件配置 Logback。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 1
2<?xml version="1.0" encoding="UTF-8"?>
3<configuration>
4 <include resource="org/springframework/boot/logging/logback/base.xml" />
5 <springProfile name="dev,staging">
6 <logger name="guru.springframework.controllers" level="DEBUG" additivity="false">
7 <appender-ref ref="CONSOLE" />
8 </logger>>
9 </springProfile>
10 <springProfile name="production">
11 <logger name="guru.springframework.controllers" level="WARN" additivity="false">
12 <appender-ref ref="FILE" />
13 </logger>
14 </springProfile>
15 </configuration>
16
17
18
在上面的配置代码中, 对于dev和staging profiles, 我们配置了 guru.springframework.controllers 记录器, 以便将DEBUG和更高级别的消息记录到控制台。对于生产配置文件, 我们配置了相同的记录器, 以便将警告和更高级别的消息记录到文件中。
若要将配置文件传递给应用程序, 请使用 -Dspring.profiles.active= JVM 参数运行应用程序。
对于本地开发, 在 IntelliJ 中, 选择 "运行-编辑配置", 然后在 "运行/调试配置" 对话框中设置 JVM 参数, 如下所列。
现在
,
当
我们
使用dev
配置文件
运行
应用程序
时
,
我们
将
看到
以下
日志
输出
在上述输出中, 观察 IndexController 的测井输出。根据dev文件的配置, 调试和更高的日志消息被记录到控制台。您可以使用production文件重新启动应用程序, 以确保将警告和更高的日志消息记录到文件中。
Conditional Processing of Configuration File
Logback 支持在 Janino 库的帮助下对配置文件进行条件处理。可以使用配置文件中的 <if>、<then> 和 <else> 元素来针对多个环境。要执行条件处理, 请将 Janino 依赖项添加到您的 Maven POM, 如下所愿。
1
2
3
4
5
6 1<dependency>
2 <groupId>org.codehaus.janino</groupId>
3 <artifactId>janino</artifactId>
4 <version>2.7.8</version>
5</dependency>
6
完整的logback-spring.xml文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 1
2<?xml version="1.0" encoding="UTF-8"?>
3<configuration>
4 <include resource="org/springframework/boot/logging/logback/base.xml" />
5 <springProfile name="dev,staging">
6 <logger name="guru.springframework.controllers" level="DEBUG" additivity="false">
7 <appender-ref ref="CONSOLE" />
8 </logger>>
9 </springProfile>
10 <springProfile name="production">
11 <logger name="guru.springframework.controllers" level="WARN" additivity="false">
12 <appender-ref ref="FILE" />
13 </logger>
14 </springProfile>
15 <if condition='property("spring.profiles.active").contains("dev")'>
16 <then>
17 <logger name="guru.springframework.helpers" level="DEBUG" additivity="false">
18 <appender-ref ref="CONSOLE" />
19 </logger>
20 </then>
21 <else>
22 <logger name="guru.springframework.helpers" level="WARN" additivity="false">
23 <appender-ref ref="FILE" />
24 </logger>
25 </else>
26 </if>
27</configuration>
28
29
30
在上面的代码中, 我们在 <if> 元素中指定了一个条件, 以检查当前active profile 是否包dev。如果条件计算结果为 true, 则 <then> 元素内的配置代码将执行。在 <then> 元素中, 我们配置 guru.springframework.helpers 将DEBUG和更高的消息记录到控制台。我们使用 <else> 元素来配置记录器, 以便将WARN和更高的消息记录到日志文件中。<else> 元素为dev以外的任何配置文件执行。
当您使用生产配置文件运行应用程序并对其进行访问时, 两个记录器都会将警告和更高的消息记录到日志文件中, 类似于此。
对于开发人员配置文件, 两个记录器都会将调试和更高的消息记录到控制台, 类似于此。
Logback Auto-Scan Issue with Spring Boot
在 logback-spring.xml文件中, 可以通过设置scan="true" 属性启用对配置的自动扫描。启用自动扫描后, Logback 扫描配置文件中的更改。对于任何更改, Logback 会自动使用它们进行重新配置。通过将时间段传递给 scanPeriod 属性, 可以指定扫描期间, 并以毫秒、秒、分钟或小时为单位指定值。
例如, 此代码告诉 Logback 在每10秒后扫描 Logback-spring. xml。
1
2
3
4 1<configuration debug="true" scan="true" scanPeriod="10 seconds" >
2 ...
3</configuration>
4
Spring boot Logback 的一个限制是, 使用 springProfile 和 springProperty, 设置自动扫描会导致错误。
1
2
3
4
5
6
7
8
9
10 1//Error on using auto-scan with springProfile
2
3-ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:39 - no applicable action for [springProfile],
4 current ElementPath is [[configuration][springProfile]]
5
6//Error on using auto-scan with springProperty
7
8 -ERROR in ch.qos.logback.core.joran.spi.Interpreter@12:125 - no applicable action for [springProperty],
9 current ElementPath is [[configuration][springProperty]]
10
错误是由于不兼容问题而发生的。Spring boot使用 JoranConfigurator 子类支持 springProfile 和 springProperty。不幸的是, Logback 的 ReconfigureOnChangeTask 并没有提供一个钩子插入它。
Conclusion
Logback 在开源社区中的流行趋势。许多流行的开源项目使用 Logback 来满足他们的日志需求。Apache Camel, Gradle只是几个例子。
Logback 显然具有处理复杂企业应用程序中的日志记录需求的能力。所以, 难怪Spring boot 团队为默认的日志记录实现选择 Logback。正如您在这篇文章中看到的, Spring boot 团队提供了与 Logback 的良好集成。出框, Logback 准备使用Spring boot。在这篇文章中, 您已经看到了在您的日志要求不断变化的情况下, 在 Spring boot中配置 Logback 是多么容易
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 1<?xml version="1.0" encoding="UTF-8" ?>
2<configuration scan="true" scanPeriod="30 seconds">
3 <!-- 自定义变量参数 -->
4 <property name="log.dir" value="C:/logs/fkandy-springboot-logback" />
5 <!--控制台日志日志输出策略-->
6 <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
7 <layout class="ch.qos.logback.classic.PatternLayout">
8 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%t] [%C#%M:%L] - %msg%n</pattern>
9 </layout>
10 </appender>
11
12 <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
13 <filter class="ch.qos.logback.classic.filter.LevelFilter">
14 <!--DEBUG ->INFO -> WARN ->ERROR-->
15 <!-- 拦截ERROR级别的日志。如果匹配到了,则禁用处理。如果不匹配,则接受,开始处理日志 -->
16 <level>ERROR</level>
17 <onMatch>DENY</onMatch>
18 <onMismatch>ACCEPT</onMismatch>
19 </filter>
20
21 <encoder>
22 <charset>UTF-8</charset>
23 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%t] [%C#%M:%L] - %msg%n</pattern>
24 </encoder>
25
26 <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
27 <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
28 <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
29 <FileNamePattern>${log.dir}/info.%d{yyyy-MM-dd}-%i.log.zip</FileNamePattern>
30 <!--只保留最近60天的日志-->
31 <maxFileSize>100MB</maxFileSize>
32 <maxHistory>60</maxHistory>
33 <totalSizeCap>20GB</totalSizeCap>
34 </rollingPolicy>
35 </appender>
36
37 <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
38 <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
39 <level>ERROR</level>
40 </filter>
41 <encoder>
42 <charset>UTF-8</charset>
43 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%t] [%C#%M:%L] - %msg%n</pattern>
44 </encoder>
45 <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
46 <fileNamePattern>${log.dir}/error.%d{yyyy-MM-dd}-%i.log.zip</fileNamePattern>
47 <!--设置日志文件切割的大小-->
48 <maxFileSize>100MB</maxFileSize>
49 <!--只保留最近60天的日志-->
50 <maxHistory>60</maxHistory>
51 <totalSizeCap>20GB</totalSizeCap>
52 </rollingPolicy>
53 </appender>
54
55 <root level="info">
56 <appender-ref ref="consoleLog"/>
57 <appender-ref ref="fileInfoLog"/>
58 <appender-ref ref="fileErrorLog"/>
59 </root>
60
61</configuration>
62
以上内容主要做了以下几件事
- 日志分为控制台日志、普通信息日志文件、错误日志文件三类
- 每类文件大小为100MB,一天内大于100MB会切割成多个文件存储
- 新文件生成会对之前的日志进行压缩存储 (100MB的文件压缩之后大约为1MB)
- 默认保留60天的日志,默认日志总大小为20GB, maxHistory的优先级大于totalSizeCap
更多请参看中文文档http://www.logback.cn/