본문 바로가기

STUDY/Spring

Spring Boot | Request 마다 로그 찍기

HandlerInterceptor

HandlerInterceptor 인터페이스를 구현하는 방법.
preHandle()의 반환 값을 true로 설정한다.

@Slf4j
@Component
public class CustomRequestInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpServletRequest requestCacheWrapperObject = new ContentCachingRequestWrapper(request);
        requestCacheWrapperObject.getParameterMap();

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

HandlerInterceptorAdapter는 deprecated되었기 때문에 HandlerInterceptor를 구현한다.

ContentCachingRequestWrapper를 사용한 이유는 request data를 읽고, 캐시하도록 하기 위함이다. 요청 값 input stream을 읽고 캐시해두어 로깅할 수 있도록 한다. 응답 값을 로깅하기 위해서는 ContentCachingResponseWrapper를 사용할 수 있다.


그리고 인터셉터를 등록해준다.
addPathPatterns()로 특정 URI를 등록할 수 있다.

@RequiredArgsConstructor
@Configuration
public class WebConfig implements WebMvcConfigurer {

    private final CustomRequestInterceptor requestInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(requestInterceptor)
            .addPathPatterns(Arrays.asList("/api/**"));
    }

}

스프링에서 제공하는 CommonsRequestLoggingFilter를 빈으로 등록해 로깅을 활성화 한다.

@Configuration
public class RequestLoggingFilterConfig {

    @Bean
    public CommonsRequestLoggingFilter logFilter() {
        CommonsRequestLoggingFilter filter
          = new CommonsRequestLoggingFilter();
        filter.setIncludeQueryString(true);
        filter.setIncludePayload(true);
        filter.setMaxPayloadLength(10000);
        filter.setIncludeHeaders(false);
        filter.setAfterMessagePrefix("REQUEST DATA : ");
        return filter;
    }
}

마지막으로 로그 설정을 해주면 끝이다. 레벨은 DEBUG로 해야 한다.

<!-- logback-spring.xml -->

<logger name="org.springframework.web.filter.CommonsRequestLoggingFilter" level="DEBUG" />

logback-spring.xml을 사용하지 않으면, application.yml파일에 간단히 설정하는 것도 가능하다.

# application.yml
logging:
    level:
        org.spring.framework.web.filter.CommonsRequestLoggingFilter: DEBUG

참고 Spring – Log Incoming Requests





OncePerRequestFilter

OncePerRequestFilter를 추가하는 방법.
OncePerRequestFilter는 요청당 딱 한 번만 필터를 실행한다.

@Slf4j
@Component
public class RequestAndResponseLoggingFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 로깅 처리
    }
}

두 개의 OncePerRequestFilter를 추가할 경우

@Order로 먼저 적용될 순서를 정한다.

@Component
@Order(2)
public class RequestAndResponseLoggingFilter extends OncePerRequestFilter { ...


@Component
@Order(1)
public class CustomAuthorizationFilter extends OncePerRequestFilter { ...