Skip to content

Commit

Permalink
Merge pull request #17 from BSjaeyoung-kim/main
Browse files Browse the repository at this point in the history
CUR batch update & alarm service update
  • Loading branch information
BSjaeyoung-kim authored Sep 30, 2024
2 parents 9db124f + 05e1845 commit 8409124
Show file tree
Hide file tree
Showing 161 changed files with 5,930 additions and 1,407 deletions.
14 changes: 12 additions & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,17 @@ MAIL_DB_URL=jdbc:mariadb://host.docker.internal:3306/mailing?autoReconnect=true&
MAIL_DB_USERNM=mcmpcostopti
MAIL_DB_PW=0000
# CostCollector
COST_COLLECT_CRON_SCHEDULE=0 30 0 * * ?
COST_COLLECT_UNUSED_CRON_SCHEDULE=0 30 0 * * ?
COST_COLLECT_CUR_CRON_SCHEDULE=0 0 0,6 * * ?
AWS_CUR_EXPORT_NAME=MCMP-CostOpti
AWS_CUR_EXPORT_PATH_PREFIX=mcmp-costopti
AWS_ACCESS_KEY_ID=accesskey
AWS_SECRET_ACCESS_KEY=secretkey
# CostProcessor
COST_PROCESS_CRON_SCHEDULE=0 45 * * * ?
COST_PROCESS_UNUSED_CRON_SCHEDULE=0 45 * * * ?
COST_PROCESS_ABNORMAL_CRON_SCHEDULE=0 0 1,7 * * ?
COST_SELECTOR_URL=http://costselector:8083
ALARM_URL=http://localhost:9000
# AssetCollector
ASSET_MONITORING_SERVER=http://asset.mornitor.server:8080
ASSET_COLLECT_BATCH_CRON_SCHEDULE=0 0 0 * * ?
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.mcmp.slack_demo.common.model.costOpti.CostOptiAlarmReqModel;
import com.mcmp.slack_demo.mail.model.MailMessage;
import com.mcmp.slack_demo.mail.service.MailService;
import com.mcmp.slack_demo.slack.api_client.SlackACService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.ResponseEntity;
Expand All @@ -19,6 +20,9 @@ public class CommonController {
@Autowired
private MailService mailService;

@Autowired
private SlackACService slackService;

@PostMapping("/sendOptiAlarmMail")
public ResponseEntity<CommonResultModel> sendOptiAlarmMail(@RequestBody CostOptiAlarmReqModel reqModel){
CommonResultModel result = new CommonResultModel();
Expand All @@ -29,6 +33,7 @@ public ResponseEntity<CommonResultModel> sendOptiAlarmMail(@RequestBody CostOpti
mailService.sendEmail(reqModel, null);
break;
case "slack":
slackService.sendSlack(reqModel);
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.mcmp.slack_demo.common.dao;

import com.mcmp.slack_demo.common.model.costOpti.CostOptiAlarmReqModel;
import com.mcmp.slack_demo.mail.model.SendMailFormModel;
import com.mcmp.slack_demo.slack.model.SendSlackFormModel;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
Expand All @@ -15,12 +17,23 @@ public class CommonDao {
@Qualifier("sqlSessionTemplateHistory")
private SqlSessionTemplate sqlSession;

public int getAlertDuplicate(SendMailFormModel model){
return sqlSession.selectOne("HistorySql.getAlertDuplicate", model);
}

public void insertAlarmHistory(SendMailFormModel model){
sqlSession.insert("HistorySql.insertAlertHistory", model);
}

public List<String> getAlarmMailReceivers(Map<String, String> param){
public List<String> getAlarmMailReceivers(CostOptiAlarmReqModel param){
return sqlSession.selectList("HistorySql.getAlarmMailReceivers", param);
}

public int getSlackDuplicate(SendSlackFormModel model){
return sqlSession.selectOne("HistorySql.getAlertDuplicate", model);
}

public void insertSlackHistory(SendSlackFormModel model){
sqlSession.insert("HistorySql.insertAlertHistory", model);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ public class CostOptiAlarmModel {
private String resource_id;
private String resource_type;
private LocalDateTime occure_time;
private String csp_type;
private String account_id;
private String urgency;
private String plan;
private String note;
private String project_cd;

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.mcmp.slack_demo.common.service;

import com.mcmp.slack_demo.common.dao.CommonDao;
import com.mcmp.slack_demo.common.model.costOpti.CostOptiAlarmReqModel;
import com.mcmp.slack_demo.mail.model.SendMailFormModel;
import com.mcmp.slack_demo.slack.model.SendSlackFormModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
Expand All @@ -15,11 +17,23 @@ public class CommonService {
@Autowired
private CommonDao commonDao;

public int getAlertDuplicate(SendMailFormModel model){
return commonDao.getAlertDuplicate(model);
}

public void insertAlarmHistory(SendMailFormModel model){
commonDao.insertAlarmHistory(model);
}

public List<String> getAlarmMailReceivers(Map<String, String> param){
public List<String> getAlarmMailReceivers(CostOptiAlarmReqModel param){
return commonDao.getAlarmMailReceivers(param);
}

public int getSlackDuplicate(SendSlackFormModel model){
return commonDao.getSlackDuplicate(model);
}

public void insertSlackHistory(SendSlackFormModel model){
commonDao.insertSlackHistory(model);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ public class SendMailFormModel extends CostOptiAlarmReqModel {
private List<String> to;
private String subject;
private String message;
private String alarm_impl;
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,37 +51,52 @@ public class MailService {
public void sendEmail(CostOptiAlarmReqModel optiAlarmReqModel, ClassPathResource file){
SendMailFormModel mailFormModel = new SendMailFormModel();
BeanUtils.copyProperties(optiAlarmReqModel, mailFormModel);
mailFormModel.setOccure_time(ZonedDateTime.now(ZoneId.of("UTC")).toLocalDateTime());
mailFormModel.setOccure_time(ZonedDateTime.now().toLocalDateTime());
mailFormModel.setAlarm_impl("mail");

int checkDuplicateMail = commonService.getAlertDuplicate(mailFormModel);
if(checkDuplicateMail >= 1){
log.info("############Send OptiAlertEmail Duplicate : {} - {} - {}############", mailFormModel.getEvent_type(), mailFormModel.getResource_id()
, (mailFormModel.getAccount_id() != null ? mailFormModel.getAccount_id() : mailFormModel.getProject_cd()));
return;
}

try {
JavaMailSender emailSender = mailConfig.getJavaMailSender();
MimeMessage mimeMessage = emailSender.createMimeMessage();

// find mail receiver
mailFormModel.setTo(getAlarmMailReceivers(optiAlarmReqModel.getResource_id(), optiAlarmReqModel.getAccount_id()));
mailFormModel.setTo(getAlarmMailReceivers(optiAlarmReqModel));

String mailMessage = "[MCMP-Notice] Cost Alarm occurred";
switch (optiAlarmReqModel.getEvent_type()){
case "Unused":
mailFormModel.setSubject("[MCMP-Notice] Cost Alarm occurred : Caution Unused Resources");
mailMessage = "MCMP Cost에서 미사용 자원 주의 알람이 발생했습니다." +
"<br><br>" +
"계정 : " + mailFormModel.getAccount_id() + "<br>" +
"리소스 ID : " + mailFormModel.getResource_id();
"CSP : " + mailFormModel.getCsp_type() + "<br>" +
"리소스 ID : " + mailFormModel.getResource_id() + "<br>" +
"리소스 Type : " + mailFormModel.getResource_type() + "<br>" +
"해당 자원이 미사용 자원으로 의심됩니다.";
break;
case "Abnormal":
mailFormModel.setSubject("[MCMP-Notice] Cost Alarm occurred : Warning Abnormal Cost");
mailMessage = "MCMP Cost에서 이상 비용 경고 알람이 발생했습니다." +
"<br><br>" +
"계정 : " + mailFormModel.getAccount_id() + "<br>" +
"리소스 ID : " + mailFormModel.getResource_id();
"CSP : " + mailFormModel.getCsp_type() + "<br>" +
"제품군 : " + mailFormModel.getResource_type() + "<br>" +
"이상비용 등급 : " + mailFormModel.getPlan() + "<br>" +
"이상비용이 발생했습니다. " + mailFormModel.getNote();
break;
case "Resize":
mailFormModel.setSubject("[MCMP-Notice] Cost Alarm occurred : Advise Resizing Resources");
mailFormModel.setSubject("[MCMP-Notice] Cost Alarm occurred : Advise Right Size Resources");
mailMessage = "MCMP Cost에서 자원 최적화 권고 알람이 발생했습니다." +
"<br><br>" +
"계정 : " + mailFormModel.getAccount_id() + "<br>" +
"리소스 ID : " + mailFormModel.getResource_id();
"CSP : " + mailFormModel.getCsp_type() + "<br>" +
"리소스 ID : " + mailFormModel.getResource_id() + "<br>" +
"리소스 Type : " + mailFormModel.getResource_type() + "<br>" +
"추천 Plan : " + mailFormModel.getPlan() + "<br>" +
mailFormModel.getNote();
break;
}

Expand Down Expand Up @@ -155,14 +170,8 @@ public MailingInfoModel getMailingInfo(){
return mailingDao.getMailingInfo();
}

private List<String> getAlarmMailReceivers(String resource_id, String account_id){
Map<String, String> param = Map.of(
"resource_id", resource_id,
"account_id", account_id
);

private List<String> getAlarmMailReceivers(CostOptiAlarmReqModel param){
return commonService.getAlarmMailReceivers(param);

}

}
Original file line number Diff line number Diff line change
@@ -1,25 +1,114 @@
package com.mcmp.slack_demo.slack.api_client;

import com.mcmp.slack_demo.common.model.costOpti.CostOptiAlarmReqModel;
import com.mcmp.slack_demo.common.service.CommonService;
import com.mcmp.slack_demo.slack.encryto.TokenService;
import com.mcmp.slack_demo.slack.model.SendSlackFormModel;
import com.slack.api.Slack;
import com.slack.api.methods.SlackApiException;
import com.slack.api.methods.request.chat.ChatPostMessageRequest;
import com.slack.api.methods.response.chat.ChatPostMessageResponse;
import com.slack.api.model.Attachment;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

import javax.naming.AuthenticationException;
import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.Map;

@Service
@Slf4j
public class SlackACService {
private final TokenService tokenService;

@Autowired
public SlackACService(TokenService tokenService) {
this.tokenService = tokenService;
}
@Autowired
private CommonService commonService;

public void sendSlack(CostOptiAlarmReqModel costOptiAlarmReqModel) throws SlackApiException, IOException {
SendSlackFormModel slackFormModel = new SendSlackFormModel();
BeanUtils.copyProperties(costOptiAlarmReqModel, slackFormModel);
slackFormModel.setOccure_time(ZonedDateTime.now().toLocalDateTime());
slackFormModel.setAlarm_impl("slack");

int checkDuplicateMail = commonService.getSlackDuplicate(slackFormModel);
if(checkDuplicateMail >= 1){
log.info("############Send OptiAlertSlack Duplicate : {} - {} - {}############", slackFormModel.getEvent_type(), slackFormModel.getResource_id()
, (slackFormModel.getAccount_id() != null ? slackFormModel.getAccount_id() : slackFormModel.getProject_cd()));
return;
}

Slack slack = Slack.getInstance();
String message = "[MCMP-Notice] Cost Alarm occurred";
switch (costOptiAlarmReqModel.getEvent_type()){
case "Unused":
slackFormModel.setTitle("[MCMP-Notice] Cost Alarm occurred : Caution Unused Resources");
message = "MCMP Cost에서 미사용 자원 주의 알람이 발생했습니다." +
"\n\n" +
"CSP : " + slackFormModel.getCsp_type() + "\n" +
"리소스 ID : " + slackFormModel.getResource_id() + "\n" +
"리소스 Type : " + slackFormModel.getResource_type() + "\n" +
"해당 자원이 미사용 자원으로 의심됩니다.";
break;
case "Abnormal":
slackFormModel.setTitle("[MCMP-Notice] Cost Alarm occurred : Warning Abnormal Cost");
message = "MCMP Cost에서 이상 비용 경고 알람이 발생했습니다." +
"\n\n" +
"CSP : " + slackFormModel.getCsp_type() + "\n" +
"제품군 : " + slackFormModel.getResource_type() + "\n" +
"이상비용 등급 : " + slackFormModel.getPlan() + "\n" +
"이상비용이 발생했습니다. " + slackFormModel.getNote();
break;
case "Resize":
slackFormModel.setTitle("[MCMP-Notice] Cost Alarm occurred : Advise Right Size Resources");
message = "MCMP Cost에서 자원 최적화 권고 알람이 발생했습니다." +
"\n\n" +
"CSP : " + slackFormModel.getCsp_type() + "\n" +
"리소스 ID : " + slackFormModel.getResource_id() + "\n" +
"리소스 Type : " + slackFormModel.getResource_type() + "\n" +
"추천 Plan : " + slackFormModel.getPlan() + "\n" +
slackFormModel.getNote();
break;
}
try {
// Map<String, String> result = tokenService.retrieveToken(slackFormModel.getAccount_id());
Map<String, String> result = tokenService.retrieveToken("test");
Attachment attachment = Attachment.builder()
.title(slackFormModel.getTitle())
.text(message)
.color("#36a64f")
.build();

ChatPostMessageRequest request = ChatPostMessageRequest.builder()
.channel(result.get("channel"))
.attachments(Collections.singletonList(attachment))
.build();
ChatPostMessageResponse response = slack.methods(result.get("token")).chatPostMessage(request);
if (!response.isOk()) {
switch (response.getError()) {
case "invalid_auth":
throw new AuthenticationException("Invalid authentication credentials for Slack.");
case "channel_not_found":
throw new Exception("The specified channel was not found.");
default:
throw new Exception("An error occurred with Slack API: " + response.getError());
}
}
} catch (IOException | SlackApiException e) {
e.printStackTrace();
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
commonService.insertSlackHistory(slackFormModel);
}

public void sendMessage(String userId, String message, String linkUrl, String linkText) throws SlackApiException, IOException {
Slack slack = Slack.getInstance();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.mcmp.slack_demo.slack.model;

import com.mcmp.slack_demo.common.model.costOpti.CostOptiAlarmReqModel;
import lombok.Data;

@Data
public class SendSlackFormModel extends CostOptiAlarmReqModel {
private String title;
private String message;
private String alarm_impl;
}
Loading

0 comments on commit 8409124

Please sign in to comment.