首页 > 其他分享 >数据中台预警监控功能简要设计

数据中台预警监控功能简要设计

时间:2022-12-06 16:23:58浏览次数:44  
标签:COMMENT 简要 预警 counter DEFAULT 监控 import NULL id

需求:

  针对产品主要流程中一些异常情况, 数据中台接收各个业务系统,其他中台系统发送的异常事件。 满足触发阀值之后进行短信告警功能。

 

设计:

  1、配置监控器:

      监控事件、监控范围、触发阀值、对应负责人(配置负责人)

      监控器监控的范围可以是全项目单个事件,也可以是指定项目的单个事件

  2、某个事件连续触发阀值次数的时候,生成告警记录,发送短信。已告警的所属事件继续出发时候累计触发次数

  3、告警记录点击处理,清除掉此记录上面累计的所有堆积事件,监控器重置,重新开始接收

 

  大体表结构:

-- scp_alert_monitoring_configuration: 预警监控配置表
-- scp_alert_contact: 告警联系人表
-- 异常记录表 scp_business_exception_record
-- 告警计数器表 scp_alarm_counter
-- 异常记录告警计数器关联表 scp_exception_record_alarm_counter_ref
-- 预警记录表 scp_alarm_record
-- 预警短信信息表 scp_alarm_sms_record

 

设计图:

 

 

 

 

 

 

 

 

针对各个事件的数据清洗,采用策略模式分发处理

监控器的创建与维护,每一次接收新事件记录时候校验维护一次,因为配置信息不在中台数据库

数据库表sql:

CREATE TABLE `supply_chain_dsc`.`scp_alert_monitoring_configuration` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`alert_event` varchar(3) DEFAULT NULL COMMENT '预警事件(01-授信决策失败、02-授信决策超时、03-额度激活失败、04-钱包开通失败、05-用信决策失败、06-用信决策超时、07-支付失败、08-客户自主还款失败)',
`monitoring_scope` varchar(2) DEFAULT NULL COMMENT '监控范围(01-单项目、02-全平台)',
`cumulative_times` int(11) DEFAULT NULL COMMENT '累计次数',
`alarm_level` varchar(2) DEFAULT NULL COMMENT '告警级别:01-A、02-B',
`is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除(1:已删除,0:未删除)',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='预警监控配置表';


CREATE TABLE `supply_chain_dsc`.`scp_alert_contact` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`personnel_type` varchar(2) DEFAULT NULL COMMENT '人员类型(01-客户经理、02-运营经理、03-产品经理、04-风险经理)',
`name` varchar(20) DEFAULT NULL COMMENT '姓名',
`phone_no` varchar(15) NOT NULL COMMENT '手机号',
`is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除(1:已删除,0:未删除)',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='告警联系人表';

