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());
}
}