Source Code Tracing — How to log all requests and responses

Jeffrey Chen
3 min readJun 5, 2020

--

I am trying to log all requests and responses in our Spring Boot service. After the source code tracing, I decided to implement it by add a custom filter. I will share the experience in this post.

A trivial way to log the requests and response is write a log at the beginning and the end in your controller, but it’s too annoying to add it in every controllers and it’s also hard to update. So, the most common ways to do that are using Filter or Interceptor. You can figure out the difference between those two from here. However, the request will go through the filters before the interceptors like following chart.

In each layer of the above flow, the http request and response may be changed. So, let’s check the behavior of Spring Boot to find out an ideal place to insert our logging implementation.

When the service be launched, Sprig will scan all AbstractFilterRegistrationBean and create relative filter beans. Then, it will create interceptor beans based on the setting in all WebMvcConfiguration. In other hand, you can register you custom filter by

and add your custom interceptor by

After the service has been launched successfully, users can send the requests to the service. The filter chain will be created dynamically in org.apache.catalina.core.ApplicationFilterFactory.

In our case, the filter chain includes following filters. We use Spring Security in our service so springSecurityFilterChain is included and wsMappingFilter is our custom filter which used to validate the request. Others are default included.

[characterEncodingFilter, webMvcMetricsFilter, tracingFilter, exceptionLoggingFilter, hiddenHttpMethodFilter, formContentFilter, requestContextFilter, springSecurityFilterChain, corsFilter, httpTraceFilter, wsMappingFilter, Tomcat WebSocket (JSR356) Filter]

After the filter chain, Spring will create HandlerExecutionChain (interceptor chain) in org.springframework.web.servlet.DispatcherServlet.

In our case, the interceptor chain includes following interceptors. LoginInterceptor is our custom interceptor and others are default included.

[LoginInterceptor, WebRequestHandlerInterceptorAdapter, LongTaskTimingHandlerInterceptor, SpanCustomizingAsyncHandlerInterceptor, ConversionServiceExposingInterceptor, ResourceUrlProviderExposingInterceptor]

By checking those filters and interceptors, we figured our the responses may come from 4 place in our case.

1. The response defined in our controller.

2. The response in our custom filter.

3. The response in springSecurityFilterChain

4. The common error response in BasicErrorController for un-catch exception.

So, our final solution is create a custom logging filter and insert it in front of springSecurityFilterChain. You can find our detailed implementation here.

The solution may be different by the filters and interceptors you used in your project. So, try to follow this flow and analyze where the responses may come from. Based on the analysis result, you can find out the ideal place for your logging solution.

--

--

Jeffrey Chen

Software engineer who’s dream is to become an athletes