impl
AlarmAdminService.java
package com.autohome.frostmourne.monitor.service.admin.impl;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import com.autohome.frostmourne.core.contract.PagerContract;
import com.autohome.frostmourne.core.contract.ProtocolException;
import com.autohome.frostmourne.core.jackson.JacksonUtil;
import com.autohome.frostmourne.monitor.contract.AlarmContract;
import com.autohome.frostmourne.monitor.contract.AlertContract;
import com.autohome.frostmourne.monitor.contract.DataNameContract;
import com.autohome.frostmourne.monitor.contract.DataSourceContract;
import com.autohome.frostmourne.monitor.contract.MetricContract;
import com.autohome.frostmourne.monitor.contract.RuleContract;
import com.autohome.frostmourne.monitor.contract.ServiceInfoSimpleContract;
import com.autohome.frostmourne.monitor.contract.enums.AlarmStatus;
import com.autohome.frostmourne.monitor.contract.enums.ExecuteStatus;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.domain.Alarm;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.domain.Alert;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.domain.DataName;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.domain.DataSource;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.domain.Metric;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.domain.Recipient;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.domain.Rule;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.domain.RuleProperty;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.repository.IAlarmRepository;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.repository.IAlertRepository;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.repository.IDataNameRepository;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.repository.IDataSourceRepository;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.repository.IMetricRepository;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.repository.IRecipientRepository;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.repository.IRulePropertyRepository;
import com.autohome.frostmourne.monitor.dao.mybatis.frostmourne.repository.IRuleRepository;
import com.autohome.frostmourne.monitor.service.admin.IAlarmAdminService;
import com.autohome.frostmourne.monitor.service.admin.IScheduleService;
import com.autohome.frostmourne.monitor.service.core.service.IServiceInfoService;
import com.autohome.frostmourne.monitor.transform.DataNameTransformer;
import com.autohome.frostmourne.monitor.transform.DataSourceTransformer;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.base.Splitter;
import org.apache.logging.log4j.core.util.CronExpression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
@Service
public clast AlarmAdminService implements IAlarmAdminService {
private static final Logger LOGGER = LoggerFactory.getLogger(AlarmAdminService.clast);
private static final HashMap metricRuleMap = new HashMap() {
{
put("numeric", "numeric");
put("ring_than", "percentage");
put("same_time", "percentage");
put("object", "expression");
}
};
@Resource
private IAlarmRepository alarmRepository;
@Resource
private IRecipientRepository recipientRepository;
@Resource(name = "frostmourneTransactionManager")
private DataSourceTransactionManager frostmourneTransactionManager;
@Resource
private IAlertRepository alertRepository;
@Resource
private IRulePropertyRepository rulePropertyRepository;
@Resource
private IRuleRepository ruleRepository;
@Resource
private IMetricRepository metricRepository;
@Resource
private IDataSourceRepository dataSourceRepository;
@Resource
private IDataNameRepository dataNameRepository;
@Resource
private IScheduleService scheduleService;
@Resource
private IServiceInfoService serviceInfoService;
public boolean atomicSave(AlarmContract alarmContract) {
boolean isValidCron = CronExpression.isValidExpression(alarmContract.getCron());
if (!isValidCron) {
throw new ProtocolException(510, "cron表达式非法");
}
padAlarm(alarmContract);
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = frostmourneTransactionManager.getTransaction(def);
try {
save(alarmContract);
} catch (Exception ex) {
frostmourneTransactionManager.rollback(status);
LOGGER.error("error when save alarm", ex);
throw ex;
}
frostmourneTransactionManager.commit(status);
return true;
}
public boolean delete(Long alarmId) {
Optional optionalAlarm = alarmRepository.selectByPrimaryKey(alarmId);
if (!optionalAlarm.isPresent()) {
return false;
}
Alarm alarm = optionalAlarm.get();
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = frostmourneTransactionManager.getTransaction(def);
try {
alarmRepository.deleteByPrimaryKey(alarmId);
alertRepository.deleteByAlarm(alarmId);
metricRepository.deleteByAlarm(alarmId);
ruleRepository.deleteByAlarm(alarmId);
rulePropertyRepository.deleteByAlarm(alarmId);
recipientRepository.deleteByAlarm(alarmId);
scheduleService.removeJob(Math.toIntExact(alarm.getJobId()));
} catch (Exception ex) {
frostmourneTransactionManager.rollback(status);
}
frostmourneTransactionManager.commit(status);
return true;
}
@Transactional(value = "frostmourneTransactionManager")
public boolean open(Long alarmId) {
boolean result = updateStatus(alarmId, AlarmStatus.OPEN);
Alarm alarm = this.alarmRepository.selectByPrimaryKey(alarmId).get();
this.scheduleService.openJob(Math.toIntExact(alarm.getJobId()));
return result;
}
@Transactional(value = "frostmourneTransactionManager")
public boolean close(Long alarmId) {
boolean result = updateStatus(alarmId, AlarmStatus.CLOSE);
Alarm alarm = this.alarmRepository.selectByPrimaryKey(alarmId).get();
this.scheduleService.closeJob(Math.toIntExact(alarm.getJobId()));
return result;
}
public AlarmContract findById(Long alarmId) {
AlarmContract alarmContract = new AlarmContract();
Optional optionalAlarm = alarmRepository.selectByPrimaryKey(alarmId);
if (!optionalAlarm.isPresent()) {
return null;
}
Alarm alarm = optionalAlarm.get();
alarmContract.setId(alarmId);
alarmContract.setStatus(alarm.getStatus());
alarmContract.setOwnerKey(alarm.getOwnerKey());
alarmContract.setDescription(alarm.getDescription());
alarmContract.setCron(alarm.getCron());
alarmContract.setTeamName(alarm.getTeamName());
alarmContract.setAlarmType(alarm.getAlarmType());
alarmContract.setAlarmName(alarm.getAlarmName());
alarmContract.setExecuteResult(alarm.getExecuteResult());
alarmContract.setExecuteAt(alarm.getExecuteAt());
alarmContract.setJobId(alarm.getJobId());
alarmContract.setRiskLevel(alarm.getRiskLevel());
alarmContract.setRecoverNoticeStatus(alarm.getRecoverNoticeStatus());
MetricContract metricContract = new MetricContract();
Optional optionalMetric = this.metricRepository.findOneByAlarm(alarmId);
if (!optionalMetric.isPresent()) {
throw new ProtocolException(20200229, "find no metric, alarmId: " + alarmId);
}
Metric metric = optionalMetric.get();
metricContract.setAggregationType(metric.getAggregationType());
metricContract.setAggregationField(metric.getAggregationField());
metricContract.setQueryString(metric.getQueryString());
metricContract.setDataSourceId(metric.getDataSourceId());
metricContract.setDataName(metric.getDataName());
metricContract.setMetricType(metric.getMetricType());
metricContract.setDataNameId(metric.getDataNameId());
metricContract.setAlarmId(alarmId);
metricContract.setPostData(metric.getPostData());
metricContract.setProperties(JacksonUtil.deSerialize(metric.getProperties(), new TypeReference() {
}));
if (metric.getDataSourceId() != null && metric.getDataSourceId() > 0) {
Optional optionalDataSource = dataSourceRepository.selectByPrimaryKey(metric.getDataSourceId());
DataSourceContract dataSourceContract = optionalDataSource.map(DataSourceTransformer::model2Contract)
.orElseThrow(() -> new ProtocolException(1890, "datasource not exist. id: " + metric.getDataSourceId()));
metricContract.setDataSourceContract(dataSourceContract);
}
if (metric.getDataNameId() != null && metric.getDataNameId() > 0) {
Optional optionalDataName = dataNameRepository.selectByPrimaryKey(metric.getDataNameId());
if (!optionalDataName.isPresent()) {
LOGGER.error("dataName not exist. " + metric.getDataNameId());
throw new ProtocolException(1209, "dataName not exist. " + metric.getDataNameId());
}
DataNameContract dataNameContract = DataNameTransformer.model2Contract(optionalDataName.get());
metricContract.setDataNameContract(dataNameContract);
}
alarmContract.setMetricContract(metricContract);
RuleContract ruleContract = new RuleContract();
Optional optionalRule = this.ruleRepository.findOneByAlarm(alarmId);
if (!optionalRule.isPresent()) {
throw new ProtocolException(7292346, "alarm has no rule, alarmId: " + alarmId);
}
Rule rule = optionalRule.get();
ruleContract.setAlertTemplate(rule.getAlertTemplate());
ruleContract.setRuleType(rule.getRuleType());
ruleContract.setAlarmId(alarmId);
Map rulePropertyMap = new HashMap();
List rulePropertyList = this.rulePropertyRepository.findByRuleId(rule.getId());
if (rulePropertyList != null && rulePropertyList.size() > 0) {
for (RuleProperty ruleProperty : rulePropertyList) {
rulePropertyMap.put(ruleProperty.getPropKey(), ruleProperty.getPropValue());
}
}
ruleContract.setSettings(rulePropertyMap);
alarmContract.setRuleContract(ruleContract);
AlertContract alertContract = new AlertContract();
Alert alert = this.alertRepository.findOneByAlarm(alarmId).get();
alertContract.setSilence(alert.getSilence());
alertContract.setWays(Splitter.on(",").splitToList(alert.getWays()));
alertContract.setAlarm_id(alarmId);
alertContract.setAllowSmsFrom(alert.getAllowSmsFrom());
alertContract.setAllowSmsTo(alert.getAllowSmsTo());
alertContract.setDingRobotHook(alert.getDingRobotHook());
alertContract.setHttpPostUrl(alert.getHttpPostUrl());
alertContract.setWechatRobotHook(alert.getWechatRobotHook());
alertContract.setCreateAt(alert.getCreateAt());
List recipientList = this.recipientRepository.findByAlarm(alarmId);
alertContract.setRecipients(recipientList.stream().map(Recipient::getAccount).collect(Collectors.toList()));
alarmContract.setAlertContract(alertContract);
if (Optional.ofNullable(alarm.getServiceId()).orElse(0L) > 0L) {
alarmContract.setServiceInfo(serviceInfoService.getSimpleContract(alarm.getServiceId()).orElse(null));
}
return alarmContract;
}
public PagerContract find(int pageIndex, int pageSize, Long alarmId, String name,
String teamName, String status, Long serviceId) {
return alarmRepository.findPage(pageIndex, pageSize, alarmId, name, teamName, status, serviceId);
}
@Override
public void updateAlarmLastExecuteInfo(Long alarmId, Date executeTime, ExecuteStatus status) {
alarmRepository.updateAlarmLastExecuteInfo(alarmId, executeTime, status.getName());
}
private boolean updateStatus(Long alarmId, String status) {
return alarmRepository.updateStatus(alarmId, status) > 0;
}
public void save(AlarmContract alarmContract) {
//1. save alarm
boolean isNewAlarm = (alarmContract.getId() == null) || (alarmContract.getId() == 0);
Alarm alarm = null;
if (isNewAlarm) {
alarm = addAlarm(alarmContract);
} else {
alarm = updateAlarm(alarmContract);
}
Long alarmId = alarm.getId();
saveAlert(alarmContract.getAlertContract(), alarmId, isNewAlarm, alarmContract.getOperator());
Long ruleId = saveRule(alarmContract.getRuleContract(), alarmId, isNewAlarm, alarmContract.getOperator());
saveMetric(alarmContract.getMetricContract(), alarmId, ruleId, isNewAlarm, alarmContract.getOperator());
saveJobSchedule(isNewAlarm, alarm);
}
private Alarm addAlarm(AlarmContract alarmContract) {
Alarm alarm = new Alarm();
alarm.setAlarmName(alarmContract.getAlarmName());
alarm.setAlarmType(alarmContract.getAlarmType());
alarm.setCreator(alarmContract.getOperator());
alarm.setCron(alarmContract.getCron());
alarm.setTeamName(alarmContract.getTeamName());
alarm.setDescription(alarmContract.getDescription());
alarm.setModifier(alarmContract.getOperator());
alarm.setOwnerKey(alarmContract.getOwnerKey());
alarm.setStatus(alarmContract.getStatus());
alarm.setRiskLevel(alarmContract.getRiskLevel());
alarm.setRecoverNoticeStatus(alarmContract.getRecoverNoticeStatus());
Date now = new Date();
alarm.setCreateAt(now);
alarm.setModifyAt(now);
alarm.setJobId(0L);
alarm.setExecuteResult(ExecuteStatus.WAITING.getName());
alarm.setServiceId(Optional.ofNullable(alarmContract.getServiceInfo()).map(ServiceInfoSimpleContract::getId).orElse(null));
alarmRepository.insert(alarm);
return alarm;
}
private Alarm updateAlarm(AlarmContract alarmContract) {
Date now = new Date();
Alarm alarm = new Alarm();
alarm.setId(alarmContract.getId());
alarm.setAlarmName(alarmContract.getAlarmName());
alarm.setAlarmType(alarmContract.getAlarmType());
alarm.setDescription(alarmContract.getDescription());
alarm.setOwnerKey(alarmContract.getOwnerKey());
alarm.setStatus(alarmContract.getStatus());
alarm.setRiskLevel(alarmContract.getRiskLevel());
alarm.setRecoverNoticeStatus(alarmContract.getRecoverNoticeStatus());
alarm.setCron(alarmContract.getCron());
alarm.setModifyAt(now);
alarm.setModifier(alarmContract.getOperator());
alarm.setTeamName(alarmContract.getTeamName());
alarm.setServiceId(Optional.ofNullable(alarmContract.getServiceInfo()).map(ServiceInfoSimpleContract::getId).orElse(null));
alarmRepository.updateByPrimaryKeySelective(alarm);
alarm = alarmRepository.selectByPrimaryKey(alarmContract.getId()).get();
return alarm;
}
private void saveAlert(AlertContract contract, Long alarmId, boolean isNewAlarm, String account) {
if (!isNewAlarm) {
recipientRepository.deleteByAlarm(alarmId);
alertRepository.deleteByAlarm(alarmId);
}
Alert alert = new Alert();
alert.setWays(String.join(",", contract.getWays()));
alert.setAlarmId(alarmId);
alert.setSilence(contract.getSilence());
alert.setAllowSmsFrom(contract.getAllowSmsFrom());
alert.setAllowSmsTo(contract.getAllowSmsTo());
alert.setCreator(account);
alert.setCreateAt(new Date());
alert.setDingRobotHook(contract.getDingRobotHook());
alert.setHttpPostUrl(contract.getHttpPostUrl());
alert.setWechatRobotHook(contract.getWechatRobotHook());
alertRepository.insert(alert);
for (String recipient : contract.getRecipients()) {
Recipient alertRecipient = new Recipient();
alertRecipient.setAlarmId(alarmId);
alertRecipient.setAlertId(alert.getId());
alertRecipient.setAccount(recipient);
alertRecipient.setCreateAt(new Date());
recipientRepository.insert(alertRecipient);
}
}
private Long saveRule(RuleContract ruleContract, Long alarmId, boolean isNewAlarm, String account) {
if (!isNewAlarm) {
rulePropertyRepository.deleteByAlarm(alarmId);
ruleRepository.deleteByAlarm(alarmId);
}
Rule rule = new Rule();
rule.setAlarmId(alarmId);
rule.setAlertTemplate(ruleContract.getAlertTemplate());
rule.setCreator(account);
rule.setCreateAt(new Date());
rule.setRuleType(ruleContract.getRuleType());
ruleRepository.insert(rule);
Long ruleId = rule.getId();
if (ruleContract.getSettings() != null) {
for (Map.Entry entry : ruleContract.getSettings().entrySet()) {
RuleProperty ruleProperty = new RuleProperty();
ruleProperty.setAlarmId(alarmId);
ruleProperty.setCreateAt(new Date());
ruleProperty.setPropKey(entry.getKey());
ruleProperty.setPropValue(entry.getValue());
ruleProperty.setRuleId(ruleId);
ruleProperty.setCreator(account);
rulePropertyRepository.insert(ruleProperty);
}
}
return ruleId;
}
private void saveMetric(MetricContract metricContract, Long alarmId, Long ruleId, boolean isNewAlarm, String account) {
if (!isNewAlarm) {
metricRepository.deleteByAlarm(alarmId);
}
Metric metric = new Metric();
metric.setAlarmId(alarmId);
metric.setCreator(account);
metric.setRuleId(ruleId);
metric.setAggregationType(metricContract.getAggregationType());
metric.setAggregationField(metricContract.getAggregationField());
metric.setDataName(metricContract.getDataName());
metric.setDataSourceId(metricContract.getDataSourceId());
metric.setDataNameId(metricContract.getDataNameId());
metric.setMetricType(metricContract.getMetricType());
metric.setQueryString(metricContract.getQueryString());
metric.setPostData(metricContract.getPostData());
metric.setProperties(JacksonUtil.serialize(metricContract.getProperties()));
metric.setCreateAt(new Date());
metricRepository.insert(metric);
}
public void padAlarm(AlarmContract alarmContract) {
alarmContract.setAlarmType(alarmContract.getMetricContract().getDataName());
String ruleType = metricRuleMap.get(alarmContract.getMetricContract().getMetricType());
alarmContract.getRuleContract().setRuleType(ruleType);
if (!alarmContract.getMetricContract().getDataName().equalsIgnoreCase("http")) {
Optional optionalDataName = dataNameRepository.findByName(alarmContract.getMetricContract().getDataName());
if (!optionalDataName.isPresent()) {
throw new ProtocolException(1290, "dataName not exist. " + alarmContract.getMetricContract().getDataName());
}
DataName dataName = optionalDataName.get();
alarmContract.getMetricContract().setDataNameId(dataName.getId());
alarmContract.getMetricContract().setDataNameContract(DataAdminService.toDataNameContract(dataName));
alarmContract.getMetricContract().setDataSourceId(dataName.getDataSourceId());
Optional optionalDataSource = dataSourceRepository.selectByPrimaryKey(dataName.getDataSourceId());
DataSourceContract dataSourceContract = optionalDataSource.map(DataSourceTransformer::model2Contract)
.orElseThrow(() -> new ProtocolException(1900, "dataSource not exist. id: " + dataName.getDataSourceId()));
alarmContract.getMetricContract().setDataSourceContract(dataSourceContract);
}
}
private void saveJobSchedule(boolean isNewAlarm, Alarm alarm) {
if (isNewAlarm || alarm.getJobId()