java透传参数至logback,自定义日志文件名。过期日志文件自动删除

LogFilter

filter日志拦截,把不需要打印的日志信息拦截在外,只录入有key参数的(filterReply = FilterReply.ACCEPT;)。

java 复制代码
package com.***.***.filter;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * task log filter
 */
public class LogFilter extends Filter<ILoggingEvent> {

    private static Logger logger = LoggerFactory.getLogger(LogFilter.class);

    /**
     * Task Logger Thread's name
     */
    public static final String LOG_FORMAT = "customLogId";

    /**
     * level
     */
    private Level level;

    /**
     * Accept or reject based on thread name
     *
     * @param event event
     * @return FilterReply
     */
    @Override
    public FilterReply decide(ILoggingEvent event) {
        FilterReply filterReply = FilterReply.DENY;
        if (event.getMDCPropertyMap().containsKey(LOG_FORMAT)) {
            filterReply = FilterReply.ACCEPT;
        }
        logger.debug("task log filter, thread name:{}, loggerName:{}, filterReply:{}, level:{}", event.getThreadName(),
                event.getLoggerName(), filterReply.name(), level);

        return filterReply;
    }
}

java打印日志

java 复制代码
public void TestLog() {
    String customLogId = "123456789";
    MDC.put("customLogId", customLogId);
    log.info("customLogId={}, logTest start success!", customLogId);
    log.info("111111111111111111111111111111111111111111111111");
    log.info("customLogId={}, logTest end success!", customLogId);
    MDC.clear();
}

logback的XML配置:

filter class配置为filter的包路径.类名。如果不需要拦截日志的话,可以不用配置filter,java中也不用写。因为我的参数透传使用在了日志文件命名当中,没有key的数据会替换为unknown,日志就录入到unknown文件当中了,所以加了filter过滤。

appender SiftingAppender 可以使用discriminator自定义参数

discriminator 的key 是在java代码录日志之前通过MDC录入

XML 复制代码
<appender name="CUSTOMLOGFILE" class="ch.qos.logback.classic.sift.SiftingAppender">
        <filter class="com.***.***.filter.LogFilter"/>
        <discriminator>
            <key>customLogId</key>
            <defaultValue>unknown</defaultValue>
        </discriminator>
        <sift>
            <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <file>${log_dir}/custom/${customLogId}.log</file>
                <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                    <!--日志文件输出的文件名-->
                    <fileNamePattern>${log_dir}/custom/%d{yyyy-MM-dd}/${customLogId}.%i.log</fileNamePattern>
                    <!--日志保留时长-->
                    <maxHistory>2</maxHistory>
                    <!--日志大小-->
                    <maxFileSize>2KB</maxFileSize>
                    <totalSizeCap>5KB</totalSizeCap>
                    <cleanHistoryOnStart>true</cleanHistoryOnStart>
                </rollingPolicy>

                <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                    <providers>
                        <pattern>
                            <pattern>
                                {
                                "time": "%d{yyyy-MM-dd HH:mm:ss.SSS}",
                                "level": "%level",
                                "thread": "%thread",
                                "class": "%logger{40}",
                                "message": "%msg",
                                "stack_trace": "%exception{10}"
                                }
                            </pattern>
                            <charset>utf8</charset>
                        </pattern>
                    </providers>
                </encoder>
            </appender>
        </sift>
    </appender>

参数解析

RollingFileAppender可以用于滚动日志。期望根据日期、文件大小删除日志时,可使用。

file 生成的日志名称

rollingPolicy 滚动策略,这里采用的SizeAndTimeBasedRollingPolicy,基于日志文件大小和时间滚动。

fileNamePattern 定义翻转(归档)日志文件的名称。

它的值应该包括文件的名称以及适当放置的% d 转换说明符。% d 转换说明符可能包含日期和时间模式。如果省略了日期和时间模式,则假定使用默认模式 yyyy-MM-dd。翻转周期是从 fileNamePattern 的值推断出来的。这里的滚动周期需要和maxHistory配合使用。

maxFileSize 单个日志文件的最大体积,到达最大体积后就会触发日志滚动操作,生成新的日志文件

maxHistory 要保存的归档文件的最大数量,以异步方式删除旧文件。例如,如果通过fileNamePattern中的%d{yyyy-MM}指定滚动周期为月度滚动,并将 maxHistory 设置为6,那么存档文件中超过6个月的文件将被删除。

totalSizeCap 控制所有归档日志文件的总大小。当超出总大小上限时,将异步删除最早的归档日志文件。设置totalSizeCap 属性还要求设置 maxHistory 属性。优先"最大历史"限制,其次是"总大小上限"的限制。

按照实际业务情况配置 totalSizeCap ,可以有效避免占用过大的磁盘空间。

比如你希望 maxHistory 保留7天日志文件,但是可能这7个文件总大小超出磁盘容量,所以可以通过 totalSizeCap 来控制总大小,这样系统会判断大于此值时进行自动覆盖。

注意⚠️:单独配置totalSizeCap是没有意义的,一定要同时配置maxHistory属性,且大于0,才能实现超过总大小上限异步删除。

cleanHistoryOnStart 是否在应用启动的时候删除历史日志。

如果设置为真,将在启动应用程序时执行档案删除。默认情况下,此属性设置为 false。归档日志移除通常在滚动期间执行。但是,有些应用程序的存活时间可能不够长,无法触发滚动。因此,对于如此短命的应用程序,删除存档可能永远没有机会执行。通过将 cleanHistoryOnStart 设置为 true,将在启动 appender 时执行档案删除。

encoder 控制输出日志的格式和编码。

patten里的内容可以看到我改成了json格式。有利于后续在ELK中使用。

当然你也可以写成常规的打印的日志格式

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative %thread %-5level %logger{35} - %msg%n</pattern>

<fileNamePattern>{log_dir}/custom/%d{yyyy-MM-dd}/{customLogId}.%i.log</fileNamePattern>

这段话要注意一下:

日志是根据%d来进行日期滚动的,如果有多个%d就无法识别了。

在fileNamePattern配置中添加多个%d的日期符号,但是只能有一个是主要的,其它的只能做为辅助(auxiliary)。在RollingCalendar类中,日志的文件滚动方式就是根据主%d那个日期判断的.

比如:/var/log/%d{yyyy/MM, aux}/myapplication.%d{yyyy-MM-dd}.log

%i是自然数,当生成多个的时候会按照0123...生成尾号不同的文件。

图中配的时长大小比较小是为了测试。正常可以按周/月清理日志,大小在100MB,总大小20GB左右。根据情况调整

相关推荐
SWAGGY..3 分钟前
Linux系统编程:(十三)环境变量
java·linux·算法
程序员黑豆9 分钟前
AI全栈开发 - Java:基本数据类型 vs 引用数据类型的内存存储
java·前端·ai编程
布朗克16827 分钟前
34 JVM深入理解
java·jvm
Flittly35 分钟前
【AgentScope Java新手村系列】(4)结构化输出
java·spring boot·spring·ai
wzg19690226wzg36 分钟前
rust 学习 泛型
开发语言·学习·rust
techdashen38 分钟前
Rust 基础设施团队 2025 Q4 回顾与 2026 Q1 计划
开发语言·后端·rust
红宝村村长39 分钟前
torch.autograd.Function.apply()
开发语言·python
AI科技星39 分钟前
《数术工坊:非欧射影录》类型:硬核光影·几何本源
c语言·开发语言·网络·量子计算·agi
何以解忧,唯有..1 小时前
Python 中的继承机制:从基础到高级用法详解
java·开发语言·python