CREATE TABLE `supply_chain_dsc`.`scp_dsc_alarm_counter` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`project_id` varchar(64) DEFAULT NULL COMMENT '项目id',
`monitoring_scope` char(2) NOT NULL COMMENT '阀值范围:01-单项目、02-全平台',
`event_type` char(2) NOT NULL COMMENT '异常类型:01-授信决策失败,02-授信决策超时,03-额度激活失败,04-钱包开通失败,05-用信决策失败,06-用信决策超时,07-支付失败,08-客户自主还款失败',
`alarm_trigger_base_times` int(11) NOT NULL COMMENT '告警触发基础次数',
`alarm_level` char(2) NOT NULL COMMENT '告警级别:01-A、02-B',
`trigger_times` int(11) NOT NULL DEFAULT '0' COMMENT '触发次数',
`alarm_status` char(1) NOT NULL DEFAULT '2' COMMENT '告警状态:1-已告警,2-未告警',
`is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '''逻辑删除(1:已删除,0:未删除)''',
`reset_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '重置时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT='告警计数器表';
CREATE TABLE `supply_chain_dsc`.`scp_dsc_alarm_record` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`project_id` varchar(64) DEFAULT NULL COMMENT '项目id',
`alarm_counter_id` int(11) NOT NULL COMMENT '计数器id',
`trigger_times` int(11) NOT NULL COMMENT '触发次数',
`monitoring_scope` char(2) NOT NULL COMMENT '监控范围(01-单项目、02-全平台)',
`event_type` char(2) NOT NULL COMMENT '预警事件(01-授信决策失败、02-授信决策超时、03-额度激活失败、04-钱包开通失败、05-用信决策失败、06-用信决策超时、07-支付失败、08-客户自主还款失败)',
`alarm_level` char(2) NOT NULL COMMENT '告警级别:01-A、02-B',
`status` char(1) NOT NULL DEFAULT '1' COMMENT '状态:1-未处理、2-已处理',
`deal_time` datetime DEFAULT NULL COMMENT '处理时间',
`deal_user_phone` varchar(255) DEFAULT NULL COMMENT '处理人手机号',
`deal_user_name` varchar(255) DEFAULT NULL COMMENT '处理人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `index_alarm_counter_id` (`alarm_counter_id`) COMMENT '告警计数器id索引'
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='预警记录表';
CREATE TABLE `supply_chain_dsc`.`supply_chain_dsc`.`scp_dsc_alarm_sms_record` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`alarm_record_id` int(11) NOT NULL COMMENT '告警记录id',
`name` varchar(20) DEFAULT NULL COMMENT '姓名',
`phone_no` varchar(15) DEFAULT NULL COMMENT '手机号',
`content` varchar(500) NOT NULL COMMENT '短信内容',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `index_alarm_record_id` (`alarm_record_id`) COMMENT '告警记录id索引'
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='告警短信记录表';
CREATE TABLE `supply_chain_dsc`.`scp_dsc_business_exception_record` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`exception_type` char(2) NOT NULL COMMENT '异常类型:01-授信决策失败,02-授信决策超时,03-额度激活失败,04-钱包开通失败,05-用信决策失败,06-用信决策超时,07-支付失败,08-客户自主还款失败',
`business_no` varchar(100) NOT NULL COMMENT '业务单号',
`project_id` varchar(64) NOT NULL COMMENT '项目id',
`project_name` varchar(255) DEFAULT NULL COMMENT '项目名称',
`user_id` varchar(50) DEFAULT NULL COMMENT '用户id',
`user_name` varchar(100) DEFAULT NULL COMMENT '用户名称',
`fail_reason` varchar(1024) NOT NULL COMMENT '错误原因',
`fail_reason_detail` varchar(500) DEFAULT NULL COMMENT '错误详细原因',
`remark` varchar(200) DEFAULT NULL COMMENT '备注',
`trigger_time` datetime NOT NULL COMMENT '触发时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=214 DEFAULT CHARSET=utf8 COMMENT='业务异常记录表';
CREATE TABLE `supply_chain_dsc`.`scp_dsc_exception_record_alarm_counter_ref` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`alarm_counter_id` int(11) NOT NULL COMMENT '告警计数器id',
`exception_record_id` int(11) NOT NULL COMMENT '异常记录id',
`alarm_record_id` int(11) DEFAULT NULL COMMENT '告警记录id',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=198 DEFAULT CHARSET=utf8 COMMENT='异常记录告警计数器关联表';
View Code

 

为了方便下次理解,贴主要代码:

package com.wxsbank.supplychain.dsc.business.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.wxsbank.common.exception.BusinessMessage;
import com.wxsbank.framework.common.exception.impl.BusinessException;
import com.wxsbank.framework.spring.annotation.Business;
import com.wxsbank.supplychain.dsc.business.ExceptionEventCleanStrategy;
import com.wxsbank.supplychain.dsc.business.IExceptionAlarmBusiness;
import com.wxsbank.supplychain.dsc.business.SmsBusiness;
import com.wxsbank.supplychain.dsc.dto.input.AlarmQueryDTO;
import com.wxsbank.supplychain.dsc.dto.output.AlarmRepayInfoSimpleDTO;
import com.wxsbank.supplychain.dsc.entity.*;
import com.wxsbank.supplychain.dsc.enums.*;
import com.wxsbank.supplychain.dsc.event.AlarmPageEvent;
import com.wxsbank.supplychain.dsc.event.BatchClearAlarmEvent;
import com.wxsbank.supplychain.dsc.event.SmsEvent;
import com.wxsbank.supplychain.dsc.model.AlarmMessageModel;
import com.wxsbank.supplychain.dsc.model.AlarmMessagePageModel;
import com.wxsbank.supplychain.dsc.service.*;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 异常告警业务处理类
 * @author zhen
 */
