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
相关产品推荐
相关产品推荐

