Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Spring Boot Actuator's Trace does a good job of capturing input/output HTTP params, headers, users, etc. I'd like to expand it to also capture the body of the HTTP response, that way I can have a full view of what is coming in and going out of the the web layer. Looking at the TraceProperties, doesn't look like there is a way to configure response body capturing. Is there a "safe" way to capture the response body without messing up whatever character stream it is sending back?

like image 685
SergeyB Avatar asked Mar 07 '16 16:03

SergeyB


People also ask

How can we expose custom endpoints in spring boot?

To create a custom actuator endpoints, Use @Endpoint annotation on a class. Then leverage @ReadOperation / @WriteOperation / @DeleteOperation annotations on the methods to expose them as actuator endpoint bean as needed.

How do I enable actuators in spring boot?

To enable Spring Boot actuator endpoints to your Spring Boot application, we need to add the Spring Boot Starter actuator dependency in our build configuration file. Maven users can add the below dependency in your pom. xml file. Gradle users can add the below dependency in your build.


1 Answers

Recently, I wrote a blog post about customization of Spring Boot Actuator's trace endpoint and while playing with Actuator, I was kinda surprised that response body isn't one of the supported properties to trace.

I thought I may need this feature and came up with a quick solution thanks to Logback's TeeFilter.

To duplicate output stream of the response, I copied and used TeeHttpServletResponse and TeeServletOutputStream without too much examination.

Then, just like I explained in the blog post, extended WebRequestTraceFilter like:

@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;
    }
}

Now, you can see responseBody in the JSON trace endpoint serves.

like image 50
sedooe Avatar answered Oct 02 '22 19:10

sedooe