Logback-日志文件按日期切分解决方案

  • Post author:
  • Post category:其他


Logback,是一个开源的日志组件,同样也是由log4j创始人设计。天然支持SLF4J(Simple Logging Facade For Java)。在Spring Boot中,使用Logback是最优的选择,可使用logback-spring.xml进行配置使用。

实际项目中经常需要通过日志文件来定位,不同于本地测试开发环境,线上的日志文件如果不做按日期切割整理就会比较乱,而且打开日志文件需要很久。

本文旨在提供多种实际可用的日志配置文件模板,便捷可用。



一、Logback使用

logback有5种级别,分别是TRACE < DEBUG < INFO < WARN < ERROR。

使用如下:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;

public class MyLogback {

    private Logger logger = LoggerFactory.getLogger(MyLogback.class);
    
    void test(){
        String now = LocalDateTime.now().toString
        logger.trace("trace 测试日志打印->{}", now);
        logger.debug("debug 测试日志打印->{}", now);
        logger.info("info   测试日志打印->{}", now);
        logger.warn("warn   测试日志打印->{}", now);
        logger.error("error 测试日志打印->{}", now);
    }
}

如何自定义日志管理。在resource目录下新建一个logback-spring.xml文件。该xml文件主要分为以下几部分:

  1. 头部声明

    <?xml version="1.0" encoding="UTF-8"?>
    
  2. 主节点

    包含参数定义以及关键appender节点

    <configuration>
    	<!-- 项目名称 例:mylogback -->
        <property name="APP_NAME" value="mylogback" />
        <!-- 日志目录 例:/usr/local/mylogback/logs -->
        <property name="LOG_PATH" value="/usr/local/${APP_NAME}/logs" />
    </configuration>
    
  3. 关键子节点

    • appender:是一个接口,最重要的有两个Appender,分别为ConsoleAppender和RollingFileAppender。顾名思义,前者主要是控制台输出,对应的class值为:ch.qos.logback.core.ConsoleAppender;后者则是输出到文件中,对应的class值为ch.qos.logback.core.rolling.RollingFileAppender
    • file:主要针对RollingFileAppender输出文件命名规则
    • encoder:最主要的是pattern,定义日志格式
    • filter:日志过滤规则
    • rollingPolicy:主要针对文件日志输出,定义输出日志策略
    <appender name="myDebuglog" class="ch.qos.logback.core.ConsoleAppender">
        <file>
        	${LOG_PATH}/debug.log
        </file>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <!-- 过滤策略 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 设置命中策略 debug、info、warn、error -->
            <level>debug</level>
            <!-- 命中设置的日志等级就记录 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 未命中则拒绝该appender策略 -->
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 日志归档 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 每产生一个日志文件,该日志文件的保存期限为30天 -->
            <maxHistory>30</maxHistory>
            <!-- 单个文件达到最大10MB时开始切分 -->
            <maxFileSize>10MB</maxFileSize>
            <!-- 当日志容量超过20GB,即使没有到保存期限的30天也会开启日志清理 -->
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
    </appender>
    



二、默认实现

如果我们不写logback.xml配置文件,工程项目也会正常打印日志,因为springboot有默认的实现,即通过以下两个文件进行指定,以下是Spring Boot下的org/springframework/boot/logging/logback/base.xml、defaults.xml文件默认实现:

base.xml:

<?xml version="1.0" encoding="UTF-8"?>

<!--
Base logback configuration provided for compatibility with Spring Boot 1.1
-->

<included>
	<include resource="org/springframework/boot/logging/logback/defaults.xml" />
	<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
	<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
	<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
	<root level="INFO">
		<appender-ref ref="CONSOLE" />
		<appender-ref ref="FILE" />
	</root>
</included>

defaults.xml:

<?xml version="1.0" encoding="UTF-8"?>

<!--
Default logback configuration provided for import
-->

<included>
	<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{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
	<property name="CONSOLE_LOG_CHARSET" value="${CONSOLE_LOG_CHARSET:-${file.encoding:-UTF-8}}"/>
	<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
	<property name="FILE_LOG_CHARSET" value="${FILE_LOG_CHARSET:-${file.encoding:-UTF-8}}"/>

	<logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/>
	<logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"/>
	<logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN"/>
	<logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"/>
	<logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"/>
	<logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR"/>
	<logger name="org.hibernate.validator.internal.util.Version" level="WARN"/>
	<logger name="org.springframework.boot.actuate.endpoint.jmx" level="WARN"/>
</included>



三、实用模板

经过上述分析,对logback配置文件有了大概的了解,接下来旨在提供标准可用的日志配置文件,并且由于trace级别的日志打印极少用到,我们在配置文件中暂不体现trace级别配置,若有需要请根据实际需求进行增减调整配置。

此处定义的日志目录会输出到C盘,若部署到线上需要做调整;日志最大保留天数均为30天,单个文件最大不超过100MB,且在同个level下总文件大小不超过20GB,否则即使没超过30天也会自动清理日志:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 引入默认实现 -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <!-- 自定义项目名称 例:mylogback -->
    <property name="APP_NAME" value="mylogback" />
    <!-- 自定义日志目录 若线上部署环境需调整 如:/usr/local/${APP_NAME}/logs -->
    <property name="LOG_PATH" value="C:/${APP_NAME}/logs" />
    <!-- 引入日志等级参数,支持从配置文件读入 -->
    <springProperty scope="context" name="log.level" source="log.level"/>

    <!-- 时间滚动输出 level为 DEBUG 日志 -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/debug.log</file>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <!-- 日志归档 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <maxFileSize>100MB</maxFileSize>
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
        <!-- 此日志文件只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 INFO 日志 -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/info.log</file>
        <encoder>
            <charset>UTF-8</charset>
            <!-- 引用默认的配置项 -->
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <!-- 日志归档 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <maxFileSize>100MB</maxFileSize>
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 WARN 日志 -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/warn.log</file>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <!-- 日志归档 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <maxFileSize>100MB</maxFileSize>
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
        <!-- 此日志文件只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 ERROR 日志 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/error.log</file>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <!-- 日志归档 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <maxFileSize>100MB</maxFileSize>
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
        <!-- 此日志文件只记录error级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>${log.level}</level>
        </filter>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <root level="${log.level}">
        <appender-ref ref="DEBUG_FILE" />
        <appender-ref ref="INFO_FILE" />
        <appender-ref ref="WARN_FILE" />
        <appender-ref ref="ERROR_FILE" />
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>

使用前建议配置日志打印等级,表示只打印输出设置值及以上等级的日志:

logging:
  level:
    root: debug #debug info warn error

实际使用效果如下:

image-20211123135321043

image-20211123135359092



四、总结

项目中最细微的日志打印虽然平时感知不到,正所谓润物细无声,但是实际上好的日志打印能够帮助你更快定位项目的线上问题。

读者可以clone该项目体验日志文件输出,该项目会定时每隔5秒打印各个等级的日志:

https://gitee.com/dearvainycos/mylogback.git

参考资料:



版权声明:本文为imVainiycos原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。