@Business
@Slf4j
public class ExceptionAlarmBusinessImpl implements IExceptionAlarmBusiness {

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private IScpAlertMonitoringConfigurationService alertMonitoringConfigurationService;

    @Resource
    private IScpAlarmCounterService alarmCounterService;

    @Resource
    private IScpAlarmRecordService alarmRecordService;

    @Resource
    private IScpBusinessExceptionRecordService businessExceptionRecordService;

    @Resource
    private IScpExceptionRecordAlarmCounterRefService exceptionRecordAlarmCounterRefService;

    @Resource
    private IScpAlertContactService alertContactService;

    @Resource
    private IScpAlarmSmsRecordService smsRecordService;

    @Resource
    private ICreditApplyInfoService creditApplyInfoService;

    @Resource
    private IUseCreditApplyInfoService useCreditApplyInfoService;

    @Resource
    private ICreditApplyStatusRecordService creditApplyStatusRecordService;

    @Resource
    private IUseCreditApplyStatusRecordService useCreditApplyStatusRecordService;

    @Resource
    private IRepayInfoService repayInfoService;

    @Resource
    private IRmScpPclGrantCreditApplyService pclGrantCreditApplyService;

    @Resource
    private IPclUseCreditApplyInfoService pclUseCreditApplyInfoService;

    @Resource
    private SmsBusiness smsBusiness;

    @Value("${exception.monitor.alarm.sms}")
    private String monitorAlarmSmsTemplate;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchClearAlarm(BatchClearAlarmEvent event) {
        List<Integer> alarmRecordIdList = event.getAlarmRecordIdList();
        if (CollUtil.isEmpty(alarmRecordIdList)) {
            return;
        }
        // 判断解除人的合法性
        ScpAlertContact scpAlertContact = alertContactService.findByNameAndPhone(event.getDealUserName(), event.getDealUserPhone());
        if (scpAlertContact == null) {
            throw new BusinessException(BusinessMessage.ALERT_CONTACT_NOT_EXIST);
        }

        List<ScpAlarmRecord> scpAlarmRecordList = new ArrayList<>(alarmRecordIdList.size());
        ScpAlarmRecord scpAlarmRecord;
        ScpAlarmCounter scpAlarmCounter;
        for (Integer id : alarmRecordIdList) {
            // 告警计数器表触发次数清零
            ScpAlarmRecord alarmRecord = alarmRecordService.getById(id);
            if (alarmRecord == null || AlarmRecordStatusEnum.PROCESSED.getValue().equals(alarmRecord.getStatus())) {
                continue;
            }
            scpAlarmCounter = new ScpAlarmCounter();
            scpAlarmCounter.setId(alarmRecord.getAlarmCounterId());
            scpAlarmCounter.setTriggerTimes(0);
            scpAlarmCounter.setAlarmStatus(AlarmStatusEnum.UN_COMPLETE_ALARM.getValue());
            scpAlarmCounter.setResetTime(LocalDateTime.now());
            alarmCounterService.updateById(scpAlarmCounter);
            // 预警记录
            scpAlarmRecord = new ScpAlarmRecord();
            scpAlarmRecord.setId(id);
            // 预警记录已被处理
            scpAlarmRecord.setStatus(AlarmRecordStatusEnum.PROCESSED.getValue());
            scpAlarmRecord.setDealTime(LocalDateTime.now());
            scpAlarmRecord.setDealUserName(event.getDealUserName());
            scpAlarmRecord.setDealUserPhone(event.getDealUserPhone());
            scpAlarmRecordList.add(scpAlarmRecord);
        }
        // 预警记录表更新处理人信息
        alarmRecordService.updateBatchById(scpAlarmRecordList);
    }

