假如在logback配置文件中存在以下配置
<appender name="custom_log_file" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${custom_log_dir}/custom_%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>${maxHistory}</maxHistory><totalSizeCap>${totalSizeCap}</totalSizeCap></rollingPolicy><encoder><pattern>%msg%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>DEBUG</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender>
那么最终生成的日志文件名称为custom_+当前日期
,但是有时候不想读取自然日期,而是业务日期(业务日期可能与自然日期存在一些出入)。那么怎么处理呢?
在TimeBasedRollingPolicy中有一个timeBasedFileNamingAndTriggeringPolicy属性。如果不配置,则取值为DefaultTimeBasedFileNamingAndTriggeringPolicy
。
以下源码方法为 ch.qos.logback.core.rolling.TimeBasedRollingPolicy#start
if (timeBasedFileNamingAndTriggeringPolicy == null) {timeBasedFileNamingAndTriggeringPolicy = new DefaultTimeBasedFileNamingAndTriggeringPolicy<E>();}
然后在ch.qos.logback.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy#isTriggeringEvent
方法中会判断是否为触发事件。源码如下
public boolean isTriggeringEvent(File activeFile, final E event) {long time = getCurrentTime();if (time >= nextCheck) {Date dateOfElapsedPeriod = dateInCurrentPeriod;addInfo("Elapsed period: " + dateOfElapsedPeriod);elapsedPeriodsFileName = tbrp.fileNamePatternWithoutCompSuffix.convert(dateOfElapsedPeriod);setDateInCurrentPeriod(time);computeNextCheck();return true;} else {return false;}}
覆盖该方法即可,自定一个CustomTimeBasedFileNamingAndTriggeringPolicy
类覆盖时间获取逻辑。
package org.example;import ch.qos.logback.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy;
import ch.qos.logback.core.rolling.helper.FileNamePattern;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;/*** @author: guanglai.zhou* @date: 2023/12/29 10:45*/
public class CustomTimeBasedFileNamingAndTriggeringPolicy extends DefaultTimeBasedFileNamingAndTriggeringPolicy {private static final Logger logger = LoggerFactory.getLogger(CustomTimeBasedFileNamingAndTriggeringPolicy.class);private static AtomicInteger INDEX = new AtomicInteger(0);private static String currDate = "2023-03-05";@Overridepublic boolean isTriggeringEvent(File activeFile, Object event) {List<String> dayList = Arrays.asList("2023-03-06", "2023-03-07", "2023-03-08", "2023-03-09", "2023-03-10");// 业务日期 从数据库里面查currDate = dayList.get(INDEX.getAndIncrement() % dayList.size());logger.info("从数据库获取业务日期{}", currDate);if (activeFile.getName().contains(currDate)) {return false;} else {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");Date parse = null;try {parse = dateFormat.parse(currDate);} catch (ParseException e) {logger.error(e.getMessage(), e);}long time = parse != null ? parse.getTime() : getCurrentTime();Date dateOfElapsedPeriod = parse != null ? parse : dateInCurrentPeriod;addInfo("Elapsed period: " + dateOfElapsedPeriod);// 通过反射获取 fileNamePatternWithoutCompSuffixtry {FileNamePattern fileNamePatternWithoutCompSuffix = (FileNamePattern) FieldUtils.readField(tbrp, "fileNamePatternWithoutCompSuffix", true);elapsedPeriodsFileName = fileNamePatternWithoutCompSuffix.convert(dateOfElapsedPeriod);System.out.println("elapsedPeriodsFileName = " + elapsedPeriodsFileName);} catch (IllegalAccessException e) {logger.error(e.getMessage(), e);throw new RuntimeException(e);}setDateInCurrentPeriod(time);computeNextCheck();return true;}}}
再自定义一个org.example.CustomTimeBasedRollingPolicy
设置上面的自定义类
package org.example;import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;/*** @author: guanglai.zhou* @date: 2023/12/29 10:54*/
public class CustomTimeBasedRollingPolicy extends TimeBasedRollingPolicy {public CustomTimeBasedRollingPolicy() {setTimeBasedFileNamingAndTriggeringPolicy(new CustomTimeBasedFileNamingAndTriggeringPolicy());}
}
最后修改logback中的相关定义即可,完整定义参考如下
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds" debug="true"><property name="custom_log_dir" value="/home/working/logs/custom"/><!-- 日志最大的历史 30天 --><property name="maxHistory" value="30"/><!-- 最大当前日志容量 --><property name="totalSizeCap" value="30GB"/><!-- 单个日志文件最大大小 --><property name="maxFileSize" value="16MB"/><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{18}.%M\(%F:%L\) #X# %msg%n</pattern></encoder></appender><appender name="custom_log_file" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="org.example.CustomTimeBasedRollingPolicy"><fileNamePattern>${custom_log_dir}/custom_%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>${maxHistory}</maxHistory><totalSizeCap>${totalSizeCap}</totalSizeCap></rollingPolicy><encoder><pattern>%msg%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>DEBUG</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><logger name="org.example" level="debug" additivity="true"/><root level="WARN"><appender-ref ref="STDOUT"/><appender-ref ref="custom_log_file"/></root></configuration>
相关依赖
<dependencies><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.3.2</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.30</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>1.7.30</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>log4j-over-slf4j</artifactId><version>1.7.30</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jul-to-slf4j</artifactId><version>1.7.30</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.3</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version><exclusions><exclusion><artifactId>slf4j-api</artifactId><groupId>org.slf4j</groupId></exclusion></exclusions></dependency></dependencies>
测试案例如下,创建一个主类,多次打印日志
public static void main(String[] args) {logger1.debug("API");logger3.debug("LOG4J-1");logger3.debug("LOG4J-2");logger3.debug("LOG4J-3");logger3.debug("LOG4J-4");logger3.debug("LOG4J-5");
}
最后日志会打印到多个文件当中