[Tistory] [Spring] 프로젝트 협업 툴 디스코드 연동해서 에러 메세지 받아보기 (Feat. feign, logback.xml)

원글 페이지 : 바로가기

이번에 팝콘메이트 하면서 통신할 때 에러 코드나 짤막한 에러 원인을 받아 볼 수 있게 하였는데, 그 정보들만 가지고 원인을 해결하지 못할 때가 있다 보니 리팩토링 할 겸 팀 공용 디스코드에 로그 전체를 볼 수 있는 시스템을 만들어 보려고 한다 먼저 팀이 사용하는 디스코드에서 웹후크를 만들려면 채널 설정 -> 연동 들어가서 웹후크 만들기를 누르면 된다! 간단한 작업이다 본격적으로 코드 구현에 대해 알아보자 (1) FeignClient 이용하는 방식 먼저 DiscordClient 클래스에 Controller 클래스에 메서드 짜주는 것처럼 인터셉터를 위한 메서드를 써준다 @FeignClient(
name = “discord-client”,
url = “웹후크 URL”,
configuration = DiscordFeignConfig.class)
public interface DiscordClient {

@PostMapping
void sendAlarm(@RequestBody DiscordMessage message);
} 그다음에 DiscordFeignConfig에다가 intercept하기 위한 Bean을 등록해 준다 public class DiscordFeignConfig{

@Bean
public RequestInterceptor requestInterceptor() {
return template -> template.header(“Content-Type”, “application/json;charset=UTF-8”);
}
} Discord 공식 문서에 나와있는 요청 바디는 {
“content”: “string”
“embeds”: [
{
“title”: “string”
“description”: “string”
},

]
} 이런 식으로 되어있어서 DTO 또한 똑같이 만들어 주었다 @Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class DiscordMessage {

private String content;
private List embeds;

@Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public static class Embed {

private String title;
private String description;
}
} 나는 따로 ErrorHandlerResponse를 만들어서 쓰고 있기 때문에 GlobalExceptionHandler이라는 파일을 따로 만들어서 사용하고 있어 통신할 때 처리해 주는 메서드에 “sendDiscordAlarm”메서드를 만들어 호출해 주었다 @ExceptionHandler(BaseErrorException.class)
public ResponseEntity handleBaseErrorException(
BaseErrorException e, HttpServletRequest request) {
log.error(“BaseErrorException”, e);
final ErrorReason errorReason = e.getErrorCode().getErrorReason();
final ErrorResponse errorResponse = ErrorResponse.from(errorReason);
if (!Arrays.asList(environment.getActiveProfiles()).contains(“local”)) {
sendDiscordAlarm(e, request);
}
return ResponseEntity.status(HttpStatus.valueOf(errorReason.getStatus()))
.body(errorResponse);
}

private void sendDiscordAlarm(Exception e, WebRequest request) {
discordClient.sendAlarm(createMessage(e, request));
}

private DiscordMessage createMessage(Exception e, WebRequest request) {
return DiscordMessage.builder()
.content(“# 🚨 에러 발생 🚨”)
.embeds(
List.of(
DiscordMessage.Embed.builder()
.title(“ℹ️ 정보”)
.description(
“### 🕖 발생 시간\n”
+ LocalDateTime.now()
+ “\n”
+ “### 🔗 요청 URL\n”
+ createRequestFullPath(request)
+ “\n”
+ “### 📄 Stack Trace\n”
+ ““`\n”
+ getStackTrace(e).substring(0, 1000)
+ “\n“`”)
.build()
)
)
.build();
}
private String createRequestFullPath(WebRequest webRequest) {
HttpServletRequest request = ((ServletWebRequest) webRequest).getRequest();
String fullPath = request.getMethod() + ” ” + request.getRequestURL();

String queryString = request.getQueryString();
if (queryString != null) {
fullPath += “?” + queryString;
}

return fullPath;
}

private String getStackTrace(Exception e) {
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
} 여기서 중요한 점은 spring Profile을 사용하고 있다면 local에서 테스트하는 에러 로그들을 굳이 모두가 보는 디스코드 채널에 보낼 필요가 없으니 꼭 local profile이 아닐 때를 고려해서 코드를 짜줘야 한다!! if (!Arrays.asList(environment.getActiveProfiles()).contains(“local”)) {
sendDiscordAlarm(e, request);
} + 디스코드 채널의 HTTP 연결 허용을 꼭 해줘야 한다. 안 한다면 401 에러가 난다! 하지만 이렇게 Intercept방식으로 하면 통신할 때 쓰는 에러 Response까지 바뀌게 된다.. 그래서 그냥 Discord LogBack 형식으로 바꿔서 해보았다 (2) LogBack 방식 위에 디스코드 웹훅 성정은 그대로지만 이번엔 LogBack.xml파일을 설정해주어야 한다 Api 모듈의 Resource 디렉터리에 logback.xml파일을 만들어 주었다









웹후크URL
%d{HH:mm:ss} [%thread] [%-5level] %logger{36} – %msg%n“`%ex{full}“`
에러 비상 비상
https://velog.velcdn.com/images/sangyoung23/post/d0e62103-e8d8-4a2e-955f-d5a27137044e/image.png
false



${CONSOLE_LOG_PATTERN}
utf8




ERROR






나는 특히 Spring Profile을 “애용”하고 있는 개발자로서 logback에 spring profile을 지원해 주는 점이 너무 좋았다 이 파일만 추가해 주면 디스코드에 이런 식으로 자세한 로그까지 오는 것을 볼 수 있다 결론 Feign을 이용하는 방법보다 디스코드의 logback형식이 훨씬 더 리소스를 잡아먹지도 않고 나처럼 디스코드 연동 처음 해보는 사람한테 엄청 편할 것 같다 하지만 Feign의 장점으로는 굳이 gradle library를 사용할 필요 없이 api로 통신하면 되는 것이라서 케이스 바이 케이스라는 말이 항상 맞는 것 같다! 대규모 팀 프로젝트나 인원이 많을 때 특히 이러한 협업 툴 연동이 정말 유용할 것 같아 적용해 보았다 출처 https://velog.io/@qwe916/Discord%EB%A1%9C-Spring-Logback-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0 Discord로 Spring Logback 설정하기 Logback이란 log4j 이후에 출시된 Java 기반 Logging Framework 중 하나로 가장 널리 사용되고 있다. SLF4j 의 구현체이며 Spring Boot 환경이라면 별도의 dependency 추가 없이 기본적으로 포함되어 있다.application. velog.io + Feign으로 디스코드 연동하는 부분은 이 분 블로그 참고하면서 도움 많이 되었다 https://velog.io/@eomgerm/AvAb-Spring-Discord-Webhook%EC%9C%BC%EB%A1%9C-%EC%97%90%EB%9F%AC-%EC%83%81%ED%99%A9-%EC%95%8C%EB%A6%BC-%EB%B0%9B%EA%B8%B0 [AvAb] Spring + Discord Webhook으로 에러 상황 알림 받기 아브아브의 데모데이도 얼마 남지 않았습니다. 서버는 얼추 기능 개발이 종료되고 리팩터링할 것들을 찾아보고 있는데요. 그 중에서 프런트엔드와 소통하면서 겪었던 문제 상황을 자동화해 보 velog.io

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다