如何在 Spring 引导执行器的跟踪中包含 JSON 响应 body?

How to include JSON response body in Spring Boot Actuator's Trace?

Spring Boot Actuator 的 Trace 在捕获 input/output HTTP 参数、headers、用户等方面做得很好。我想将其扩展到捕获 HTTP 响应的 body,这样我就可以全面了解 Web 层的传入和传出内容。查看 TraceProperties,似乎没有办法配置响应 body 捕获。有没有一种 "safe" 方法可以捕获响应 body 而不会弄乱它发回的任何字符流?

最近,我写了一篇 blog post 关于自定义 Spring Boot Actuator 的 trace 端点的文章,在使用 Actuator 时,我有点惊讶 response body 不是要跟踪的受支持属性之一。

我想我可能需要这个功能,并想出了一个快速的解决方案,感谢 Logback 的 TeeFilter

为了复制响应的输出流,我没有过多检查就复制并使用了TeeHttpServletResponse and TeeServletOutputStream

然后,就像我在博客 post 中解释的那样,将 WebRequestTraceFilter 扩展为:

@Component
public class RequestTraceFilter extends WebRequestTraceFilter {

    RequestTraceFilter(TraceRepository repository, TraceProperties properties) {
        super(repository, properties);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        TeeHttpServletResponse teeResponse = new TeeHttpServletResponse(response);

        filterChain.doFilter(request, teeResponse);

        teeResponse.finish();

        request.setAttribute("responseBody", teeResponse.getOutputBuffer());

        super.doFilterInternal(request, teeResponse, filterChain);
    }

    @Override
    protected Map<String, Object> getTrace(HttpServletRequest request) {
        Map<String, Object> trace = super.getTrace(request);

        byte[] outputBuffer = (byte[]) request.getAttribute("responseBody");

        if (outputBuffer != null) {
            trace.put("responseBody", new String(outputBuffer));
        }

        return trace;
    }
}

现在,您可以在 JSON trace 端点服务中看到 responseBody

来自 spring 维护者之一:

Tracing the request and response body has never been supported out of the box. Support for tracing parameters was dropped as, when the request is POSTed form data, it requires reading the entire request body.

https://github.com/spring-projects/spring-boot/issues/12953

使用 webflux 反应堆栈,可以使用 spring-cloud-gateway 捕获 http 请求和响应主体,并通过定义自定义 HttpTraceWebFilter 将它们注入执行器 httptrace

https://gist.github.com/gberche-orange/06c26477a313df9d19d20a4e115f079f

查看完整的相关代码

这需要相当多的重复,希望springboot团队能帮助减少这种重复,参见相关内容https://github.com/spring-projects/spring-boot/issues/23907