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

Micrometer WebMvcTagsContributor生产环境无法添加自定义标签排查

问题:Spring Boot生产环境下Micrometer自定义路径变量标签不生效

背景

我使用Spring Boot(Java 16)开发时,尝试为Micrometer生成的指标添加请求路径变量作为自定义标签。经调研,创建WebMvcTagsContributor类型的Bean可实现该需求,以下是实现代码:

自定义WebMvcTagsContributor实现

public class CustomWebMvcTagsContributor implements WebMvcTagsContributor {

  private static int PRINT_ERROR_COUNTER = 0;

  @Override
  public Iterable<Tag> getTags(HttpServletRequest request, HttpServletResponse response,
      Object handler,
      Throwable exception) {
    return Tags.of(getAllTags(request));
  }

  private static List<Tag> getAllTags(HttpServletRequest request) {

    Object attributesMapObject = request.getAttribute(View.PATH_VARIABLES);
    if (isNull(attributesMapObject)) {
      attributesMapObject = request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);

      if (isNull(attributesMapObject)) {
        attributesMapObject = extractPathVariablesFromURI(request);
      }
    }

    if (nonNull(attributesMapObject)) {
      return getPathVariablesTags(attributesMapObject);
    }

    return List.of();
  }

  private static Object extractPathVariablesFromURI(HttpServletRequest request) {
    Long currentUserId = SecurityUtils.getCurrentUserId().orElse(null);
    try {
      URI uri = new URI(request.getRequestURI());
      String path = uri.getPath(); //get the path
      UriTemplate uriTemplate = new UriTemplate((String) request.getAttribute(
          HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)); //create template
      return uriTemplate.match(path); //extract values form template
    } catch (Exception e) {
        log.warn("[Error on 3rd attempt]", e);
    }

    return null;
  }

  private static List<Tag> getPathVariablesTags(Object attributesMapObject) {
    try {
      Long currentUserId = SecurityUtils.getCurrentUserId().orElse(null);

      if (nonNull(attributesMapObject)) {
        var attributesMap = (Map<String, Object>) attributesMapObject;
        List<Tag> tags = attributesMap.entrySet().stream()
            .map(stringObjectEntry -> Tag.of(stringObjectEntry.getKey(),
                String.valueOf(stringObjectEntry.getValue())))
            .toList();

          log.warn("[CustomTags] [{}]", CommonUtils.toJson(tags));
        return tags;
      }
    } catch (Exception e) {
      if (PRINT_ERROR_COUNTER < 5) {
        log.error("[Error while getting attributes map object]", e);
        PRINT_ERROR_COUNTER++;
      }
    }
    return List.of();
  }

  @Override
  public Iterable<Tag> getLongRequestTags(HttpServletRequest request, Object handler) {
    return null;
  }
}

Bean配置代码

@Bean
public WebMvcTagsContributor webMvcTagsContributor() {
  return new CustomWebMvcTagsContributor();
}

本地与生产表现差异

  • 本地测试项目正常,指标包含自定义路径变量标签:
http_server_requests_seconds_count {exception="None", method="GET",id="123",outcome="Success",status="200",test="test",uri="/test/{id}/compute/{test}",)1.0
  • 生产环境(独立的大型应用)仅生成默认指标,无自定义标签:
http_server_requests_seconds_count {exception="None", method="GET",outcome="Success",status="200",uri="/api/{something}/test",)1.0

已尝试的无效方案

  • 改用实现WebMvcTagsProvider的Bean:本地正常,但生产环境带路径变量的端点无法生成指标;
  • 添加日志查看自定义标签内容:无日志输出(已排除当前用户ID相关影响)。

排查方向建议

  • Bean加载验证:检查生产环境中CustomWebMvcTagsContributor是否被Spring容器正确初始化。可在Bean构造函数添加初始化日志,或通过Spring Boot Actuator的/beans端点确认Bean存在性;
  • 请求属性差异检查:生产环境可能存在额外过滤器、拦截器(如网关、安全组件),导致View.PATH_VARIABLES、HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE等请求属性丢失。在getAllTags方法开头打印所有请求属性,对比本地与生产的差异;
  • 依赖版本一致性:确认生产环境的Micrometer、Spring Boot版本与本地完全一致,避免版本差异导致接口逻辑不兼容或依赖冲突;
  • 端点类型兼容性:检查生产环境出现问题的端点是否为异步处理、特殊映射类型,这类场景可能导致路径变量属性未被正确设置;
  • 日志级别调整:生产环境日志级别可能高于本地(如仅打印ERROR),导致自定义代码中的WARN日志无法输出。临时调整日志级别至WARN/DEBUG,确认自定义代码是否被执行;
  • Bean优先级检查:生产环境可能存在其他WebMvcTagsContributor或WebMvcTagsProvider实现Bean,覆盖了自定义Bean。可给自定义Bean添加@Primary注解提升优先级,或检查容器中同类型Bean的数量;
  • 路径变量提取逻辑排查:在extractPathVariablesFromURI方法中添加更详细的异常日志,确认生产环境中该方法是否因URI格式、BEST_MATCHING_PATTERN_ATTRIBUTE值异常而执行失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 21:35:16