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

Spring Boot中@Valid验证失败时如何生成失败链路追踪?

问题

我希望在请求负载的@Valid验证失败时生成失败的链路追踪。以下是相关代码:

控制器代码

@Autowired MyService myService;

@PostMapping("/validate")
String question(@Valid @RequestBody SomeRequest someRequest) {
    System.out.println(someRequest);
    myService.business(someRequest);
    return "foo";
}

请求实体定义

import jakarta.validation.constraints.Email;

@ValidSomeRequest
public record SomeRequest(@Email String email, int score, String fieldPositive, String fieldZeroAndNegative) { }

自定义校验器实现

@Override
@Observed(name = "Validate.timed", contextualName = "Validate.span", lowCardinalityKeyValues = {"getValidation", "getValidation"})
public boolean isValid(SomeRequest request, ConstraintValidatorContext context) {
    if (request == null) {
        return true; // 交给@NotNull处理null情况
    }

    boolean isValid = true;
    context.disableDefaultConstraintViolation(); // 禁用默认提示信息

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }

    if (request.score() > 0) {
        // 当score为正数时,fieldPositive不能为空,fieldZeroAndNegative必须为null
        if (request.fieldPositive() == null || request.fieldPositive().isEmpty()) {
            isValid = false;
            context.buildConstraintViolationWithTemplate("score为正数时fieldPositive不能为空")
                    .addPropertyNode("fieldPositive")
                    .addConstraintViolation();
        }
        if (request.fieldZeroAndNegative() != null) {
            isValid = false;
            context.buildConstraintViolationWithTemplate("score为正数时fieldZeroAndNegative必须为null")
                    .addPropertyNode("fieldZeroAndNegative")
                    .addConstraintViolation();
        }
    }

    return isValid;
}

验证通过时能看到正常的链路追踪,但验证失败时没有错误链路,我希望能看到失败追踪效果,请问我遗漏了什么配置或代码?


解决方案

问题出在以下几个关键点,对应修复步骤如下:

  • 自定义校验器的@Observed注解未标记失败状态
    当前注解仅记录了校验耗时,但未区分验证成功/失败的状态。修改注解,通过status参数根据返回值标记结果:

    @Observed(
        name = "Validate.timed",
        contextualName = "Validate.span",
        lowCardinalityKeyValues = {"getValidation", "getValidation"},
        status = "${#return ? 'SUCCESS' : 'FAILURE'}"
    )
    

    这样链路追踪系统会根据校验结果标记Span状态,失败时会被识别为错误链路。

  • Spring Validation异常未被链路追踪捕获
    当@Valid验证失败时,Spring会抛出MethodArgumentNotValidException,默认情况下该异常可能未被追踪框架(如Micrometer Tracing)捕获。需自定义全局异常处理器,手动将异常标记到当前Span:

    @RestControllerAdvice
    public class ValidationExceptionHandler {
    
        private final Tracer tracer;
    
        public ValidationExceptionHandler(Tracer tracer) {
            this.tracer = tracer;
        }
    
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
            // 将当前Span标记为错误状态
            tracer.currentSpan().error(ex);
            // 构建错误响应
            Map<String, String> errors = new HashMap<>();
            ex.getBindingResult().getAllErrors().forEach(error -> {
                String fieldName = ((FieldError) error).getField();
                String errorMessage = error.getDefaultMessage();
                errors.put(fieldName, errorMessage);
            });
            return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
        }
    }
    
  • 检查链路追踪配置是否开启异常捕获
    确保追踪框架配置中开启了Spring MVC异常追踪,以Micrometer Tracing为例,在application.yml中添加:

    management:
      tracing:
        sampling:
          probability: 1.0 # 全量采样,便于调试
        propagation:
          type: B3
      metrics:
        tags:
          application: your-app-name
    

    全量采样可确保所有请求(包括验证失败的请求)都被追踪。

  • 可选:自定义校验器中明确标记错误
    若需要更精细的错误追踪,可在校验失败时调用tracer.currentSpan().error()手动标记,但更推荐通过@Observed的status参数实现,符合Validation规范。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:13:19