Spring
Error를 MatterMost로 받아보자!
Hasky96
2022. 4. 29. 00:31
결과!

사용환경
- SpringBoot(Gradle)
- MatterMost
* 코드이후에 웹훅 받아오는 법 있습니다
- build.gradle
//Mattermost
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
implementation 'org.apache.httpcomponents:httpcore:4.4.15'
implementation 'org.apache.httpcomponents:httpclient:4.5.13'
- Properties.java
- 알림에 대한 설정을 할 수 있는 페이지 입니다.
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
@Getter
@Setter
@ConfigurationProperties("notification.mattermost")
@Primary
public class MattermostProperties {
// 알림 켜고 끄기!
private boolean mmEnabled = true;
private String channel;
private String pretext;
private String color = "#ff5d52";
private String authorName = "server";
private String authorIcon;
private String title ;
private String text = "";
private String footer = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
}
- MessageDto.java
- 메세지 내용이 담기는 부분입니다.
import com.google.gson.annotations.SerializedName;
import lombok.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
public class MatterMostMessageDTO {
@Getter
public static class Attachments {
private Props props;
private List<Attachment> attachments;
public Attachments() {
attachments = new ArrayList<>();
}
public Attachments(List<Attachment> attachments) {
this.attachments = attachments;
}
public Attachments(Attachment attachment) {
this();
this.attachments.add(attachment);
}
public void addProps(Exception e) {
props = new Props(e);
}
}
@Getter
@AllArgsConstructor
@Builder
@ToString
public static class Attachment {
private String channel;
private String pretext;
private String color;
@SerializedName("author_name")
private String authorName;
@SerializedName("author_icon")
private String authorIcon;
private String title;
private String text;
private String footer;
public Attachment addExceptionInfo(Exception e) {
this.title = e.getClass().getSimpleName();
StringBuilder sb = new StringBuilder(text);
sb.append("\n").append("**Error Message**").append("\n").append("```").append(e.getMessage()).append("```")
.append("\n");
this.text = sb.toString();
return this;
}
public Attachment addExceptionInfo(Exception e, String uri) {
this.addExceptionInfo(e);
StringBuilder sb = new StringBuilder(text);
sb.append("\n").append("**Reqeust URL**").append("\n").append(uri).append("\n");
this.text = sb.toString();
return this;
}
public Attachment addExceptionInfo(Exception e, String uri, String params) {
this.addExceptionInfo(e, uri);
StringBuilder sb = new StringBuilder(text);
sb.append("\n").append("**Parameters**").append("\n").append(params.toString()).append("\n");
this.text = sb.toString();
return this;
}
}
@Getter
@NoArgsConstructor
public static class Props {
private String card;
public Props(Exception e) {
StringBuilder text = new StringBuilder();
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
text.append("**Stack Trace**").append("/n").append("```");
text.append(sw.toString().substring(0,
Math.min(5500, sw.toString().length())) + "/n...").append("/n");
this.card = text.toString();
}
}
}
- Sender.java
- MatterMostWebHookUrl을 통해 에러를 전송합니다.
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
@RequiredArgsConstructor
public class MatterMostSender {
private Logger log = LoggerFactory.getLogger(MatterMostSender.class);
private String webhookUrl= "{MatterMostWebHookUrl}";
// private RestTemplate restTemplate;
private final MattermostProperties mmProperties;
public void sendMessage(Exception excpetion, String uri, String params) {
if (!mmProperties.isMmEnabled())
return;
try {
MatterMostMessageDTO.Attachment attachment = MatterMostMessageDTO.Attachment.builder()
.channel(mmProperties.getChannel())
.authorIcon(mmProperties.getAuthorIcon())
.authorName(mmProperties.getAuthorName())
.color(mmProperties.getColor())
.pretext(mmProperties.getPretext())
.title(mmProperties.getTitle())
.text(mmProperties.getText())
.footer(mmProperties.getFooter())
.build();
attachment.addExceptionInfo(excpetion, uri, params);
MatterMostMessageDTO.Attachments attachments = new MatterMostMessageDTO.Attachments(attachment);
attachments.addProps(excpetion);
String payload = new Gson().toJson(attachments);
HttpHeaders headers = new HttpHeaders();
headers.set("Content-type", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> entity = new HttpEntity<>(payload, headers);
RestTemplate restTemplate = new RestTemplate();
restTemplate.postForEntity(webhookUrl, entity, String.class);
} catch (Exception e) {
log.error("#### ERROR!! Notification Manager : {}", e.getMessage());
}
}
}
- NotificationManager.java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class NotificationManager {
private Logger log = LoggerFactory.getLogger(NotificationManager.class);
@Autowired
private MatterMostSender mSender;
public void sendNotification(Exception e, String uri, String params) {
log.info("SEND Notification");
mSender.sendMessage(e, uri, params);
}
}
- ControllerAdvice
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
@ControllerAdvice
public class GlobalControllerAdvice {
@Autowired
private NotificationManager notificationManager;
@ExceptionHandler(Exception.class)
public ResponseEntity exceptionTest(Exception e, HttpServletRequest req) {
e.printStackTrace();
notificationManager.sendNotification(e, req.getRequestURI(), getParams(req));
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
private String getParams(HttpServletRequest req) {
StringBuilder params = new StringBuilder();
Enumeration<String> keys = req.getParameterNames();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
params.append("- ").append(key).append(" : ").append(req.getParameter(key)).append("/n");
}
return params.toString();
}
}
웹훅 만들기
1. MatterMost 왼쪽에 메뉴를 열어 통합창을 열어줍니다.

2. 통합에서 전체 Incoming Webhook으로 들어가 줍니다.

3. Incoming Webhook 추가하기를 눌러 Webhook을 제작합니다.

4.Sender.java에 넣어서 사용합니다!