diff --git a/src/main/java/kr/co/mcmp/softwarecatalog/common/service/RabbitMqAlertService.java b/src/main/java/kr/co/mcmp/softwarecatalog/common/service/RabbitMqAlertService.java index 4fcb676..c1e419c 100644 --- a/src/main/java/kr/co/mcmp/softwarecatalog/common/service/RabbitMqAlertService.java +++ b/src/main/java/kr/co/mcmp/softwarecatalog/common/service/RabbitMqAlertService.java @@ -1,5 +1,6 @@ package kr.co.mcmp.softwarecatalog.common.service; +import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -11,6 +12,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; +import org.springframework.web.util.UriComponentsBuilder; + +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * RabbitMQ를 통한 알람 전송 서비스 @@ -36,10 +43,7 @@ public class RabbitMqAlertService { @Value("${rabbitmq.alert.password:mc-agent}") private String password; - - @Value("${rabbitmq.alert.slack-channel-id:#kubernetes-alerts}") - private String defaultSlackChannelId; - + public RabbitMqAlertService() { this.restTemplate = new RestTemplate(); this.objectMapper = new ObjectMapper(); @@ -57,42 +61,43 @@ public RabbitMqAlertService() { public boolean sendScaleOutAlert(String title, String message, String channelName, String recipients) { try { // RabbitMQ HTTP API URL 생성 (담당자 예시에 맞춤) - String url = String.format("http://%s:%s/api/exchanges/%%2F%s/amq.default/publish", + String url = String.format("http://%s:%s/api/exchanges/%%2f%s/alert-manual.exchange/publish", rabbitmqUrl, rabbitmqPort, vhost); - - log.info("Sending alert to RabbitMQ: {}", url); + + URI uri = UriComponentsBuilder.fromHttpUrl(url) + .build(true) + .toUri(); + + log.info("Sending alert to RabbitMQ: {}", uri.toString()); // 알람 메시지 생성 AlertMessage alertMessage = new AlertMessage(); alertMessage.setTitle(title); alertMessage.setMessage(message); alertMessage.setChannelName(channelName); - alertMessage.setRecipients(recipients); + alertMessage.setRecipients(List.of(recipients)); // JSON 문자열로 변환 String payload = objectMapper.writeValueAsString(alertMessage); - + log.info("Alert payload: {}", payload); + // RabbitMQ 요청 본문 생성 RabbitMqRequest request = new RabbitMqRequest(); - request.setRoutingKey("alert.queue"); // 담당자 예시에 맞춤 + request.setRoutingKey("alert-manual.queue"); // 담당자 예시에 맞춤 request.setPayload(payload); request.setPayloadEncoding("string"); - - String requestBody = objectMapper.writeValueAsString(request); - - log.info("Alert payload: {}", payload); - log.info("RabbitMQ request body: {}", requestBody); + log.info("RabbitMQ request body: {}", request); // HTTP 요청 헤더 설정 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBasicAuth(username, password); - HttpEntity entity = new HttpEntity<>(requestBody, headers); + HttpEntity entity = new HttpEntity<>(request, headers); // RabbitMQ에 POST 요청 org.springframework.http.ResponseEntity response = restTemplate.exchange( - url, + uri, HttpMethod.POST, entity, String.class @@ -119,7 +124,7 @@ public static class AlertMessage { private String title; private String message; private String channelName; - private String recipients; + private List recipients; // Getters and Setters public String getTitle() { return title; } @@ -131,22 +136,24 @@ public static class AlertMessage { public String getChannelName() { return channelName; } public void setChannelName(String channelName) { this.channelName = channelName; } - public String getRecipients() { return recipients; } - public void setRecipients(String recipients) { this.recipients = recipients; } + public List getRecipients() { return recipients; } + public void setRecipients(List recipients) { this.recipients = recipients; } } /** * RabbitMQ HTTP API 요청 DTO */ public static class RabbitMqRequest { - private Object properties = new Object(); + private Map properties = new HashMap<>(); + @JsonProperty("routing_key") private String routingKey; private String payload; + @JsonProperty("payload_encoding") private String payloadEncoding; // Getters and Setters public Object getProperties() { return properties; } - public void setProperties(Object properties) { this.properties = properties; } + public void setProperties(Object properties) { this.properties = (Map) properties; } public String getRoutingKey() { return routingKey; } public void setRoutingKey(String routingKey) { this.routingKey = routingKey; } diff --git a/src/main/java/kr/co/mcmp/softwarecatalog/kubernetes/service/KubernetesMonitoringService.java b/src/main/java/kr/co/mcmp/softwarecatalog/kubernetes/service/KubernetesMonitoringService.java index 55c385b..d2588f1 100644 --- a/src/main/java/kr/co/mcmp/softwarecatalog/kubernetes/service/KubernetesMonitoringService.java +++ b/src/main/java/kr/co/mcmp/softwarecatalog/kubernetes/service/KubernetesMonitoringService.java @@ -11,6 +11,8 @@ import java.util.Objects; import java.util.stream.Collectors; +import kr.co.mcmp.softwarecatalog.SoftwareCatalog; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -70,6 +72,14 @@ public class KubernetesMonitoringService { @Value("${k8s.autoscaling.test-memory-threshold:0.1}") private double testMemoryThreshold; + @Value("${rabbitmq.alert.slack-channel-id}") + private String defaultSlackChannelId; + @Value("${rabbitmq.alert.email}") + private String defaultEmail; + @Value("${rabbitmq.alert.sms-phonenumber}") + private String defaultSmsPhonenumber; + @Value("${rabbitmq.alert.kakao-phonenumber}") + private String defaultKakaoPhonenumber; @Scheduled(fixedRate = 60000) // 1분마다 실행 public void monitorKubernetesResources() { @@ -927,21 +937,55 @@ private void sendScaleOutCompletedAlert(DeploymentHistory deployment, int newNod "Application '%s' has been successfully scaled out to %d nodes in cluster '%s' (namespace: %s).", appName, newNodeCount, clusterName, namespace ); - + // Slack 채널로 알람 전송 (환경변수에서 채널 ID 가져오기) - String recipients = System.getenv("ALERT_SLACK_CHANNEL_ID"); - if (recipients == null) { - recipients = "#kubernetes-alerts"; // 기본값 + String recipients = defaultSlackChannelId; + if (StringUtils.isNotBlank(recipients)) { + boolean sent = rabbitMqAlertService.sendScaleOutAlert(title, message, "slack", recipients); + if (sent) { + log.info("Scale out alert (slack) sent successfully for {} to {} nodes", appName, newNodeCount); + } else { + log.warn("Failed to send scale out alert (slack) for {}", appName); + } } - - boolean sent = rabbitMqAlertService.sendScaleOutAlert(title, message, "slack", recipients); - - if (sent) { - log.info("Scale out alert sent successfully for {} to {} nodes", appName, newNodeCount); - } else { - log.warn("Failed to send scale out alert for {}", appName); + + // Email + recipients = defaultEmail; + if (StringUtils.isNotBlank(recipients)) { + boolean sent = rabbitMqAlertService.sendScaleOutAlert(title, message, "email", recipients); + if (sent) { + log.info("Scale out alert (email) sent successfully for {} to {} nodes", appName, newNodeCount); + } else { + log.warn("Failed to send scale out alert (email) for {}", appName); + } } - + + // SMS - 글자제약으로 메시지 내용 축약 + recipients = defaultSmsPhonenumber; + String smsTitle = String.format("Scale-out OK. %s", appName); + String smsMessage = String.format("Node: %d, Cluster: '%s', NS: %s", + newNodeCount, clusterName, namespace + ); + if (StringUtils.isNotBlank(recipients)) { + boolean sent = rabbitMqAlertService.sendScaleOutAlert(smsTitle, smsMessage, "sms", recipients); + if (sent) { + log.info("Scale out alert (sms) sent successfully for {} to {} nodes", appName, newNodeCount); + } else { + log.warn("Failed to send scale out alert (sms) for {}", appName); + } + } + + // kako + recipients = defaultKakaoPhonenumber; + if (StringUtils.isNotBlank(recipients)) { + boolean sent = rabbitMqAlertService.sendScaleOutAlert(title, message, "kakao", recipients); + if (sent) { + log.info("Scale out alert (kakao) sent successfully for {} to {} nodes", appName, newNodeCount); + } else { + log.warn("Failed to send scale out alert (kakao) for {}", appName); + } + } + } catch (Exception e) { log.error("Error sending scale out alert: {}", e.getMessage(), e); } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 4fe3e4e..137ec82 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -108,11 +108,13 @@ k8s: rabbitmq: alert: - url: ${RABBITMQ_URL:localhost} + url: ${RABBITMQ_URL:210.207.104.130} port: ${RABBITMQ_PORT:15672} vhost: ${RABBITMQ_VHOST:test} username: ${RABBITMQ_USERNAME:mc-agent} password: ${RABBITMQ_PASSWORD:mc-agent} - slack-channel-id: ${ALERT_SLACK_CHANNEL_ID:#kubernetes-alerts} + slack-channel-id: ${ALERT_SLACK_CHANNEL_ID:} + email: ${ALERT_EMAIL:} + sms-phonenumber: ${ALERT_SMS_PHONE_NUMBER:} + kakao-phonenumber: ${ALERT_KAKAO_PHONE_NUMBER:} - \ No newline at end of file