-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEAT] 예외 발생 시, Slack 채널에 메세지를 보내는 기능 추가 (#214)
* chore: slack 의존성 추가 및 불필요한 주석 제거 * chore: favicon error 해결을 위해 favicon.ico 추가 * feat: BusinessException 발생 시, Slack 채널에 메세지 보내는 기능 추가 - BusinessException 발생 시, Slack의 #exception-log 채널에 메세지를 보내는 기능 추가 - GlobalException에 대한 추가 처리도 필요 - .yml 파일에 slack 정보 추가 필요 - 스택 트레이스 가독성 개선 필요 * feat: Exception 발생 시 보내는 메세지 포멧 변경 - Exception 발생 시 전송하는 Slack 메세지에 예외 발생 시각 데이터 추가 * feat: 처리하지 않은 예외 외에 다른 예외 발생 시에도 Slack 메세지 보내도록 설정 * fix: prod 프로파일이 활성화되어 있을 때에만 메세지를 보내도록 설정 - Environment를 의존성 주입받아 prod(application-prod.yml) 프로파일이 활성화되어 있을 때에만 Slack 메세지를 보내도록 설정 - 각 ExceptionHandler가 MessageSender 인터페이스를 상속받고, sendSlackMessage() 메서드를 구현 - 테스트 및 개발 환경에서 Slack 메세지를 보내지 않는 점 확인
- Loading branch information
Showing
10 changed files
with
218 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 18 additions & 2 deletions
20
...l/exception/BusinessExceptionHandler.java → ...ion/handler/BusinessExceptionHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,38 @@ | ||
package com.genius.gitget.global.util.exception; | ||
package com.genius.gitget.global.util.exception.handler; | ||
|
||
import com.genius.gitget.global.util.exception.BusinessException; | ||
import com.genius.gitget.global.util.response.dto.CommonResponse; | ||
import com.genius.gitget.slack.service.SlackService; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.core.env.Environment; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
|
||
@Slf4j | ||
@RestControllerAdvice | ||
@RequiredArgsConstructor | ||
public class BusinessExceptionHandler { | ||
public class BusinessExceptionHandler implements MessageSender { | ||
private final Environment env; | ||
private final SlackService slackService; | ||
|
||
@ExceptionHandler(BusinessException.class) | ||
protected ResponseEntity<CommonResponse> globalBusinessExceptionHandler(BusinessException e) { | ||
log.error("[ERROR]" + e.getMessage(), e); | ||
sendSlackMessage(e); | ||
|
||
return ResponseEntity.badRequest().body( | ||
new CommonResponse(e.getStatus(), e.getMessage()) | ||
); | ||
} | ||
|
||
@Override | ||
public void sendSlackMessage(Exception exception) { | ||
if (!env.matchesProfiles("prod")) { | ||
return; | ||
} | ||
slackService.sendMessage(exception); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
src/main/java/com/genius/gitget/global/util/exception/handler/MessageSender.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.genius.gitget.global.util.exception.handler; | ||
|
||
public interface MessageSender { | ||
/** | ||
* 예외가 발생했을 때 Slack에 예외 발생에 대한 메세지를 보내는 메서드 | ||
* <p> | ||
* 주의 사항!! | ||
* 활성화 된 profile이 "prod"일 때에만 작동하도록 해야 합니다. | ||
* Environment의 matchProfiles()를 통해 특정 프로파일이 활성화되어 있는지 확인 가능 | ||
* if(!environment.matchesProfiles("prod")) return; | ||
* | ||
* @param exception 발생한 예외 | ||
*/ | ||
void sendSlackMessage(Exception exception); | ||
} |
61 changes: 61 additions & 0 deletions
61
src/main/java/com/genius/gitget/slack/service/SlackMessageUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package com.genius.gitget.slack.service; | ||
|
||
import static com.slack.api.model.block.Blocks.divider; | ||
import static com.slack.api.model.block.Blocks.section; | ||
import static com.slack.api.model.block.composition.BlockCompositions.markdownText; | ||
|
||
import com.genius.gitget.challenge.certification.util.DateUtil; | ||
import com.slack.api.model.Attachment; | ||
import com.slack.api.model.block.LayoutBlock; | ||
import com.slack.api.model.block.composition.TextObject; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class SlackMessageUtil { | ||
|
||
private static final String ERROR_TITLE = "*Exception 발생 시각:* "; | ||
private static final String ERROR_MESSAGE = "*Exception Message:*\n"; | ||
private static final String ERROR_STACK = "*Exception Stack:*\n"; | ||
private static final String FILTER_STRING = "gitget"; | ||
|
||
|
||
public static String createErrorTitle() { | ||
return ERROR_TITLE + DateUtil.getKstLocalTime(); | ||
} | ||
|
||
public static List<Attachment> createAttachments(String color, List<LayoutBlock> data) { | ||
List<Attachment> attachments = new ArrayList<>(); | ||
Attachment attachment = new Attachment(); | ||
attachment.setColor(color); | ||
attachment.setBlocks(data); | ||
attachments.add(attachment); | ||
return attachments; | ||
} | ||
|
||
public static List<LayoutBlock> createProdErrorMessage(Exception exception) { | ||
StackTraceElement[] stacks = exception.getStackTrace(); | ||
|
||
List<LayoutBlock> layoutBlockList = new ArrayList<>(); | ||
|
||
List<TextObject> sectionInFields = new ArrayList<>(); | ||
sectionInFields.add(markdownText(ERROR_MESSAGE + exception.getMessage())); | ||
sectionInFields.add(markdownText(ERROR_STACK + exception)); | ||
layoutBlockList.add(section(section -> section.fields(sectionInFields))); | ||
|
||
layoutBlockList.add(divider()); | ||
layoutBlockList.add(section(section -> section.text(markdownText(filterErrorStack(stacks))))); | ||
return layoutBlockList; | ||
} | ||
|
||
private static String filterErrorStack(StackTraceElement[] stacks) { | ||
StringBuilder stringBuilder = new StringBuilder(); | ||
stringBuilder.append("```"); | ||
for (StackTraceElement stack : stacks) { | ||
if (stack.toString().contains(FILTER_STRING)) { | ||
stringBuilder.append(stack).append("\n"); | ||
} | ||
} | ||
stringBuilder.append("```"); | ||
return stringBuilder.toString(); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/com/genius/gitget/slack/service/SlackService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.genius.gitget.slack.service; | ||
|
||
public interface SlackService { | ||
void sendMessage(String message); | ||
|
||
void sendMessage(Exception exception); | ||
} |
62 changes: 62 additions & 0 deletions
62
src/main/java/com/genius/gitget/slack/service/SlackServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package com.genius.gitget.slack.service; | ||
|
||
import com.slack.api.Slack; | ||
import com.slack.api.methods.MethodsClient; | ||
import com.slack.api.methods.SlackApiException; | ||
import com.slack.api.methods.request.chat.ChatPostMessageRequest; | ||
import com.slack.api.model.Attachment; | ||
import com.slack.api.model.block.LayoutBlock; | ||
import java.io.IOException; | ||
import java.util.List; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Slf4j | ||
@Service | ||
public class SlackServiceImpl implements SlackService { | ||
private static final String ATTACHMENTS_ERROR_COLOR = "#eb4034"; | ||
@Value("${slack.token}") | ||
private String token; | ||
@Value("${slack.channel}") | ||
private String channel; | ||
|
||
@Override | ||
public void sendMessage(String message) { | ||
try { | ||
MethodsClient methods = Slack.getInstance().methods(token); | ||
ChatPostMessageRequest request = ChatPostMessageRequest.builder() | ||
.channel(channel) | ||
.text(message) | ||
.build(); | ||
|
||
methods.chatPostMessage(request); | ||
|
||
} catch (SlackApiException | IOException e) { | ||
log.error(e.getMessage()); | ||
} | ||
} | ||
|
||
@Override | ||
public void sendMessage(Exception exception) { | ||
try { | ||
String errorTitle = SlackMessageUtil.createErrorTitle(); | ||
List<LayoutBlock> layoutBlocks = SlackMessageUtil.createProdErrorMessage(exception); | ||
List<Attachment> attachments = SlackMessageUtil.createAttachments(ATTACHMENTS_ERROR_COLOR, | ||
layoutBlocks); | ||
|
||
MethodsClient methods = Slack.getInstance().methods(token); | ||
ChatPostMessageRequest request = ChatPostMessageRequest.builder() | ||
.channel(channel) | ||
.attachments(attachments) | ||
.text(errorTitle) | ||
.build(); | ||
|
||
methods.chatPostMessage(request); | ||
log.info("slack 메세지 전송 성공"); | ||
|
||
} catch (SlackApiException | IOException e) { | ||
log.error(e.getMessage()); | ||
} | ||
} | ||
} |
Binary file not shown.