diff --git a/api/common-api/src/main/java/kr/ac/kookmin/stream/GlobalExceptionHandler.java b/api/common-api/src/main/java/kr/ac/kookmin/stream/GlobalExceptionHandler.java new file mode 100644 index 0000000..de1e702 --- /dev/null +++ b/api/common-api/src/main/java/kr/ac/kookmin/stream/GlobalExceptionHandler.java @@ -0,0 +1,48 @@ +package kr.ac.kookmin.stream; + +import static kr.ac.kookmin.stream.logging.MdcKeys.REQUEST_ID; +import static kr.ac.kookmin.stream.logging.MdcKeys.USER_ID; + +import kr.ac.kookmin.stream.common.BusinessException; +import kr.ac.kookmin.stream.common.CommonErrorCode; +import kr.ac.kookmin.stream.common.ErrorStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + @ExceptionHandler(BusinessException.class) + public ResponseEntity> handleBusiness(BusinessException e) { + log.warn("[requestId={}, userId={}] ({}) {}", + MDC.get(REQUEST_ID), MDC.get(USER_ID), e.getErrorCode().name(), e.getMessage()); + return ResponseEntity.status(e.getErrorCode().status()).body(ApiResponse.error(e)); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity> handleValidation(MethodArgumentNotValidException e) { + String message = e.getBindingResult().getFieldErrors().stream() + .findFirst().map(FieldError::getDefaultMessage) + .orElse(CommonErrorCode.INVALID_INPUT.message()); + log.warn("[requestId={}, userId={}] (INVALID_INPUT) {}", + MDC.get(REQUEST_ID), MDC.get(USER_ID), message); + return ResponseEntity.status(CommonErrorCode.INVALID_INPUT.status()) + .body(ApiResponse.error(CommonErrorCode.INVALID_INPUT.name(), message)); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity> handleInternal(Exception e) { + log.error("[requestId={}, userId={}] {}", + MDC.get(REQUEST_ID), MDC.get(USER_ID), e.getMessage(), e); + return ResponseEntity.status(ErrorStatus.INTERNAL_SERVER_ERROR) + .body(ApiResponse.error(CommonErrorCode.INTERNAL_SERVER_ERROR)); + } +} diff --git a/gateway/logging/src/main/java/kr/ac/kookmin/stream/logging/MdcKeys.java b/gateway/logging/src/main/java/kr/ac/kookmin/stream/logging/MdcKeys.java new file mode 100644 index 0000000..661a38e --- /dev/null +++ b/gateway/logging/src/main/java/kr/ac/kookmin/stream/logging/MdcKeys.java @@ -0,0 +1,11 @@ +package kr.ac.kookmin.stream.logging; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class MdcKeys { + + public static final String REQUEST_ID = "requestId"; + public static final String USER_ID = "userId"; +}