Skip to content

Commit 6747b3d

Browse files
authored
feat: logging 기능 & slack notification 리팩토링 (#294)
* refactor: 커스텀 에러 메시지가 보이도록 수정 * refactor: 로그 처리중 slack알림 보내도록 설정 * refactor: 중복 코드 제거 --------- Co-authored-by: 나용준 <141994188+youngJun99@users.noreply.github.com>
1 parent e1d93ce commit 6747b3d

File tree

4 files changed

+61
-27
lines changed

4 files changed

+61
-27
lines changed

src/main/java/ssu/eatssu/domain/slack/entity/SlackMessageFormat.java

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -73,23 +73,46 @@ public static String sendUserInquiry(Inquiry inquiry) {
7373
return messageFormat.format(args);
7474
}
7575

76-
77-
public static String sendServerError(BaseException ex) {
78-
MessageFormat messageFormat = new MessageFormat(
79-
"""
76+
public static String sendServerError(Throwable ex, String method, String uri, String userId, String args) {
77+
final String messageTemplate = """
8078
===================
8179
*서버 에러 발생*
82-
- 예외 상태코드: {0}
83-
- 예외 메시지: {1}
84-
- 개발환경: {2}
80+
- {0}: {1}
81+
- 예외 메시지: {2}
82+
- 개발환경: {3}
83+
*요청 정보*
84+
- HTTP Method: {4}
85+
- URI: {5}
86+
- User ID: {6}
87+
- 요청 파라미터: {7}
8588
===================
86-
"""
87-
);
88-
Object[] args = {
89-
ex.getStatus(),
90-
ex.getStatus().getMessage(),
89+
""";
90+
MessageFormat messageFormat = new MessageFormat(messageTemplate);
91+
92+
String errorTypeLabel;
93+
Object errorTypeValue;
94+
String errorMessage;
95+
96+
if (ex instanceof BaseException baseException) {
97+
errorTypeLabel = "예외 상태코드";
98+
errorTypeValue = baseException.getStatus();
99+
errorMessage = baseException.getStatus().getMessage();
100+
} else {
101+
errorTypeLabel = "예외 타입";
102+
errorTypeValue = ex.getClass().getSimpleName();
103+
errorMessage = ex.getMessage() != null ? ex.getMessage() : "메시지 없음";
104+
}
105+
106+
Object[] formatArgs = {
107+
errorTypeLabel,
108+
errorTypeValue,
109+
errorMessage,
91110
serverEnv,
111+
method,
112+
uri,
113+
userId,
114+
args != null && args.length() > 500 ? args.substring(0, 500) + "...(truncated)" : args
92115
};
93-
return messageFormat.format(args);
116+
return messageFormat.format(formatArgs);
94117
}
95118
}

src/main/java/ssu/eatssu/domain/slack/service/SlackErrorNotifier.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ public SlackErrorNotifier(SlackService slackService) {
1818
this.slackService = slackService;
1919
}
2020

21-
public void notify(BaseException ex) {
21+
public void notify(Throwable ex, String method, String uri, String userId, String args) {
2222
if (!"prod".equals(serverEnv)) {
2323
return;
2424
}
2525
try {
26-
String message = SlackMessageFormat.sendServerError(ex);
26+
String message = SlackMessageFormat.sendServerError(ex, method, uri, userId, args);
2727
slackService.sendSlackMessage(message, SlackChannel.SERVER_ERROR);
2828
} catch (Exception slackEx) {
2929
log.warn("슬랙 전송 실패: {}", slackEx.getMessage());

src/main/java/ssu/eatssu/global/handler/GlobalExceptionHandler.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,11 @@ public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
4646
*/
4747
@ExceptionHandler(BaseException.class)
4848
public ResponseEntity<BaseResponse<Void>> handleBaseException(BaseException e) {
49-
if (BaseResponseStatus.sendSlackNotification(e.getStatus())) {
50-
slackErrorNotifier.notify(e);
51-
}
5249
return ResponseEntity.status(e.getStatus().getHttpStatus()).body(BaseResponse.fail(e.getStatus()));
5350
}
5451

5552
@ExceptionHandler(Exception.class)
5653
public ResponseEntity<BaseResponse<Void>> handleAllUnhandledException(Exception ex) {
57-
slackErrorNotifier.notify(new BaseException(BaseResponseStatus.BAD_REQUEST));
5854
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
5955
.body(BaseResponse.fail(BaseResponseStatus.INTERNAL_SERVER_ERROR));
6056
}
@@ -241,10 +237,6 @@ protected ResponseEntity<Object> handleExceptionInternal(
241237

242238
HttpStatus status = HttpStatus.valueOf(statusCode.value());
243239

244-
if (status.is5xxServerError()) {
245-
slackErrorNotifier.notify(new BaseException(BaseResponseStatus.BAD_REQUEST));
246-
}
247-
248240
BaseResponseStatus responseStatus = status.is4xxClientError()
249241
? BaseResponseStatus.BAD_REQUEST
250242
: BaseResponseStatus.INTERNAL_SERVER_ERROR;

src/main/java/ssu/eatssu/global/log/ControllerLogAspect.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
import org.springframework.web.context.request.RequestContextHolder;
1515
import org.springframework.web.context.request.ServletRequestAttributes;
1616
import ssu.eatssu.domain.auth.security.CustomUserDetails;
17+
import ssu.eatssu.domain.slack.service.SlackErrorNotifier;
18+
import ssu.eatssu.global.handler.response.BaseException;
19+
import ssu.eatssu.global.handler.response.BaseResponseStatus;
1720
import ssu.eatssu.global.log.annotation.LogMask;
1821

1922
import java.lang.reflect.Field;
@@ -30,6 +33,7 @@
3033
public class ControllerLogAspect {
3134

3235
private final ObjectMapper objectMapper;
36+
private final SlackErrorNotifier slackErrorNotifier;
3337

3438
@Pointcut("within(@org.springframework.web.bind.annotation.RestController *)")
3539
public void restController() {}
@@ -48,14 +52,16 @@ public Object logApi(ProceedingJoinPoint joinPoint) throws Throwable {
4852
Object[] args = joinPoint.getArgs();
4953

5054
// 요청자
51-
String userIdLog = IntStream.range(0, args.length)
55+
String userId = IntStream.range(0, args.length)
5256
.filter(i -> args[i] instanceof CustomUserDetails)
5357
.mapToObj(i -> {
5458
CustomUserDetails user = (CustomUserDetails) args[i];
55-
return "userId=" + user.getId();
59+
return String.valueOf(user.getId());
5660
})
5761
.findFirst()
58-
.orElse("userId=anonymous");
62+
.orElse("anonymous");
63+
64+
String userIdLog = "userId=" + userId;
5965

6066
// 나머지 요청 인자
6167
String otherArgsJson = IntStream.range(0, args.length)
@@ -103,11 +109,24 @@ public Object logApi(ProceedingJoinPoint joinPoint) throws Throwable {
103109
return result;
104110
} catch (Throwable e) {
105111
long time = System.currentTimeMillis() - start;
106-
log.error("EXCEPTION {} {} ({} ms) cause={}", method, uri, time, e.getMessage(), e);
112+
String causeMessage = getCauseMessage(e);
113+
String exceptionType = e.getClass().getSimpleName();
114+
log.error("EXCEPTION {} {} ({} ms) type={} cause={}", method, uri, time, exceptionType, causeMessage, e);
115+
116+
slackErrorNotifier.notify(e, method, uri, userId, argsJson);
107117
throw e;
108118
}
109119
}
110120

121+
private String getCauseMessage(Throwable e) {
122+
if (e instanceof BaseException) {
123+
BaseException baseException = (BaseException) e;
124+
return baseException.getStatus().getMessage();
125+
}
126+
String message = e.getMessage();
127+
return message != null ? message : e.getClass().getSimpleName();
128+
}
129+
111130
private Map<String, Object> toSafeMap(Object arg) {
112131
Map<String, Object> result = new HashMap<>();
113132
for (Field field : arg.getClass().getDeclaredFields()) {

0 commit comments

Comments
 (0)