spring 如果观察停止后openScope会发生什么?(过滤器错误的日志相关性缺失)

ep6jt1vc  于 2023-06-21  发布在  Spring
关注(0)|答案(1)|浏览(106)

**后台:**SpringBoot 3.1.0 -内嵌tomcat

样本:https://github.com/PerryZhao/spring-filter-error-lost-log-correlation-demo/tree/main
//在过滤器中抛出异常

public class MyFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
      // ...
      throw new IllegalArgumentException("IllegalArgumentException");
    }
}

//自定义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); 
    }
}

//自定义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在finally块中调用了observation.stop()

// 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:如果观察停止后openScope会发生什么?

6jjcrrmo

6jjcrrmo1#

Spring MVC中的整个请求处理都发生在ServerHttpObservationFilter打开的范围内。不需要打开新的作用域,因为当前观察已经在作用域中。从跟踪程序中获取traceId就足够了。

相关问题