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

为何被过滤的日志事件仍会导致Logback指标logback.events增长?

解决Micrometer Logback指标在过滤特定日志后仍增长的问题

你的问题核心在于Logback过滤器的执行顺序:Micrometer的MetricsTurboFilter是Turbo级别的过滤器,会在Appender的EvaluatorFilter之前触发,所以即使后者过滤了日志输出,前者已经完成了指标统计,导致logback.events仍会增长。

下面提供两种可行的解决方式:

方式一:自定义MetricsTurboFilter,在指标统计阶段排除目标日志

直接替换默认的MetricsTurboFilter,在它的日志判断逻辑中加入你的过滤规则,从根源上阻止这类日志被统计。

  1. 实现自定义TurboFilter
import io.micrometer.core.instrument.binder.logging.MetricsTurboFilter;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.spi.FilterReply;
import org.slf4j.Marker;

public class FilteredMetricsTurboFilter extends MetricsTurboFilter {

    @Override
    public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
        // 先执行原有的指标统计逻辑
        FilterReply originalReply = super.decide(marker, logger, level, format, params, t);
        
        // 仅当原逻辑允许统计时,再检查是否需要排除
        if (originalReply == FilterReply.NEUTRAL) {
            if ("org.hibernate.engine.jdbc.spi.SqlExceptionHelper".equals(logger.getName())) {
                // 拼接完整的日志消息内容
                StringBuilder messageBuilder = new StringBuilder(format != null ? format : "");
                if (params != null) {
                    for (Object param : params) {
                        if (param instanceof String) {
                            messageBuilder.append(param);
                        } else if (param instanceof Throwable) {
                            messageBuilder.append(((Throwable) param).getMessage());
                        }
                    }
                }
                String message = messageBuilder.toString();
                // 匹配要排除的错误规则
                if (message.contains("duplicate key value violates unique constraint \"the_constraint_name\"") 
                    || message.contains("SQLState: 23505")) {
                    return FilterReply.DENY;
                }
            }
        }
        return originalReply;
    }
}
  1. 在Spring Boot中注册自定义Filter
    通过配置类替换默认的MetricsTurboFilter:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.micrometer.core.instrument.MeterRegistry;

@Configuration
public class LoggingMetricsConfig {

    @Bean
    public FilteredMetricsTurboFilter filteredMetricsTurboFilter(MeterRegistry meterRegistry) {
        FilteredMetricsTurboFilter filter = new FilteredMetricsTurboFilter();
        filter.setMeterRegistry(meterRegistry);
        return filter;
    }
}

方式二:将Appender Filter改为TurboFilter

把原来的EvaluatorFilter升级为Turbo级过滤器,让它在日志处理的最早期就终止请求,这样MetricsTurboFilter不会触发统计。

修改你的logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false">
    <!-- 新增TurboFilter,替代原Appender内的Filter -->
    <turboFilter class="ch.qos.logback.classic.turbo.EvaluatorFilter">
        <evaluator>
            <expression>return logger.equals("org.hibernate.engine.jdbc.spi.SqlExceptionHelper") &amp;&amp;
                (message.contains("duplicate key value violates unique constraint \"the_constraint_name\"") ||
                message.contains("SQLState: 23505"));</expression>
        </evaluator>
        <OnMatch>DENY</OnMatch>
    </turboFilter>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 移除原Appender内的Filter -->
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>

    <logger name="com.mypackage" level="DEBUG" additivity="false">
        <appender-ref ref="CONSOLE"/>
    </logger>
</configuration>

原理说明

Logback的过滤器执行优先级为:TurboFilter → Logger级别过滤 → Appender级Filter。MetricsTurboFilter属于Turbo级,会先于Appender的Filter执行。只要让目标日志在Turbo阶段就被过滤(返回DENY),整个日志请求会被直接终止,既不会输出到控制台,也不会被Micrometer统计。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:50:30