diff --git a/module-api/src/main/java/com/mile/exception/handler/GlobalExceptionHandler.java b/module-api/src/main/java/com/mile/exception/handler/GlobalExceptionHandler.java index 5ac7ab7c..cedb19f4 100644 --- a/module-api/src/main/java/com/mile/exception/handler/GlobalExceptionHandler.java +++ b/module-api/src/main/java/com/mile/exception/handler/GlobalExceptionHandler.java @@ -9,6 +9,7 @@ import com.mile.exception.model.NotFoundException; import com.mile.exception.model.TooManyRequestException; import com.mile.exception.model.UnauthorizedException; +import com.mile.slack.module.SendErrorModule; import io.sentry.Sentry; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; @@ -31,22 +32,25 @@ public class GlobalExceptionHandler { private static final int INDEX_ZERO = 0; + private final SendErrorModule sendErrorModule; + + public GlobalExceptionHandler(SendErrorModule sendErrorModule) { + this.sendErrorModule = sendErrorModule; + } @ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity handleHttpMessageNotReadableException(final HttpMessageNotReadableException e) { - Sentry.captureException(e); + ; return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ErrorResponse.of(ErrorMessage.ENUM_VALUE_BAD_REQUEST)); } @ExceptionHandler(HandlerMethodValidationException.class) public ResponseEntity handleHandlerMethodValidationException(final HandlerMethodValidationException e) { - Sentry.captureException(e); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ErrorResponse.of(HttpStatus.BAD_REQUEST.value(), Objects.requireNonNull(e.getAllValidationResults().get(INDEX_ZERO).getResolvableErrors().get(INDEX_ZERO).getDefaultMessage()))); } @ExceptionHandler(MethodArgumentTypeMismatchException.class) public ResponseEntity handleMethodArgumentTypeMismatchException(final MethodArgumentTypeMismatchException e) { - Sentry.captureException(e); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ErrorResponse.of(ErrorMessage.REQUEST_URL_WRONG_ERROR)); } @@ -58,13 +62,11 @@ public ResponseEntity handleBadRequestException(final BadRequestE @ExceptionHandler(UnauthorizedException.class) public ResponseEntity handleUnauthorizedException(final UnauthorizedException e) { - Sentry.captureException(e); return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ErrorResponse.of(e.getErrorMessage())); } @ExceptionHandler(JwtValidationException.class) public ResponseEntity handleJwtValidationException(final JwtValidationException e) { - Sentry.captureException(e); return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ErrorResponse.of(e.getErrorMessage())); } @@ -92,25 +94,21 @@ protected ResponseEntity handleMethodArgumentNotValidException(fi @ExceptionHandler(ForbiddenException.class) public ResponseEntity handleForbiddenException(final ForbiddenException e) { - Sentry.captureException(e); return ResponseEntity.status(HttpStatus.FORBIDDEN).body(ErrorResponse.of(e.getErrorMessage())); } @ExceptionHandler(NotFoundException.class) public ResponseEntity handleNotFoundException(final NotFoundException e) { - Sentry.captureException(e); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ErrorResponse.of(e.getErrorMessage())); } @ExceptionHandler(ConflictException.class) public ResponseEntity handleConflictException(final ConflictException e) { - Sentry.captureException(e); return ResponseEntity.status(HttpStatus.CONFLICT).body(ErrorResponse.of(e.getErrorMessage())); } @ExceptionHandler(TooManyRequestException.class) public ResponseEntity handleTooManyRequestException(final TooManyRequestException e) { - Sentry.captureException(e); return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body(ErrorResponse.of(e.getErrorMessage())); } @@ -121,7 +119,8 @@ public ResponseEntity handleNoHandlerFoundException(final NoHandl @ExceptionHandler(Exception.class) protected ResponseEntity handleException(final Exception error, final HttpServletRequest request) { - Sentry.captureException(error); + sendErrorModule.sendError(error); + log.error("================================================NEW==============================================="); log.error(error.getMessage(), error); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ErrorResponse.of(ErrorMessage.INTERNAL_SERVER_ERROR)); diff --git a/module-domain/src/main/java/com/mile/common/CacheService.java b/module-domain/src/main/java/com/mile/common/CacheService.java index 7bce197e..5f6463e6 100644 --- a/module-domain/src/main/java/com/mile/common/CacheService.java +++ b/module-domain/src/main/java/com/mile/common/CacheService.java @@ -1,6 +1,5 @@ package com.mile.common; -import com.mile.slack.module.SendMessageModule; import lombok.RequiredArgsConstructor; import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; @@ -11,10 +10,8 @@ public class CacheService { private final String MOIM_CACHE_NAME = "moimPopularInfo"; private final CacheManager cacheManager; - private final SendMessageModule sendMessageModule; public void deleteMoimCache() { - sendMessageModule.sendMessage("INTERNAL API 호출) 글모임 별 인기 글/ 작가에 대한 캐시 삭제 완료"); if (cacheManager.getCache(MOIM_CACHE_NAME) != null) { cacheManager.getCache(MOIM_CACHE_NAME).clear(); } diff --git a/module-external/src/main/java/com/mile/slack/module/SendErrorModule.java b/module-external/src/main/java/com/mile/slack/module/SendErrorModule.java new file mode 100644 index 00000000..4af0269c --- /dev/null +++ b/module-external/src/main/java/com/mile/slack/module/SendErrorModule.java @@ -0,0 +1,59 @@ +package com.mile.slack.module; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.MDC; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; + +@Slf4j +@Component +public class SendErrorModule extends SendWebhookMessage { + private final StringBuilder sb = new StringBuilder(); + + @Value("${webhook.url-for-error}") + private String webHookUri; + + @Value("${spring.profiles.active}") + private String profile; + + @Override + public void sendError(@NonNull final Exception exception) { + WebClient webClient = WebClient.builder() + .baseUrl(webHookUri).build(); + + + webClient.post() + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(generateMessage(exception)) + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(String.class) + .doOnError(e -> log.error("WEB HOOK 전송 중 에러 발생 -> {}", e.getMessage())) + .subscribe(); + } + + + private String readRootStackTrace(Exception error) { + return error.getStackTrace()[0].toString(); + } + + private Message generateMessage(final Exception exception) { + sb.append("🚨 ERROR🚨").append("\n").append(exception.toString()).append("\n").append("\n"); + sb.append("🏃🏻PROFILE🏃🏻").append("\n").append(profile).append("\n").append("\n"); + sb.append("🆔REQUEST ID🆔").append("\n").append(MDC.get("request_id")).append("\n").append("\n"); + sb.append("️✏️DETAILS✏️").append("\n").append(readRootStackTrace(exception)).append("\n"); + + return new Message(sb.toString()); + } + + @Getter + @AllArgsConstructor + private class Message { + private String text; + } +} diff --git a/module-external/src/main/java/com/mile/slack/module/SendMessageModule.java b/module-external/src/main/java/com/mile/slack/module/SendMessageModule.java index 6b8b2e4d..7f2f4f8f 100644 --- a/module-external/src/main/java/com/mile/slack/module/SendMessageModule.java +++ b/module-external/src/main/java/com/mile/slack/module/SendMessageModule.java @@ -16,7 +16,7 @@ @Component @Slf4j -public class SendMessageModule implements SendWebhookMessage { +public class SendMessageModule extends SendWebhookMessage { private final StringBuilder sb = new StringBuilder(); @Value("${webhook.url-for-event}") diff --git a/module-external/src/main/java/com/mile/slack/module/SendWebhookMessage.java b/module-external/src/main/java/com/mile/slack/module/SendWebhookMessage.java index ae4f1e2e..f227c1dd 100644 --- a/module-external/src/main/java/com/mile/slack/module/SendWebhookMessage.java +++ b/module-external/src/main/java/com/mile/slack/module/SendWebhookMessage.java @@ -1,8 +1,10 @@ package com.mile.slack.module; -import org.springframework.lang.NonNull; - -public interface SendWebhookMessage { - void sendMessage(@NonNull final String message); - +public abstract class SendWebhookMessage { + void sendMessage(String message) { + // TODO() - 상속받아 구현하기 + } + void sendError(Exception exception){ + // TODO() - 상속받아 구현하기 + } }