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左右。根据情况调整

相关推荐
Scott9999HH8 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔8 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社9 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海9 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖10 小时前
JDK 26 新特性详解
java·开发语言
马优晨11 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区12 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大13 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai13 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说13 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json