Spring REST 로깅

  • Spring Web RestTemplate을 이용한 HTTP 통신시 Interceptor를 활용하여 요청과 응답 로그를 남긴다.
  • 주의할 점은, ResponseEntity의 Body는 Stream 이므로 로깅 인터셉터에서 Body Stream을 읽어 소비가되면 실제 비즈니스 로직에서는 Body가 없어진다.
  • 이를 해결하기 위해 RestTemplate Bean 설정에서 requestFactory에 BufferingClientHttpRequestFactory를 세팅해줘야 한다.

설정

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    ...

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
        return restTemplateBuilder
                // 로깅 인터셉터에서 Stream을 소비하므로 BufferingClientHttpRequestFactory 을 꼭 써야한다.
                .requestFactory(() -> new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()))
                // 타임아웃 설정 (ms 단위)
                .setConnectTimeout(30000)
                .setReadTimeout(30000)
                // UTF-8 인코딩으로 메시지 컨버터 추가
                .additionalMessageConverters(new StringHttpMessageConverter(Charset.forName("UTF-8")))
                // 로깅 인터셉터 설정
                .additionalInterceptors(new RestTemplateLoggingRequestInterceptor())
                .build();
    }

    ...
}

RestTemplateLoggingInterceptor

/**
 * Spring RestTemplate 로깅 인터셉터
 *
 * @author Hoonmaro
 */
@Slf4j
public class RestTemplateLoggingRequestInterceptor implements ClientHttpRequestInterceptor {

    /**
     * <pre>
     * RestTemplate 로깅 Interceptor
     *
     * <pre>
     *
     * @param request HttpRequest
     * @param body Request Body
     * @param execution ClientHttpRequestExecution
     * @throws IOException
     */
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {

        // request log
        URI uri = request.getURI();
        traceRequest(request, body);

        // execute
        ClientHttpResponse response = execution.execute(request, body);

        // response log
        traceResponse(response, uri);
        return response;
    }

    /**
     * <pre>
     * RestTemplate Request 로깅
     *
     * <pre>
     * @param request HttpRequest
     * @param body Request Body
     */
    private void traceRequest(HttpRequest request, byte[] body) {
        StringBuilder reqLog = new StringBuilder();
        reqLog.append("[REQUEST] ")
        .append("Uri : ").append(request.getURI())
        .append(", Method : ").append(request.getMethod())
        .append(", Request Body : ").append(new String(body, StandardCharsets.UTF_8));
        log.info(reqLog.toString());
    }

    /**
     * <pre>
     * RestTemplate Response 로깅
     *
     * <pre>
     * @param response ClientHttpResponse
     * @throws IOException
     */
    private void traceResponse(ClientHttpResponse response, URI uri) throws IOException {
        StringBuilder resLog = new StringBuilder();
        resLog.append("[RESPONSE] ")
        .append("Uri : ").append(uri)
        .append(", Status code : ").append(response.getStatusCode())
        .append(", Response Body : ").append(StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8));
        log.info(resLog.toString());
    }
}

+ Recent posts