You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Logback实现特定Logger9-17点Info级、其余时段Warning级?

Logback实现按时间段切换特定Logger日志级别

Logback原生没有提供基于时间的日志级别动态切换功能,不过可以通过两种自定义方案实现需求:

方案一:自定义TurboFilter(实时判断时间过滤)

TurboFilter是Logback中优先级最高的过滤器,能在日志事件生成前进行判断,适合这种需要实时根据时间动态过滤的场景。

1. 编写自定义TurboFilter类

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.core.spi.FilterReply;
import java.time.LocalTime;

public class TimeBasedLevelFilter extends TurboFilter {
    // 目标Logger的名称(支持子Logger匹配)
    private String targetLoggerName;
    // 工作时段开始时间,默认9:00
    private LocalTime startTime = LocalTime.of(9, 0);
    // 工作时段结束时间,默认17:00
    private LocalTime endTime = LocalTime.of(17, 0);
    // 工作时段允许的最低日志级别
    private Level workingLevel = Level.INFO;
    // 非工作时段允许的最低日志级别
    private Level nonWorkingLevel = Level.WARN;

    @Override
    public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
        // 只处理目标Logger及其子Logger,其他日志直接放行
        if (!logger.getName().startsWith(targetLoggerName)) {
            return FilterReply.NEUTRAL;
        }

        LocalTime now = LocalTime.now();
        // 判断当前是否处于工作时段
        boolean isWorkingHours = now.isAfter(startTime) && now.isBefore(endTime);
        Level allowedLevel = isWorkingHours ? workingLevel : nonWorkingLevel;

        // 日志级别高于等于允许级别则放行,否则拒绝
        return level.isGreaterOrEqual(allowedLevel) ? FilterReply.ACCEPT : FilterReply.DENY;
    }

    // 提供setter方法,供Logback配置文件注入参数
    public void setTargetLoggerName(String targetLoggerName) {
        this.targetLoggerName = targetLoggerName;
    }

    public void setStartTime(String startTime) {
        this.startTime = LocalTime.parse(startTime);
    }

    public void setEndTime(String endTime) {
        this.endTime = LocalTime.parse(endTime);
    }

    public void setWorkingLevel(String workingLevel) {
        this.workingLevel = Level.valueOf(workingLevel);
    }

    public void setNonWorkingLevel(String nonWorkingLevel) {
        this.nonWorkingLevel = Level.valueOf(nonWorkingLevel);
    }
}

2. 在Logback配置文件中注册过滤器

修改logback.xml(或logback-spring.xml),添加自定义过滤器配置:

<configuration>
    <!-- 注册自定义时间级别过滤器 -->
    <turboFilter class="com.yourpackage.TimeBasedLevelFilter">
        <!-- 指定要控制的目标Logger,例如com.example.myapp -->
        <targetLoggerName>com.example.myapp</targetLoggerName>
        <!-- 工作时段开始时间,格式HH:mm -->
        <startTime>09:00</startTime>
        <!-- 工作时段结束时间 -->
        <endTime>17:00</endTime>
        <!-- 工作时段允许的最低日志级别 -->
        <workingLevel>INFO</workingLevel>
        <!-- 非工作时段允许的最低日志级别 -->
        <nonWorkingLevel>WARN</nonWorkingLevel>
    </turboFilter>

    <!-- 常规Appender配置示例 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- Root Logger配置 -->
    <root level="DEBUG">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>

方案二:定时切换Logger级别(修改Logger配置)

通过定时任务每天在指定时间修改目标Logger的级别,逻辑更直观。

1. 编写定时任务类

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import org.slf4j.LoggerFactory;
import java.time.LocalTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class LogLevelScheduler {
    public static void setupScheduledLogLevelChange(String targetLoggerName) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        Logger targetLogger = loggerContext.getLogger(targetLoggerName);

        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

        // 计算距离下一个9点的延迟时间
        LocalTime now = LocalTime.now();
        LocalTime nineOClock = LocalTime.of(9, 0);
        long initialDelayToNine = now.isBefore(nineOClock)
                ? calculateDelay(now, nineOClock)
                : TimeUnit.DAYS.toMillis(1) - calculateDelay(nineOClock, now);

        // 每天9点将目标Logger级别设为INFO
        scheduler.scheduleAtFixedRate(
                () -> targetLogger.setLevel(Level.INFO),
                initialDelayToNine,
                TimeUnit.DAYS.toMillis(1),
                TimeUnit.MILLISECONDS
        );

        // 计算距离下一个17点的延迟时间
        LocalTime seventeenOClock = LocalTime.of(17, 0);
        long initialDelayToSeventeen = now.isBefore(seventeenOClock)
                ? calculateDelay(now, seventeenOClock)
                : TimeUnit.DAYS.toMillis(1) - calculateDelay(seventeenOClock, now);

        // 每天17点将目标Logger级别设为WARN
        scheduler.scheduleAtFixedRate(
                () -> targetLogger.setLevel(Level.WARN),
                initialDelayToSeventeen,
                TimeUnit.DAYS.toMillis(1),
                TimeUnit.MILLISECONDS
        );

        // 可选:在应用关闭时关闭线程池,避免内存泄漏
        Runtime.getRuntime().addShutdownHook(new Thread(scheduler::shutdown));
    }

    private static long calculateDelay(LocalTime start, LocalTime end) {
        return TimeUnit.HOURS.toMillis(end.getHour() - start.getHour())
                + TimeUnit.MINUTES.toMillis(end.getMinute() - start.getMinute())
                - TimeUnit.SECONDS.toMillis(start.getSecond())
                - start.getNano() / 1000000;
    }
}

2. 在应用启动时初始化定时任务

以Spring Boot应用为例,在启动类中调用初始化方法:

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
        // 给目标Logger设置定时级别切换
        LogLevelScheduler.setupScheduledLogLevelChange("com.example.myapp");
    }
}

两种方案对比

方案优点缺点
TurboFilter实时判断时间,精准度高;应用重启不影响需编写过滤器逻辑,需注意Filter执行顺序
定时切换逻辑直观,直接修改Logger配置应用重启后需重新初始化,重启后到触发点前级别可能不符合预期

注意事项

  • 自定义类的包路径要正确,确保Logback能加载到。
  • 使用TurboFilter时,它会优先于所有Appender执行,需避免影响其他Logger的日志输出。
  • 定时任务方案要处理好线程池的关闭,防止内存泄漏。

内容的提问来源于stack exchange,提问作者Kash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 05:35:24