在项目开发中,日志组件是整个系统框架不可或缺的重要部分。在springboot项目中,默认已集成了logback日志组件,即无需再依赖其他日志组件包,springboot已具备日志能力。

一、背景

springboot虽默认集成了logback组件,但如果不做必要的配置,在系统运行过程中,输出的日志显得杂乱。
面临的问题有:

  • debug模式下,日志杂乱,不便于查看分析日志。
    比如在开发过程中,设置为debug日志输出级别时,第三方(如spring)包会输出大量的debug日志,会让系统日志非常难以分析和查看。
  • 不能将日志保存到文件。默认的日志仅输出到控制台,并不能以日志文件存储到指定目录下。

通常这种情况下,我们希望:

  • 在开发模式下,自己开发的源代码,使用debug日志输出级别,对第三方包,使用info,或者warn等更高的级别,让日志输出的内容更加简洁,有效,提升开发过程中的代码调试效率;
  • 在生产模式下,我们希望日志能够保存到文件中,并按日归档,定期清除。

二、配置使用

针对以上情况,我们就需要对springboot项目的日志进行配置管理,以满足我们的技术需求;

配置使用的过程非常简单,通过2个步骤即可完成:

1、配置logback-spring.xml文件

在springboot项目的src/main/resources目录下,新建一个logback-spring.xml文件,配置内容及说明如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="10 seconds">
   <!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为INFO,则低于INFO级别的信息都不会输出 -->
   <!-- scan:默认值为true,当此属性设置为true时,配置文件如果发生改变,将会被重新加载 -->
   <!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
   <!-- debug:默认值为false。当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。 -->
   <contextName>logback</contextName>

   <!--设置属性 -->
   <property name="path" value="log" />
   <property name="maxHistory" value="30" />
   <property name="maxFileSize" value="50MB" />

   <!-- 彩色日志 -->
   <!-- 彩色日志依赖的渲染类 -->
   <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
   <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
   <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
   <!-- 彩色日志格式 -->
   <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39} - [%3line]){cyan}  %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>

   <!--输出到控制台-->
   <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
       <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
           <level>debug</level>
       </filter>
       <encoder>
           <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
           <charset>UTF-8</charset>
       </encoder>
   </appender>

   <!-- debug日志输出文件 -->
   <appender name="debug_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
       <file>${path}/debug.log</file>
       <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
           <!-- 每天对日志压缩归档 -->
           <fileNamePattern>${path}/debug.log.%d{yyyy-MM-dd}-%i.zip</fileNamePattern>
           <maxHistory>${maxHistory}</maxHistory>
           <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
               <maxFileSize>${maxFileSize}</maxFileSize>
           </timeBasedFileNamingAndTriggeringPolicy>
       </rollingPolicy>
       <encoder>
           <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger [%file : %line] - %msg%n</pattern>
           <charset>UTF-8</charset>
       </encoder>
       <filter class="ch.qos.logback.classic.filter.LevelFilter">
           <level>DEBUG</level>
           <onMatch>ACCEPT</onMatch>
           <onMismatch>DENY</onMismatch>
       </filter>
   </appender>

   <!-- info日志输出文件 -->
   <appender name="info_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
       <file>${path}/info.log</file>
       <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
           <!-- 每天对日志压缩归档 -->
           <fileNamePattern>${path}/info.log.%d{yyyy-MM-dd}-%i.zip</fileNamePattern>
           <maxHistory>${maxHistory}</maxHistory>
           <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
               <maxFileSize>${maxFileSize}</maxFileSize>
           </timeBasedFileNamingAndTriggeringPolicy>
       </rollingPolicy>
       <encoder>
           <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger [%file : %line] - %msg%n</pattern>
           <charset>UTF-8</charset>
       </encoder>
       <filter class="ch.qos.logback.classic.filter.LevelFilter">
           <level>INFO</level>
           <onMatch>ACCEPT</onMatch>
           <onMismatch>DENY</onMismatch>
       </filter>
   </appender>

   <!-- warn日志输出文件 -->
   <appender name="warn_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
       <file>${path}/warn.log</file>
       <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
           <!-- 每天对日志压缩归档 -->
           <fileNamePattern>${path}/warn.log.%d{yyyy-MM-dd}-%i.zip</fileNamePattern>
           <maxHistory>${maxHistory}</maxHistory>
           <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
               <maxFileSize>${maxFileSize}</maxFileSize>
           </timeBasedFileNamingAndTriggeringPolicy>
       </rollingPolicy>
       <encoder>
           <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger [%file : %line] - %msg%n</pattern>
           <charset>UTF-8</charset>
       </encoder>
       <filter class="ch.qos.logback.classic.filter.LevelFilter">
           <level>WARN</level>
           <onMatch>ACCEPT</onMatch>
           <onMismatch>DENY</onMismatch>
       </filter>
   </appender>

   <!-- error日志输出文件 -->
   <appender name="error_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
       <file>${path}/error.log</file>
       <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
           <!-- 每天对日志压缩归档 -->
           <fileNamePattern>${path}/error.log.%d{yyyy-MM-dd}-%i.zip</fileNamePattern>
           <maxHistory>${maxHistory}</maxHistory>
           <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
               <maxFileSize>${maxFileSize}</maxFileSize>
           </timeBasedFileNamingAndTriggeringPolicy>
       </rollingPolicy>
       <encoder>
           <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger [%file : %line] - %msg%n</pattern>
           <charset>UTF-8</charset>
       </encoder>
       <filter class="ch.qos.logback.classic.filter.LevelFilter">
           <level>ERROR</level>
           <onMatch>ACCEPT</onMatch>
           <onMismatch>DENY</onMismatch>
       </filter>
   </appender>

   <!--项目源码包以debug级别输出,便于开发调试-->
   <logger name="com.xxx" level="debug" />
   <!--第三方包以info级别输出,减少日志量 -->
   <logger name="org.springframework" level="info" />

   <root>
       <level value="info"/>
       <appender-ref ref="console"/>
       <appender-ref ref="debug_file"/>
       <appender-ref ref="info_file"/>
       <appender-ref ref="warn_file"/>
       <appender-ref ref="error_file"/>
   </root>

</configuration>

2、加载logback-spring.xml配置

在springboog项目的配置文件application.properties配置文件中,加载上面配置的logback-spring.xml配置文件,使配置生效。

application.properties配置的内容如下:

###########################################################
## 日志配置
###########################################################
# 开启spring彩色日志
spring.output.ansi.enabled=always
# 加载logback日志配置文件
logging.config=classpath:logback-spring.xml

通过上述两步操作,springboot的日志配置文件就已配置完成了。可以看到控制台中的日志输出变得非常简洁,而且文本内容也有高亮显示,非常便于查看分析。