为何被过滤的日志事件仍会导致Logback指标logback.events增长?
解决Micrometer Logback指标在过滤特定日志后仍增长的问题
你的问题核心在于Logback过滤器的执行顺序:Micrometer的MetricsTurboFilter是Turbo级别的过滤器,会在Appender的EvaluatorFilter之前触发,所以即使后者过滤了日志输出,前者已经完成了指标统计,导致logback.events仍会增长。
下面提供两种可行的解决方式:
方式一:自定义MetricsTurboFilter,在指标统计阶段排除目标日志
直接替换默认的MetricsTurboFilter,在它的日志判断逻辑中加入你的过滤规则,从根源上阻止这类日志被统计。
- 实现自定义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; } }
- 在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") && (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
相关产品推荐
相关产品推荐