    @Override
    public void clearAndSaveBusinessException(JSONObject content, ExceptionEventCleanStrategy cleanStrategy, String businessNo) {

        final String keyPrefix = "EXCEPTION_EVENT_TRIGGER_";
        String key = keyPrefix + businessNo + "_" + cleanStrategy.getExceptionEventType().getValue();
        RLock lock = redissonClient.getLock(key);
        try {
            lock.lock(2, TimeUnit.MINUTES);
            //清洗数据
            Integer exceptionRecordId = cleanStrategy.cleanAndSave(content);
            if (exceptionRecordId == -1) {
                // -1 表示清洗数据出现数据异常
                return;
            }
            if (exceptionRecordId != null){

                //创建或销毁计数器
                repairCounterInfo(exceptionRecordId);

                //异步触发计数器
                Integer finalExceptionRecordId = exceptionRecordId;
                CompletableFuture.runAsync(() ->
                        triggerAlarmMonitorChain(finalExceptionRecordId)
                );

            }
        } catch (Exception e) {
            log.error("【LEVEL:LOW】【业务异常数据清洗 type:" + cleanStrategy.getExceptionEventType().getDesc() + " data:" + content.toJSONString()
                    + "】数据异常!", e);
        } finally {
            lock.unlock();
        }

    }

    /**
     * 触发报警监控链
     * @param businessExceptionRecordId
     */
    @Transactional
    @Override
    public void triggerAlarmMonitorChain(Integer businessExceptionRecordId) {
        ScpBusinessExceptionRecord exceptionRecord = businessExceptionRecordService.getById(businessExceptionRecordId);
        if (exceptionRecord == null) {
            return;
        }

        List<ScpAlarmCounter> counters = queryTriggerCounter(exceptionRecord);
        if(counters.isEmpty()){
            return;
        }

        for(ScpAlarmCounter counter : counters){
            String key = "EXCEPTION_EVENT_COUNTER_TRIGGER_" + counter.getId();
            // 增加一个同步锁,处理针对同一counter累加的并发问题
            RLock lock = redissonClient.getLock(key);
            try {
                lock.lock(2, TimeUnit.MINUTES);
                if (AlarmStatusEnum.COMPLETED_ALARM.getValue().equals(counter.getAlarmStatus())){
                    triggerInCompletedAlarmCounter(counter, businessExceptionRecordId);
                }else {
                    triggerInUnCompletedAlarmCounter(counter, businessExceptionRecordId);
                }
            }catch(Exception e){
                log.error("【LEVEL:LOW】【预警监控触发异常 counterId:" + counter.getId() + " businessExceptionRecordId:" + businessExceptionRecordId
                        + " 事件件类型:" + ExceptionEventTypeEnum.getDescByValue(counter.getEventType()) + "】数据异常!", e);
            }finally {
                if (lock.isLocked()){
                    lock.unlock();
                }
            }

        }

    }

    @Override
    public void sendAlarmSms(Integer alarmRecordId) {
        List<ScpAlarmSmsRecord> smsRecordList = smsRecordService.queryByAlarmRecordId(alarmRecordId);
        for (ScpAlarmSmsRecord alarmSmsRecord : smsRecordList){
            SmsEvent event = new SmsEvent();
            event.setContent(alarmSmsRecord.getContent());
            event.setPhone(alarmSmsRecord.getPhoneNo());
            smsBusiness.customMsgSend(event);
        }

    }

    @Override
    public List<UseCreditApplyInfo> selectDelayAndNoTriggerUseCreditInfoList(LocalDateTime startTime, LocalDateTime endTime,
                                                                             LocalDateTime maxCreateTime) {
        return useCreditApplyInfoService.selectDelayAndNoTriggerUseCreditInfoList(startTime, endTime, maxCreateTime);
    }

    @Override
    public List<PclUseCreditApplyInfo> selectDelayAndNoTriggerPersonUseCreditApplyInfoList(LocalDateTime startTime,
                                                                                           LocalDateTime endTime,
                                                                                           LocalDateTime maxCreateTime) {
        return pclUseCreditApplyInfoService.selectDelayAndNoTriggerPersonUseCreditApplyInfoList(startTime, endTime, maxCreateTime);
    }

