현재 회사는 모듈들이 다 나눠져 있습니다. 그리고 현재 제가 맡은 모듈은 다른 모듈과 통신할 때 HTTP 통신을 사용하고 있죠.
그러다보니 RestClient를 사용해 HTTP 통신을 하면서 4xx, 5xx 에러 로그를 남기고 싶었습니다.
로그를 남기지 않으니 문제를 파악하기가 너무 어렵더라구요.
실제 HTTP 요청을 수행하는 클라이언트 구현체입니다.
@Slf4j
@Component
@RequiredArgsConstructor
public class RestClientHttpClient implements HttpClient {
private final RestClient restClient;
private final RestClientErrorHandler errorHandler;
private final RestClientExceptionHandler exceptionHandler;
@Override
public <T> T post(String url, Object request, Class<T> responseType, UUID transactionId) {
return exceptionHandler.executeWithExceptionHandling(
() -> restClient.post()
.uri(url)
.body(request)
.retrieve()
.onStatus(HttpStatusCode::isError, errorHandler.createErrorHandler(transactionId))
.body(responseType),
transactionId
);
}
}
RestClient 호출 시 발생하는 네트워크 레벨 예외를 처리합니다.
@Slf4j
@Component
public class RestClientExceptionHandler {
public <T> T executeWithExceptionHandling(Supplier<T> apiCall, UUID transactionId) {
try {
return apiCall.get();
} catch (ResourceAccessException e) {
return handleNetworkError(e, transactionId);
} catch (RestClientException e) {
return handleRestClientError(e, transactionId);
}
}
private <T> T handleNetworkError(ResourceAccessException e, UUID transactionId) {
LOGGER.info("[{}] Network error: {}", transactionId, e.getMessage(), e);
throw new BaseBusinessException(
MessageSourceUtil.getMessage(
"conductor-service.workflow.http.network-error",
new Object[]{transactionId}
)
);
}
private <T> T handleRestClientError(RestClientException e, UUID transactionId) {
LOGGER.info("[{}] RestClient error: {}", transactionId, e.getMessage(), e);
throw new BaseBusinessException(
MessageSourceUtil.getMessage(
"conductor-service.workflow.http.client-error",
new Object[]{transactionId}
)
);
}
}