Spring

Error를 MatterMost로 받아보자!

Hasky96 2022. 4. 29. 00:31

결과!

MM으로 온 에러


사용환경

  • 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에 넣어서 사용합니다!