    @Override
    public List<CreditApplyInfo> selectDelayAndNoTriggerCreditApplyInfoList(LocalDateTime startTime, LocalDateTime endTime,
                                                                            LocalDateTime maxCreateTime) {
        return creditApplyInfoService.selectDelayAndNoTriggerCreditApplyInfoList(startTime, endTime, maxCreateTime);
    }

    @Override
    public List<RmScpPclGrantCreditApply> selectDelayAndNoTriggerPersonCreditApplyInfoList(LocalDateTime startTime,
                                                                                           LocalDateTime endTime,
                                                                                           LocalDateTime maxCreateTime) {
        return pclGrantCreditApplyService.selectDelayAndNoTriggerPersonCreditApplyInfoList(startTime, endTime, maxCreateTime);
    }

    @Override
    public List<CreditApplyStatusRecord> selectFailAndNoTriggerCreditApplyStatusList(LocalDateTime startTime, LocalDateTime endTime) {
        return creditApplyStatusRecordService.selectFailAndNoTriggerCreditApplyStatusList(startTime, endTime);
    }

    @Override
    public List<UseCreditApplyStatusRecord> selectFailAndNoTriggerUseCreditApplyStatusList(LocalDateTime startTime, LocalDateTime endTime) {
        return useCreditApplyStatusRecordService.selectFailAndNoTriggerUseCreditApplyStatusList(startTime, endTime);
    }

    @Override
    public List<AlarmRepayInfoSimpleDTO> selectFailAndNoTriggerRepayInfoList(LocalDateTime startTime, LocalDateTime endTime) {
        return repayInfoService.selectFailAndNoTriggerRepayInfoList(startTime, endTime);
    }

