background:
SpringBoot 3.1.0 - embedded tomcat
Sample: https://github.com/PerryZhao/spring-filter-error-lost-log-correlation-demo/tree/main
// Throw Exception in filter
public class MyFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// ...
throw new IllegalArgumentException("IllegalArgumentException");
}
}
// Customized ErrorController
public class MyErrorController extends AbstractErrorController {
@RequestMapping
public ResponseEntity<Map<String, Object>> handler(HttpServletRequest request) {
// ...
Object ex = request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
throw new MyErrorControllerException("requestInfo", (Throwable) ex, status);
}
}
// Customized ExceptionHandler
@ExceptionHandler(Throwable.class)
public ResponseEntity<MessageSourceResult> handler(Throwable ex, HttpServletRequest request, HttpServletResponse response) {
Observation observation = (Observation) request.getAttribute(ServerHttpObservationFilter.class.getName() + ".observation");
if (null != observation) {
** // If I want to get the traceId here, what should I do? Is the following code correct?
**
try (Observation.Scope scope = observation.openScope()) {
response.setHeader("X-B3-TraceId", tracer.currentTraceContext().context().traceId());
log.warn("Missing log correlation...");
// ...
}
}
}
ServerHttpObservationFilter invoked observation.stop() in the finally block
// org.springframework.web.filter.ServerHttpObservationFilter
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Observation observation = createOrFetchObservation(request, response);
try (Observation.Scope scope = observation.openScope()) {
filterChain.doFilter(request, response);
} catch (Exception ex) {
observation.error(unwrapServletException(ex));
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
throw ex;
} finally {
// Only stop Observation if async processing is done or has never been started.
if (!request.isAsyncStarted()) {
Throwable error = fetchException(request);
if (error != null) {
observation.error(error);
}
observation.stop();
}
}
}
Q: What happens if openScope after observation stopped?