Affects: 6.0.3 (6.0.x)
With the current version (6.0.3) (and Boot 3.1), if I throw out an error from an MVC controller method and if I have an @ExceptionHandler
, the error is not reported to the observation, i.e.: observation.error(...)
is not called.
The issue is reproducible with a simple Boot project (initializer) and adding a @RestController
with an error handler:
@GetMapping("/")
public String trouble() {
throw new IllegalStateException("Noooooo!");
}
@ExceptionHandler(Throwable.class)
ProblemDetail handleThrowable(HttpServletRequest request, Throwable error) {
ProblemDetail problemDetail = ProblemDetail.forStatus(INTERNAL_SERVER_ERROR);
problemDetail.setTitle(INTERNAL_SERVER_ERROR.getReasonPhrase());
problemDetail.setDetail(error.toString());
return problemDetail;
}
After I call the endpoint and see the error response (500), if I check the metrics (or traces), I can see that the exception was never reported to the observation (e.g.: by checking the /actuator/metrics
endpoint of the tracing backend).
Here's what I see in the metrics endpoint (I simplified the JOSN):
exception: [ "none" ]
method: [ "GET" ]
error: [ "none" ]
uri: [ "/" ]
outcome: [ "SERVER_ERROR" ]
status: [ "500" ]
Both the exception
and the error
tags should contain the error (IllegalStateException
) but they don't.
After debugging this, I think the issue is that the exception attribute is not set in mvc, if I set it manually in the @ExceptionHandler
, the error is reported as expected:
request.setAttribute(ERROR_EXCEPTION_ATTRIBUTE, error);
If you need a reproducer on top of the initializer link and the snippets, you can use apps in micrometer-samples repo, e.g.: this one or this one but they already contain the workaround you need to remove it.
Comment From: jonatan-ivanov
I think this is slightly related to https://github.com/spring-projects/spring-framework/issues/29398.
Comment From: bclozel
This was originally done on purpose in Spring Boot, as developers often handle business exceptions and handle them at the web layer, but don't consider those as "errors" in the observability sense. For example, a missing user profile results in a 404 but you probably don't want to clutter your dashboards with those errors just because a 404 happened. Right now, only exceptions that are bubbling up to the servlet filter are recorded as errors.
At the Spring MVC/WebFlux level, it's hard to know if an error can be considered worthy of an observation key-value, since we only know that an error has been handled at the MVC level, or not. With the ProblemDetail
support, error handling is somehow expanded and we can reconsider this approach.
Currently, we advise developers to register exceptions with the observation directly.
Comment From: jonatan-ivanov
I see. Can we have a section about this both in Boot's and Framework's docs (or Boot can just link to Framework's)? Since if the users want to observe and report errors happening in their apps they have a choice of not having a custom error handler or implement one. In the first case, they will bump into https://github.com/spring-projects/spring-framework/issues/29398, in the second case, the problem that is described above.