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


    LogFilter

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

    1. package com.***.***.filter;
    2. import ch.qos.logback.classic.Level;
    3. import ch.qos.logback.classic.spi.ILoggingEvent;
    4. import ch.qos.logback.core.filter.Filter;
    5. import ch.qos.logback.core.spi.FilterReply;
    6. import org.slf4j.Logger;
    7. import org.slf4j.LoggerFactory;
    8. /**
    9. * task log filter
    10. */
    11. public class LogFilter extends Filter {
    12. private static Logger logger = LoggerFactory.getLogger(LogFilter.class);
    13. /**
    14. * Task Logger Thread's name
    15. */
    16. public static final String LOG_FORMAT = "customLogId";
    17. /**
    18. * level
    19. */
    20. private Level level;
    21. /**
    22. * Accept or reject based on thread name
    23. *
    24. * @param event event
    25. * @return FilterReply
    26. */
    27. @Override
    28. public FilterReply decide(ILoggingEvent event) {
    29. FilterReply filterReply = FilterReply.DENY;
    30. if (event.getMDCPropertyMap().containsKey(LOG_FORMAT)) {
    31. filterReply = FilterReply.ACCEPT;
    32. }
    33. logger.debug("task log filter, thread name:{}, loggerName:{}, filterReply:{}, level:{}", event.getThreadName(),
    34. event.getLoggerName(), filterReply.name(), level);
    35. return filterReply;
    36. }
    37. }

    java打印日志

    1. public void TestLog() {
    2. String customLogId = "123456789";
    3. MDC.put("customLogId", customLogId);
    4. log.info("customLogId={}, logTest start success!", customLogId);
    5. log.info("111111111111111111111111111111111111111111111111");
    6. log.info("customLogId={}, logTest end success!", customLogId);
    7. MDC.clear();
    8. }

    logback的XML配置:

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

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

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

    1. <appender name="CUSTOMLOGFILE" class="ch.qos.logback.classic.sift.SiftingAppender">
    2. <filter class="com.***.***.filter.LogFilter"/>
    3. <discriminator>
    4. <key>customLogIdkey>
    5. <defaultValue>unknowndefaultValue>
    6. discriminator>
    7. <sift>
    8. <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    9. <file>${log_dir}/custom/${customLogId}.logfile>
    10. <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    11. <fileNamePattern>${log_dir}/custom/%d{yyyy-MM-dd}/${customLogId}.%i.logfileNamePattern>
    12. <maxHistory>2maxHistory>
    13. <maxFileSize>2KBmaxFileSize>
    14. <totalSizeCap>5KBtotalSizeCap>
    15. <cleanHistoryOnStart>truecleanHistoryOnStart>
    16. rollingPolicy>
    17. <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
    18. <providers>
    19. <pattern>
    20. <pattern>
    21. {
    22. "time": "%d{yyyy-MM-dd HH:mm:ss.SSS}",
    23. "level": "%level",
    24. "thread": "%thread",
    25. "class": "%logger{40}",
    26. "message": "%msg",
    27. "stack_trace": "%exception{10}"
    28. }
    29. pattern>
    30. <charset>utf8charset>
    31. pattern>
    32. providers>
    33. encoder>
    34. appender>
    35. sift>
    36. 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中使用。

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

    %d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread] %-5level %logger{35} - %msg%n

     ${log_dir}/custom/%d{yyyy-MM-dd}/${customLogId}.%i.log

    这段话要注意一下:

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

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

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

    1. public RollingCalendar(String datePattern) {
    2. super();
    3. this.datePattern = datePattern;
    4. this.periodicityType = computePeriodicityType();
    5. }
    6. public PeriodicityType computePeriodicityType() {
    7. GregorianCalendar calendar = new GregorianCalendar(GMT_TIMEZONE, Locale.getDefault());
    8. // set sate to 1970-01-01 00:00:00 GMT
    9. Date epoch = new Date(0);
    10. if (datePattern != null) {
    11. for (PeriodicityType i : PeriodicityType.VALID_ORDERED_LIST) {
    12. SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
    13. simpleDateFormat.setTimeZone(GMT_TIMEZONE); // all date formatting done in GMT
    14. String r0 = simpleDateFormat.format(epoch);
    15. Date next = innerGetEndOfThisPeriod(calendar, i, epoch);
    16. String r1 = simpleDateFormat.format(next);
    17. // System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
    18. if ((r0 != null) && (r1 != null) && !r0.equals(r1)) {
    19. return i;
    20. }
    21. }
    22. }
    23. // we failed
    24. return PeriodicityType.ERRONEOUS;
    25. }

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

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

  • 相关阅读:
    vue前端实现分页功能
    【重识云原生】第四章云网络4.7.4节vhost-user方案——virtio的DPDK卸载方案
    docker入门加实战—docker常见命令
    python 比较时间 删除mysql数据
    动手学深度学习—批量规范化(代码详解)
    Java语言程序设计-关键术语(第一弹)
    JQuery笔记
    如何解决跨域问题
    通义千问, 文心一言, ChatGLM, GPT-4, Llama2, DevOps 能力评测
    Go Web——Gin简介
  • 原文地址:https://blog.csdn.net/qq_28772075/article/details/132626967