Spring Boot配置Logback及HTTP日志

系统上先后,需要进行一系列的运维、监控工作,可能还需要排查业务故障和系统问题。

服务已经上线了,不能像本地开发的一样“”打断点调试“,此时,日志的作用就非常重要了。

与其他服务框架类似,Spring Boot也默认集成了日志系统,默认采用Logback日志类库。

Logback是Log4j的作者开发的另一款日志类库,与其他同类竞品相比,它的优势有:

  • 更高的性能,官方说比Log4j快10倍以上
  • 原生兼容slf4j
  • 支持多环境配置、自动切换、压缩等高级功能

在本节的前半部分,我们将讨论如何在Spring Boot中如何使用Logback。本节的后半部分,我们看一下如何在Spring Boot中启用HTTP访问日志(内嵌的Tomcat日志)。

Spring Boot中配置Logback

在Spring Boot中配置Logback只需要两步:

  • 确认类路中含有logback,这一般是通过其他starter自动带上的,例如spring-boot-starter-web
  • 定义配置文件:logback-spring.xml

我们来看一下配置好的文件:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <configuration>
  3. <!-- For console -->
  4. <appender name="ConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
  5. <encoder>
  6. <charset>UTF-8</charset>
  7. <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%thread] [%logger] [tr=%mdc{TRACE_ID:-0}] %msg %n</Pattern>
  8. </encoder>
  9. </appender>
  10. <!-- For file with daily rollover -->
  11. <appender name="ServerFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
  12. <encoder>
  13. <charset>UTF-8</charset>
  14. <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%thread] [%logger] [tr=%X{TRACE_ID:-0}] %msg %n</pattern>
  15. </encoder>
  16. <file>/app/logs/lmsia-abc.log</file>
  17. <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  18. <!-- daily rollover with gz -->
  19. <fileNamePattern>/app/logs/lmsia-abc.%d{yyyy_MM_dd}.log.gz</fileNamePattern>
  20. <!-- keep 30 days' max -->
  21. <maxHistory>30</maxHistory>
  22. </rollingPolicy>
  23. </appender>
  24. <!-- console only if local active -->
  25. <springProfile name="local">
  26. <root level="INFO">
  27. <appender-ref ref="ConsoleAppender"/>
  28. </root>
  29. </springProfile>
  30. <!-- file only if test or online active -->
  31. <springProfile name="test,online">
  32. <root level="INFO">
  33. <appender-ref ref="ServerFileAppender"/>
  34. </root>
  35. </springProfile>
  36. </configuration>

如上所示,我们的配置中包含了2个Appender(可理解为两种日志输出方法):

  • ConsoleAppender: 直接输出到命令行
  • ServerFileAppender: 输出到/app/logs/lmsia-abc.log文件中,并且:按天自动切换文件、并做gz压缩、最多保留30天。

上述切换、压缩、30天仅通过几行就搞定了,可见logback的强大之处!

在下面,我们通过对不同profile的判断,可以让不同的Appender生效。当我们在本地执行时,默认是local的profile,此时我们只运行ConsoleAppender,即直接输出到命令行,方便调试。当在服务器执行时,如测试环境test和生产环境online,我们只启用ServerFileAppender。因为此时没有人会看stdout的输出,都是通过看文件的方式来看日志的。

最后,我们简单看一下日志格式,即Pattern:

  1. %d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%thread] [%logger] [tr=%X{TRACE_ID:-0}] %msg %n

几个部分分别表示:

  • 日期,如2018-06-07 18:30:23.124
  • 日志级别,INFO, ERROR等
  • 日志线程,如果有名字会优先用名字,没有用线程ID
  • Logger名字,一般是类名
  • TraceId,追踪信息,下一节将介绍它
  • 消息体及换行,如果有异常及异常栈,会自动输出在后面

在代码中使用,也是非常简单:

  1. import org.slf4j.Logger;
  2. import org.slf4j.LoggerFactory;
  3. private Logger LOG = LoggerFactory.getLogger(getClass());
  4. LOG.info("Test");

配置Tomcat日志

Spring Boot默认内置了Tomcat服务器,从而实现了真正的”开箱即用”,如何开启Tomcat的HTTP访问日志呢?

一般有两种方法:

  • 在yaml中配置
  • 通过代码实现

其中yaml中配置的方案最简单,但每个项目都要配置一次,非常麻烦,网上资料很多,这里不做介绍了。

我们重点看一下第二种方案,我们可以将它抽成一个包,别的项目引用这个包时候,自动启用HTTP访问日志。

  1. import org.apache.catalina.valves.AccessLogValve;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
  5. import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
  6. import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
  7. import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  10. @Configuration
  11. @ConditionalOnWebApplication
  12. public class TomcatAccessLogConfiguration
  13. extends WebMvcConfigurerAdapter implements EmbeddedServletContainerCustomizer {
  14. private Logger LOG = LoggerFactory.getLogger(getClass());
  15. @Override
  16. public void customize(ConfigurableEmbeddedServletContainer container) {
  17. if (container instanceof TomcatEmbeddedServletContainerFactory) {
  18. TomcatEmbeddedServletContainerFactory factory = (TomcatEmbeddedServletContainerFactory) container;
  19. AccessLogValve accessLogValve = new AccessLogValve();
  20. accessLogValve.setEnabled(true);
  21. accessLogValve.setDirectory("/app/logs/");
  22. accessLogValve.setPattern("common");
  23. accessLogValve.setSuffix(".log");
  24. factory.addContextValves(accessLogValve);
  25. } else {
  26. LOG.error("This customizer does not support your configured container!");
  27. }
  28. }
  29. }

如上所示:

  • 当启用Web时,自动激活这个自动配置
  • 使用默认的日志格式common
  • 路径在/app/logs下,后缀是.log

当然不要忘记加一个spring.factories

  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  2. com.coder4.lmsia.commons.http.configuration.TomcatAccessLogConfiguration

这样,当别的Spring Boot项目引用这个库时,就会自动启用HTTP日志了。

这个HTTP日志也是支持按天滚动,只不过不支持压缩,如果你想对其进行更多定制,推荐直接阅读Tomcat的相关源代码。