    @Override
    public AlarmMessagePageModel queryAlarmPage(AlarmPageEvent event) {
        AlarmQueryDTO alarmQueryDTO = new AlarmQueryDTO();
        alarmQueryDTO.setName(event.getName());
        alarmQueryDTO.setPhoneNo(event.getPhoneNo());
        alarmQueryDTO.setProjectId(event.getProjectId());
        alarmQueryDTO.setPageNum(event.getPageNum());
        alarmQueryDTO.setPageSize(event.getPageSize());
        // 查询未处理的告警记录
        alarmQueryDTO.setStatus("1");
        IPage<ScpAlarmRecord> scpAlarmRecordIPage = alarmRecordService.queryAlarmRecordByCondition(alarmQueryDTO);
        List<ScpAlarmRecord> scpAlarmRecords = scpAlarmRecordIPage.getRecords();
        if (CollUtil.isEmpty(scpAlarmRecords)) {
            return null;
        }
        AlarmMessagePageModel alarmMessagePageModel = new AlarmMessagePageModel();
        List<AlarmMessageModel> alarmMessageModelList = new ArrayList<>(scpAlarmRecords.size());
        AlarmMessageModel alarmMessageModel;
        for (ScpAlarmRecord scpAlarmRecord : scpAlarmRecords) {
            alarmMessageModel = new AlarmMessageModel();
            alarmMessageModel.setAlarmRecordId(scpAlarmRecord.getId());
            alarmMessageModel.setMonitoringScope(scpAlarmRecord.getMonitoringScope());
            alarmMessageModel.setEventType(scpAlarmRecord.getEventType());
            alarmMessageModel.setAlarmLevel(scpAlarmRecord.getAlarmLevel());
            alarmMessageModel.setTriggerTime(
                    scpAlarmRecord.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            alarmMessageModel.setProjectId(scpAlarmRecord.getProjectId());
            alarmMessageModel.setProjectName(scpAlarmRecord.getProjectName());
            alarmMessageModelList.add(alarmMessageModel);
        }
        alarmMessagePageModel.setTotalNum((int) scpAlarmRecordIPage.getPages());
        alarmMessagePageModel.setTotalSize((int) scpAlarmRecordIPage.getTotal());
        alarmMessagePageModel.setAlarmMessageModelList(alarmMessageModelList);
        return alarmMessagePageModel;
    }

    /**
     * 在未完成的计数器触发
     * @param counter
     * @param businessExceptionRecordId
     */
    private void triggerInUnCompletedAlarmCounter(ScpAlarmCounter counter, Integer businessExceptionRecordId){
        int nowTriggerTimes = counter.getTriggerTimes() +1;

        //计数器触发次数+1
        ScpAlarmCounter updateCounter = new ScpAlarmCounter();
        updateCounter.setId(counter.getId());
        updateCounter.setTriggerTimes(counter.getTriggerTimes() + 1);
        alarmCounterService.updateById(updateCounter);

        //异常数据-触发器关联记录落库
        ScpExceptionRecordAlarmCounterRef ref = new ScpExceptionRecordAlarmCounterRef();
        ref.setAlarmCounterId(counter.getId());
        ref.setExceptionRecordId(businessExceptionRecordId);
        exceptionRecordAlarmCounterRefService.save(ref);

        //触发告警
        if(nowTriggerTimes == counter.getAlarmTriggerBaseTimes()){
            //触发器状态变更已触发
            updateCounter = new ScpAlarmCounter();
            updateCounter.setId(counter.getId());
            updateCounter.setAlarmStatus(AlarmStatusEnum.COMPLETED_ALARM.getValue());
            alarmCounterService.updateById(updateCounter);

            ScpBusinessExceptionRecord businessExceptionRecord = businessExceptionRecordService.getById(businessExceptionRecordId);
            //创建告警记录
            ScpAlarmRecord alarmRecord = new ScpAlarmRecord();
            alarmRecord.setTriggerTimes(nowTriggerTimes);
            alarmRecord.setAlarmCounterId(counter.getId());
            alarmRecord.setProjectId(counter.getProjectId());
            alarmRecord.setEventType(counter.getEventType());
            alarmRecord.setAlarmLevel(counter.getAlarmLevel());
            alarmRecord.setMonitoringScope(counter.getMonitoringScope());
            alarmRecord.setStatus(AlarmRecordStatusEnum.UNTREATED.getValue());
            alarmRecord.setProjectName(businessExceptionRecord.getProjectName());
            alarmRecordService.eachIdSave(alarmRecord);

            //为计数器内包含的时间关联与告警记录创建关联
            List<ScpExceptionRecordAlarmCounterRef> refList
                    = exceptionRecordAlarmCounterRefService.selectListByCurrentCounter(counter);
            refList.forEach(item->
                    item.setAlarmRecordId(alarmRecord.getId())
            );
            exceptionRecordAlarmCounterRefService.updateBatchById(refList);

            //目前是发送给所有的联系人
            List<ScpAlertContact> contactList = alertContactService.queryValidContactList();
            List<ScpAlarmSmsRecord> smsSendList = new ArrayList<>();
            if(!contactList.isEmpty()){
                for(ScpAlertContact  contact : contactList){
                    //创建smsRecord记录
                    ScpAlarmSmsRecord scpAlarmSmsRecord = new ScpAlarmSmsRecord();
                    scpAlarmSmsRecord.setName(contact.getName());
                    scpAlarmSmsRecord.setPhoneNo(contact.getPhoneNo());
                    scpAlarmSmsRecord.setAlarmRecordId(alarmRecord.getId());
                    String content = String.format(monitorAlarmSmsTemplate, AlarmLevelEnum.getDescByValue(alarmRecord.getAlarmLevel()),
                            MonitorScopeEnum.getDescByValue(alarmRecord.getMonitoringScope())
                                    + (MonitorScopeEnum.SINGLE_PROJECT.getValue().equals(alarmRecord.getMonitoringScope()) ?
                                    "(" + alarmRecord.getProjectName() + ")" : "")
                                    + " " + ExceptionEventTypeEnum.getDescByValue(alarmRecord.getEventType()));
                    scpAlarmSmsRecord.setContent(content);
                    smsSendList.add(scpAlarmSmsRecord);
                }
                //告警记录绑定发送短信信息落库
                smsRecordService.saveBatch(smsSendList);

                //异步触发发告警短信
                if(TransactionSynchronizationManager.isActualTransactionActive()){
                    //如果事务未提交,则提交之后调用异步方法
                    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                        @Override
                        public void afterCommit() {
                            CompletableFuture.runAsync(() ->
                                    sendAlarmSms(alarmRecord.getId())
                            );
                        }
                    });
                }else {
                    CompletableFuture.runAsync(() ->
                            sendAlarmSms(alarmRecord.getId())
                    );

                }

            }


        }


    }

    /**
     * 在已完成的计数器触发
     * @param counter
     * @param businessExceptionRecordId
     */
    private void triggerInCompletedAlarmCounter(ScpAlarmCounter counter, Integer businessExceptionRecordId){
        ScpAlarmCounter updateCounter = new ScpAlarmCounter();
        updateCounter.setId(counter.getId());
        updateCounter.setTriggerTimes(counter.getTriggerTimes() + 1);
        alarmCounterService.updateById(updateCounter);
        ScpAlarmRecord alarmRecord = alarmRecordService.findUntreatedRecordByCounter(counter.getId());

        ScpAlarmRecord updateAlarmRecord = new ScpAlarmRecord();
        updateAlarmRecord.setId(alarmRecord.getId());
        updateAlarmRecord.setTriggerTimes(alarmRecord.getTriggerTimes() + 1);
        alarmRecordService.updateById(updateAlarmRecord);

        ScpExceptionRecordAlarmCounterRef ref = new ScpExceptionRecordAlarmCounterRef();
        ref.setAlarmCounterId(counter.getId());
        ref.setAlarmRecordId(alarmRecord.getId());
        ref.setExceptionRecordId(businessExceptionRecordId);
        exceptionRecordAlarmCounterRefService.save(ref);
    }

    /**
     * 查询将要触发的counter
     * @param exceptionRecord
     * @return
     */
    private List<ScpAlarmCounter> queryTriggerCounter(ScpBusinessExceptionRecord exceptionRecord) {

        List<ScpAlarmCounter> counterList = alarmCounterService.queryWaitTriggerCounterList(exceptionRecord.getExceptionType(),
                MonitorScopeEnum.ALL_PROJECT.getValue(), null);

        List<ScpAlarmCounter> singleProjectCounterList
                = alarmCounterService.queryWaitTriggerCounterList(exceptionRecord.getExceptionType(),
                MonitorScopeEnum.SINGLE_PROJECT.getValue(), exceptionRecord.getProjectId());

        counterList.addAll(singleProjectCounterList);
        return counterList;
    }

    /**
     * 维护计数器
     * @param exceptionRecordId  异常事件id
     */
    private void repairCounterInfo(Integer exceptionRecordId){

        // 1、找到应该删除的counter,完成删除
        List<Integer> counterIds = alarmCounterService.queryShouldInvalidCounterIds();
        if (!counterIds.isEmpty()) {
            alarmCounterService.invalidCounter(counterIds);
        }

        String key = "EXCEPTION_EVENT_TRIGGER_ADD_COUNTER";
        RLock lock = redissonClient.getLock(key);
        try {
            lock.lock(2, TimeUnit.MINUTES);

            // 2、找到应该新建的counter,完成新建
            ScpBusinessExceptionRecord exceptionRecord = businessExceptionRecordService.getById(exceptionRecordId);
            String eventType = exceptionRecord.getExceptionType();
            String projectId = exceptionRecord.getProjectId();
            List<ScpAlertMonitoringConfiguration> allScopeConfigurations
                    = alertMonitoringConfigurationService.queryByEventAndScope(eventType, MonitorScopeEnum.ALL_PROJECT.getValue());
            List<ScpAlertMonitoringConfiguration> singleProjectConfigurations
                    = alertMonitoringConfigurationService.queryByEventAndScope(eventType, MonitorScopeEnum.SINGLE_PROJECT.getValue());

            for (ScpAlertMonitoringConfiguration configuration : allScopeConfigurations) {
                ScpAlarmCounter counter = alarmCounterService.findAllProjectMatchValidCounter(configuration);
                if (counter == null) {
                    createNewCounter(configuration, null);
                }
            }

            for (ScpAlertMonitoringConfiguration configuration : singleProjectConfigurations) {
                ScpAlarmCounter counter = alarmCounterService.findSingleProjectMatchValidCounter(configuration, projectId);
                if (counter == null) {
                    createNewCounter(configuration, projectId);
                }
            }
        }catch(Exception e) {
            log.error("【LEVEL:LOW】【维护计数器 新增计数器异常】", e);
            throw e;
        }finally {
            if(lock.isLocked()){
                lock.unlock();
            }
        }

    }


    /**
     * 创建新的计数器
     * @param configuration 配置器
     * @param projectId  项目id
     */
    private void createNewCounter(ScpAlertMonitoringConfiguration configuration, String projectId){
        ScpAlarmCounter counter = new ScpAlarmCounter();
        counter.setAlarmLevel(configuration.getAlarmLevel());
        counter.setMonitoringScope(configuration.getMonitoringScope());
        counter.setEventType(configuration.getAlertEvent());
        counter.setAlarmTriggerBaseTimes(configuration.getCumulativeTimes());
        counter.setAlarmStatus(AlarmStatusEnum.UN_COMPLETE_ALARM.getValue());
        counter.setProjectId(projectId);
        alarmCounterService.save(counter);
    }


}
View Code

 

