求助:Micrometer MeterRegistryCustomizer的Deny规则为何不生效?
问题根源与解决方案
你之前的配置完全没用,因为**MeterFilter是用来过滤Micrometer指标(Metrics)的,而你要拦截的是追踪(Trace/Span)数据**——这俩是Spring Boot里完全独立的模块,Jaeger接收的是追踪数据,和指标无关,所以之前的配置对追踪流程没有任何影响。
下面是针对Spring Boot 3.x + Micrometer Tracing对接Jaeger的正确解决方案:
方案1:Spring Boot配置直接排除端点(最简单)
Spring Boot的Micrometer Tracing提供了原生配置项,可以直接忽略指定路径的追踪,在application.yml(或application.properties)中添加:
management: tracing: ignore: patterns: "/actuator/**", "/health/**", "/metrics/**", "/favicon.ico", "/prometheus" # 可选:保持采样率,按需调整 sampling: probability: 1.0
如果想用代码配置替代配置文件:
import org.springframework.boot.actuate.autoconfigure.tracing.TracingProperties import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Configuration @Configuration @EnableConfigurationProperties(TracingProperties::class) class TracingConfig(tracingProperties: TracingProperties) { init { tracingProperties.ignore.patterns = listOf( "/actuator/**", "/health/**", "/metrics/**", "/favicon.ico", "/prometheus" ) } }
方案2:自定义SpanProcessor过滤Span(更灵活)
如果需要更复杂的过滤逻辑,可以自定义SpanProcessor,在Span结束前判断是否要上报到Jaeger:
import io.micrometer.tracing.Span import io.micrometer.tracing.SpanProcessor import org.springframework.stereotype.Component @Component class ExcludeActuatorSpanProcessor : SpanProcessor { private val excludedPrefixes = listOf( "/actuator/", "/health/", "/metrics/", "/favicon.ico", "/prometheus" ) override fun onStart(span: Span) {} override fun onEnd(span: Span) { val requestUri = span.tag("uri") ?: return if (excludedPrefixes.any { requestUri.startsWith(it) }) { // 标记Span为不导出,Jaeger会忽略这个Span span.context().put("otel.span.not.record", "true") } } override fun isAsyncStarted(): Boolean = false }
方案3:WebFilter拦截请求,跳过追踪
针对Web请求,直接在请求进入时判断路径,不创建追踪Span:
import jakarta.servlet.FilterChain import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse import org.springframework.web.filter.OncePerRequestFilter class ExcludeActuatorTracingFilter : OncePerRequestFilter() { private val excludedPrefixes = listOf( "/actuator/", "/health/", "/metrics/", "/favicon.ico", "/prometheus" ) override fun doFilterInternal( request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain ) { val requestUri = request.requestURI if (excludedPrefixes.any { requestUri.startsWith(it) }) { // 跳过追踪流程,直接执行后续逻辑 filterChain.doFilter(request, response) return } // 正常执行,创建追踪Span filterChain.doFilter(request, response) } }
注册这个Filter(优先级要高于默认的追踪Filter):
import org.springframework.boot.web.servlet.FilterRegistrationBean import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class FilterConfig { @Bean fun excludeActuatorTracingFilter(): FilterRegistrationBean<ExcludeActuatorTracingFilter> { val registration = FilterRegistrationBean(ExcludeActuatorTracingFilter()) registration.addUrlPatterns("/*") // 优先级设为-100,确保在追踪Filter之前执行 registration.order = -100 return registration } }
内容的提问来源于stack exchange,提问作者Arnaldo Cícero Bezerra
相关产品推荐
相关产品推荐