标签:COMMENT,简要,预警,counter,DEFAULT,监控,import,NULL,id
From: https://www.cnblogs.com/aigeileshei/p/16955633.html

相关文章

  • 等保三级安全要求简要攻略-安全物理环境
    之前有两篇文章写了为什么要做等保测评、等保测评的含义以及等保测评这份工作的一些职责和一些常见的FAQ,没有看过的朋友可以先去看下我的另外两篇文章:一起聊聊等保测评和......
  • Kubernetes(K8S) 监控 Prometheus + Grafana
    监控指标集群监控节点资源利用率节点数运行PodsPod监控容器指标应用程序Prometheus开源的监控、报警、数据库以HTTP协议周期性抓取被监控组件状态不需要......
  • 使用 Grafana 统一监控展示-对接 Zabbix
    概述在某些情况下,Metrics监控的2大顶流:Zabbix:用于非容器的虚拟机环境Prometheus:用于容器的云原生环境是共存的。但是在这种情况下,统一监控展示就不太方便,本文......
  • 线上服务异常的定位、处理与优化的探索 - 第六章 监控与自动运维平台
    监控与自动运维平台 Zabbix简介 Zabbix是一个开源的监控平台,基于C/S方式采集数据,并使用B/S的Web方式展示数据。具有主机性能、数据库性能、Web应用、CPU、IO状态、硬......
  • ESXI与PVE监控告警
    ESXI配置文件[root@192exporter]#catvmware_exporter/[email protected]_PASSWORD=P@ssworVSPHERE_HOST=192.168.0.20VSPHERE_......
  • Zabbix监控memcached
      Zabbix对memcached的监控的主要思路是可以memcached自带的的查询状态命令stats,在通过脚本来使用此命令进行数据的展示并结合相关命令将数值取出来完成zabbix对memcached......
  • JVM---性能监控与调优(JVM监控及诊断工具GUI)
    JVM监控及诊断工具-GUI概述 ......
  • 前端视频监控和回放方案
    采用方案:1、采用了萤石云(属于海康威视旗下的云服务)视频方案。2、支持第三方、海康部分及萤石云摄像头接入。3、萤石云接入登录入口:登录-用户认证中心(ys7.com)。 绑......
  • zabbix监控进程和监控日志
    zabbix监控进程和监控日志文章目录​​zabbix监控进程和监控日志​​​​一、自定义监控进程​​​​1、新建脚本存放目录​​​​2、修改zabbix_agentd.conf文件​​​​3......
  • 谈谈 Qt 程序安装包的大小,以及简要打包指南
    经常看到网上有些论调说Qt程序无比庞大,甚至拿.NET程序来比,说Qt程序打包以后跟.NET安装包差不多大。由此影响了很多人对Qt的选择。我觉得有必要对此做一些澄清—......