From 6f48e0ae41f80e51788860aa3a186ce730d7cddf Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Tue, 15 Jul 2025 14:55:47 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E9=87=8D=E6=9E=84=E6=8E=A5=E6=94=B6?= =?UTF-8?q?=E5=91=8A=E8=AD=A6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/framework/constants/alarm.go | 24 +- .../ne_alarm_state_check.go | 134 ++------ .../ne_alarm_state_check_cmd.go | 224 +++++-------- .../ne_alarm_state_check_license.go | 137 ++------ .../network_data/controller/all_alarm.go | 5 +- src/modules/network_data/model/alarm.go | 24 +- src/modules/network_data/model/alarm_event.go | 10 +- .../network_data/model/alarm_forward_log.go | 14 +- src/modules/network_data/model/alarm_log.go | 20 +- src/modules/network_data/service/alarm.go | 25 +- .../network_data/service/alarm_event.go | 44 ++- src/modules/oam/service/alarm.go | 310 ++++++++++++++++++ 12 files changed, 538 insertions(+), 433 deletions(-) create mode 100644 src/modules/oam/service/alarm.go diff --git a/src/framework/constants/alarm.go b/src/framework/constants/alarm.go index f22c8e2d..e64a4d8d 100644 --- a/src/framework/constants/alarm.go +++ b/src/framework/constants/alarm.go @@ -1,13 +1,19 @@ package constants -// 告警 alarmCode 常量 const ( - // ALARM_EVENT_REBOOT 事件-网元重启 - ALARM_EVENT_REBOOT = 9000 - // ALARM_STATE_CHECK 告警-状态检查 - ALARM_STATE_CHECK = 10000 - // ALARM_RAM_CPU_CHECK 告警-内存/CPU/磁盘检查 - ALARM_CMD_CHECK = 10001 - // ALARM_LICENSE_CHECK 告警-网元License到期检查 - ALARM_LICENSE_CHECK = 10002 + ALARM_EVENT_REBOOT = 9000 // 告警Code-事件-网元重启 + ALARM_STATE_CHECK = 10000 // 告警Code-状态检查 + ALARM_CMD_CHECK = 10001 // 告警Code-内存/CPU/磁盘检查 + ALARM_LICENSE_CHECK = 10002 // 告警Code-网元License到期检查 +) + +const ( + ALARM_ACK_STATE_NOT_ACK = "NotAck" // 告警确认状态-未确认 + ALARM_ACK_STATE_ACK = "Ack" // 告警确认状态-已确认 +) + +const ( + ALARM_CLEAR_TYPE_NOT_CLEAR = "NotClear" // 告警清除状态-未清除 + ALARM_CLEAR_TYPE_AUTO_CLEAR = "AutoClear" // 告警清除状态-自动清除 + ALARM_CLEAR_TYPE_MANUAL_CLEAR = "ManualClear" // 告警清除状态-手动清除 ) diff --git a/src/modules/crontask/processor/ne_alarm_state_check/ne_alarm_state_check.go b/src/modules/crontask/processor/ne_alarm_state_check/ne_alarm_state_check.go index f2d6e9a7..e79e6f1d 100644 --- a/src/modules/crontask/processor/ne_alarm_state_check/ne_alarm_state_check.go +++ b/src/modules/crontask/processor/ne_alarm_state_check/ne_alarm_state_check.go @@ -5,33 +5,26 @@ import ( "fmt" "time" + "github.com/tsmask/go-oam" + "be.ems/src/framework/constants" "be.ems/src/framework/cron" "be.ems/src/framework/logger" "be.ems/src/framework/utils/parse" - - neDataModel "be.ems/src/modules/network_data/model" - neDataService "be.ems/src/modules/network_data/service" neModel "be.ems/src/modules/network_element/model" neService "be.ems/src/modules/network_element/service" - wsService "be.ems/src/modules/ws/service" + oamService "be.ems/src/modules/oam/service" ) var NewProcessor = &NeAlarmStateCheckProcessor{ - neConfigBackupService: neService.NewNeConfigBackup, - neInfoService: neService.NewNeInfo, - alarmService: neDataService.NewAlarm, - wsSendService: wsService.NewWSSend, - count: 0, + neInfoService: neService.NewNeInfo, + count: 0, } // NeAlarmStateCheckProcessor 网元告警状态检查 type NeAlarmStateCheckProcessor struct { - neConfigBackupService *neService.NeConfigBackup // 网元配置文件备份记录服务 - neInfoService *neService.NeInfo // 网元信息服务 - alarmService *neDataService.Alarm // 告警信息服务 - wsSendService *wsService.WSSend // ws发送服务 - count int // 执行次数 + neInfoService *neService.NeInfo // 网元信息服务 + count int // 执行次数 } // alarmParams 告警参数 @@ -69,104 +62,37 @@ func (s *NeAlarmStateCheckProcessor) Execute(data any) (any, error) { if neInfo.CreateTime == 0 { continue } - neTypeAndId := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId) + // 网元在线状态 isOnline := parse.Boolean(neInfo.ServerState["online"]) // 告警ID params.AlarmId = fmt.Sprintf("%d%d", constants.ALARM_STATE_CHECK, neInfo.CreateTime) - // 检查网元告警ID是否唯一 - alarmIdArr := s.alarmService.Find(neDataModel.Alarm{ - NeType: neInfo.NeType, - NeId: neInfo.NeId, - AlarmId: params.AlarmId, - }) - // 告警状态 - alarmStatus := "" - if len(alarmIdArr) > 0 { - alarmStatus = fmt.Sprint(alarmIdArr[0].AlarmStatus) - } - // 在线且状态为活动告警 - if isOnline && alarmStatus == "1" { - // 进行清除 - clearAlarm, err := s.alarmClear(neInfo, alarmIdArr[0]) - if err != nil { - result[neTypeAndId] = err.Error() - continue - } - groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId) - s.wsSendService.ByGroupID(groupID, clearAlarm) - result[neTypeAndId] = "alarm clear" - } - // 不在线 - if !isOnline && alarmStatus == "" { - // 进行新增 - newAlarm, err := s.alarmNew(neInfo, params) - if err != nil { - result[neTypeAndId] = err.Error() - continue - } - groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId) - s.wsSendService.ByGroupID(groupID, newAlarm) - result[neTypeAndId] = "alarm new" + // 告警状态 + alarmStatus := oam.ALARM_STATUS_ACTIVE + if isOnline { + alarmStatus = oam.ALARM_STATUS_CLEAR + } + // 创建告警 + alarm := oam.Alarm{ + NeUid: neInfo.RmUID, // 网元唯一标识 + AlarmTime: time.Now().UnixMilli(), // 事件产生时间 + AlarmId: params.AlarmId, // 告警ID 唯一,清除时对应 + AlarmCode: constants.ALARM_STATE_CHECK, // 告警状态码 + AlarmType: params.AlarmType, // 告警类型 + AlarmTitle: params.AlarmTitle, // 告警标题 + PerceivedSeverity: params.OrigSeverity, // 告警级别 + AlarmStatus: alarmStatus, // 告警状态 + SpecificProblem: params.SpecificProblem, // 告警问题原因 + SpecificProblemID: params.SpecificProblemID, // 告警问题原因ID + AddInfo: params.AddInfo, // 告警辅助信息 + LocationInfo: "NE State: Heartbeat", // 告警定位信息 + } + if err = oamService.NewAlarm.Resolve(alarm); err == nil { + result[neInfo.RmUID] = "state alarm" } } // 返回结果,用于记录执行结果 return result, nil } - -// alarmClear 清除告警 -func (s NeAlarmStateCheckProcessor) alarmClear(neInfo neModel.NeInfo, v neDataModel.Alarm) (neDataModel.Alarm, error) { - // 变更告警ID为告警清除ID - v.AlarmId = fmt.Sprintf("%d%d", v.AlarmCode, v.EventTime) - v.AlarmStatus = "0" - // 告警清除 - v.ClearType = 1 - v.ClearTime = neInfo.UpdateTime - v.ClearUser = "system" - rows := s.alarmService.Update(v) - if rows > 0 { - return v, nil - } - return neDataModel.Alarm{}, fmt.Errorf("clear alarm fail") -} - -// alarmNew 新增告警 -func (s NeAlarmStateCheckProcessor) alarmNew(neInfo neModel.NeInfo, v alarmParams) (neDataModel.Alarm, error) { - // seq 告警序号 - lastSeq := s.alarmService.FindAlarmSeqLast(neInfo.NeType, neInfo.NeId) - lastTime := neInfo.UpdateTime // 网元最后更新时间 - if lastTime < neInfo.CreateTime { - lastTime = time.Now().UnixMilli() - } - alarm := neDataModel.Alarm{ - NeType: neInfo.NeType, - NeId: neInfo.NeId, - NeName: neInfo.NeName, - Province: neInfo.Province, - PvFlag: neInfo.PvFlag, - AlarmSeq: lastSeq + 1, - AlarmId: v.AlarmId, - AlarmTitle: v.AlarmTitle, - AlarmCode: constants.ALARM_STATE_CHECK, - EventTime: lastTime, - AlarmType: v.AlarmType, - OrigSeverity: v.OrigSeverity, - PerceivedSeverity: v.OrigSeverity, - ObjectUid: neInfo.RmUID, - ObjectName: "NE State", - ObjectType: "state", - LocationInfo: "NE State: Heartbeat", - AlarmStatus: "1", // 活动告警 - SpecificProblem: v.SpecificProblem, - SpecificProblemId: v.SpecificProblemID, - AddInfo: v.AddInfo, - } - insertId := s.alarmService.InsertAndForword(alarm) - if insertId > 0 { - alarm.ID = insertId - return alarm, nil - } - return neDataModel.Alarm{}, fmt.Errorf("new alarm fail") -} diff --git a/src/modules/crontask/processor/ne_alarm_state_check_cmd/ne_alarm_state_check_cmd.go b/src/modules/crontask/processor/ne_alarm_state_check_cmd/ne_alarm_state_check_cmd.go index 6a622081..2d7fc89e 100644 --- a/src/modules/crontask/processor/ne_alarm_state_check_cmd/ne_alarm_state_check_cmd.go +++ b/src/modules/crontask/processor/ne_alarm_state_check_cmd/ne_alarm_state_check_cmd.go @@ -10,6 +10,8 @@ import ( "sync" "time" + "github.com/tsmask/go-oam" + "be.ems/src/framework/constants" "be.ems/src/framework/cron" "be.ems/src/framework/logger" @@ -18,6 +20,7 @@ import ( neDataService "be.ems/src/modules/network_data/service" neModel "be.ems/src/modules/network_element/model" neService "be.ems/src/modules/network_element/service" + oamService "be.ems/src/modules/oam/service" wsService "be.ems/src/modules/ws/service" ) @@ -28,22 +31,18 @@ var ( ) var NewProcessor = &NeAlarmStateCheckCMDProcessor{ - neConfigBackupService: neService.NewNeConfigBackup, - neInfoService: neService.NewNeInfo, - neStateService: neDataService.NewNEState, - alarmService: neDataService.NewAlarm, - wsSendService: wsService.NewWSSend, - count: 0, + neInfoService: neService.NewNeInfo, + neStateService: neDataService.NewNEState, + wsSendService: wsService.NewWSSend, + count: 0, } // NeAlarmStateCheckCMDProcessor 网元告警内存/CPU/磁盘检查 type NeAlarmStateCheckCMDProcessor struct { - neConfigBackupService *neService.NeConfigBackup // 网元配置文件备份记录服务 - neInfoService *neService.NeInfo // 网元信息服务 - neStateService *neDataService.NEState // 网元状态信息服务 - alarmService *neDataService.Alarm // 告警信息服务 - wsSendService *wsService.WSSend // ws发送服务 - count int // 执行次数 + neInfoService *neService.NeInfo // 网元信息服务 + neStateService *neDataService.NEState // 网元状态信息服务 + wsSendService *wsService.WSSend // ws发送服务 + count int // 执行次数 } // alarmParams 告警参数 @@ -103,65 +102,83 @@ func (s *NeAlarmStateCheckCMDProcessor) Execute(data any) (any, error) { } // 检查状态 - err := s.serverState(neInfo.ServerState, params.CPUUseGt, params.MemUseGt, params.DiskUseGt) + sysCpuUsage, sysMemUsage, sysDiskUsage := s.serverState(neInfo.ServerState) + // 检查CPU/Menory/Disk使用率 + warnMsg := []string{} + if int64(sysCpuUsage) >= params.CPUUseGt { + warnMsg = append(warnMsg, fmt.Sprintf("cpu usage %.2f%%", sysCpuUsage)) + } + if int64(sysMemUsage) >= params.MemUseGt { + warnMsg = append(warnMsg, fmt.Sprintf("memory usage %.2f%%", sysMemUsage)) + } + if int64(sysDiskUsage) >= params.DiskUseGt { + warnMsg = append(warnMsg, fmt.Sprintf("disk usage %.2f%%", sysDiskUsage)) + } + var err error + if len(warnMsg) > 0 { + currentTime := time.Now() + validTimes := []time.Time{} + if v, ok := triggerCount.Load(neInfo.RmUID); ok { + times := v.([]time.Time) + // 清理过期的记录:10秒前的触发记录不再计入 + for _, t := range times { + if currentTime.Sub(t) <= triggerWindow { + validTimes = append(validTimes, t) + } + } + validTimes = append(validTimes, currentTime) + triggerCount.Store(neInfo.RmUID, validTimes) + } else { + // 事件第一次触发,初始化记录 + validTimes = append(validTimes, currentTime) + triggerCount.Store(neInfo.RmUID, validTimes) + } + if int64(len(validTimes)) >= triggerMax { + err = fmt.Errorf("greater than %s", strings.Join(warnMsg, ", ")) + } + } + + // 检查状态连续触发 if err == nil { continue } + if params.AddInfo != "" { + params.AddInfo = params.AddInfo + ", " + err.Error() + } else { + params.AddInfo = err.Error() + } - neTypeAndId := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId) + // 事件产生时间 + alarmTime := time.Now().UnixMilli() // 告警ID - params.AlarmId = fmt.Sprintf("%d%d", constants.ALARM_CMD_CHECK, neInfo.CreateTime) - // 检查网元告警ID是否唯一 - alarmIdArr := s.alarmService.Find(neDataModel.Alarm{ - NeType: neInfo.NeType, - NeId: neInfo.NeId, - AlarmId: params.AlarmId, - }) - // 告警状态, 存在的需要手动清除 - alarmStatus := "" - if len(alarmIdArr) > 0 { - alarmStatus = fmt.Sprint(alarmIdArr[0].AlarmStatus) + params.AlarmId = fmt.Sprintf("%d%d", constants.ALARM_CMD_CHECK, alarmTime) + // 创建告警 + alarm := oam.Alarm{ + NeUid: neInfo.RmUID, // 网元唯一标识 + AlarmTime: alarmTime, // 事件产生时间 + AlarmId: params.AlarmId, // 告警ID 唯一,清除时对应 + AlarmCode: constants.ALARM_CMD_CHECK, // 告警状态码 + AlarmType: params.AlarmType, // 告警类型 + AlarmTitle: params.AlarmTitle, // 告警标题 + PerceivedSeverity: params.OrigSeverity, // 告警级别 + AlarmStatus: oam.ALARM_STATUS_ACTIVE, // 告警状态 + SpecificProblem: params.SpecificProblem, // 告警问题原因 + SpecificProblemID: params.SpecificProblemID, // 告警问题原因ID + AddInfo: params.AddInfo, // 告警辅助信息 + LocationInfo: "NE CPU/Menory/Disk: Heartbeat", // 告警定位信息 } - // 活动告警进行清除 - if alarmStatus == "1" { - clearAlarm, err := s.alarmClear(neInfo, alarmIdArr[0]) - if err != nil { - result[neTypeAndId] = err.Error() - continue - } - groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId) - s.wsSendService.ByGroupID(groupID, clearAlarm) - result[neTypeAndId] = "alarm clear" - alarmStatus = "" // 标记为未记录再次发起新告警 - } - // 未记录 - if alarmStatus == "" { - addInfo := params.AddInfo - if params.AddInfo != "" { - params.AddInfo = params.AddInfo + ", " + err.Error() - } else { - params.AddInfo = err.Error() - } - // 进行新增 - newAlarm, err := s.alarmNew(neInfo, params) - params.AddInfo = addInfo // 恢复附加信息 - triggerCount.Clear() // 重置连续触发次数 - if err != nil { - result[neTypeAndId] = err.Error() - continue - } - groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId) - s.wsSendService.ByGroupID(groupID, newAlarm) - result[neTypeAndId] = "alarm new" + if err = oamService.NewAlarm.Resolve(alarm); err == nil { + result[neInfo.RmUID] = "cmd alarm" } + triggerCount.Delete(neInfo.RmUID) } // 返回结果,用于记录执行结果 return result, nil } -// serverState 网元状态 -func (s NeAlarmStateCheckCMDProcessor) serverState(state map[string]any, cpuUseGt, memUseGt, diskUseGt int64) error { +// serverState 网元状态记录 +func (s NeAlarmStateCheckCMDProcessor) serverState(state map[string]any) (float64, float64, float64) { // 网元CPU使用率 var nfCpuUsage float64 = 0 // CPU使用率 @@ -224,94 +241,5 @@ func (s NeAlarmStateCheckCMDProcessor) serverState(state map[string]any, cpuUseG groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_NE_STATE, neState.NeType, neState.NeId) s.wsSendService.ByGroupID(groupID, neState) - // 检查CPU/Menory/Disk使用率 - warnMsg := []string{} - if int64(sysCpuUsage) >= cpuUseGt { - warnMsg = append(warnMsg, fmt.Sprintf("cpu usage %.2f%%", sysCpuUsage)) - } - if int64(sysMemUsage) >= memUseGt { - warnMsg = append(warnMsg, fmt.Sprintf("memory usage %.2f%%", sysMemUsage)) - } - if int64(sysDiskUsage) >= diskUseGt { - warnMsg = append(warnMsg, fmt.Sprintf("disk usage %.2f%%", sysDiskUsage)) - } - if len(warnMsg) > 0 { - currentTime := time.Now() - neTypeAndId := fmt.Sprintf("%s_%s", neState.NeType, neState.NeId) - validTimes := []time.Time{} - if v, ok := triggerCount.Load(neTypeAndId); ok { - times := v.([]time.Time) - // 清理过期的记录:10秒前的触发记录不再计入 - for _, t := range times { - if currentTime.Sub(t) <= triggerWindow { - validTimes = append(validTimes, t) - } - } - validTimes = append(validTimes, currentTime) - triggerCount.Store(neTypeAndId, validTimes) - } else { - // 事件第一次触发,初始化记录 - validTimes = append(validTimes, currentTime) - triggerCount.Store(neTypeAndId, validTimes) - } - if int64(len(validTimes)) >= triggerMax { - return fmt.Errorf("greater than %s", strings.Join(warnMsg, ", ")) - } - } - return nil -} - -// alarmClear 清除告警 -func (s NeAlarmStateCheckCMDProcessor) alarmClear(neInfo neModel.NeInfo, v neDataModel.Alarm) (neDataModel.Alarm, error) { - // 变更告警ID为告警清除ID - v.AlarmId = fmt.Sprintf("%d%d", v.AlarmCode, v.EventTime) - v.AlarmStatus = "0" - // 告警清除 - v.ClearType = 1 - v.ClearTime = neInfo.UpdateTime - v.ClearUser = "system" - rows := s.alarmService.Update(v) - if rows > 0 { - return v, nil - } - return neDataModel.Alarm{}, fmt.Errorf("clear alarm fail") -} - -// alarmNew 新增告警 -func (s NeAlarmStateCheckCMDProcessor) alarmNew(neInfo neModel.NeInfo, v alarmParams) (neDataModel.Alarm, error) { - // seq 告警序号 - lastSeq := s.alarmService.FindAlarmSeqLast(neInfo.NeType, neInfo.NeId) - lastTime := neInfo.UpdateTime // 网元最后更新时间 - if lastTime < neInfo.CreateTime { - lastTime = time.Now().UnixMilli() - } - alarm := neDataModel.Alarm{ - NeType: neInfo.NeType, - NeId: neInfo.NeId, - NeName: neInfo.NeName, - Province: neInfo.Province, - PvFlag: neInfo.PvFlag, - AlarmSeq: lastSeq + 1, - AlarmId: v.AlarmId, - AlarmTitle: v.AlarmTitle, - AlarmCode: constants.ALARM_CMD_CHECK, - EventTime: lastTime, - AlarmType: v.AlarmType, - OrigSeverity: v.OrigSeverity, - PerceivedSeverity: v.OrigSeverity, - ObjectUid: neInfo.RmUID, - ObjectName: "NE CPU/Menory/Disk", - ObjectType: "cmd", - LocationInfo: "NE CPU/Menory/Disk: Heartbeat", - AlarmStatus: "1", // 活动告警 - SpecificProblem: v.SpecificProblem, - SpecificProblemId: v.SpecificProblemID, - AddInfo: v.AddInfo, - } - insertId := s.alarmService.InsertAndForword(alarm) - if insertId > 0 { - alarm.ID = insertId - return alarm, nil - } - return neDataModel.Alarm{}, fmt.Errorf("new alarm fail") + return sysCpuUsage, sysMemUsage, sysDiskUsage } diff --git a/src/modules/crontask/processor/ne_alarm_state_check_license/ne_alarm_state_check_license.go b/src/modules/crontask/processor/ne_alarm_state_check_license/ne_alarm_state_check_license.go index 761fad13..a5ae5411 100644 --- a/src/modules/crontask/processor/ne_alarm_state_check_license/ne_alarm_state_check_license.go +++ b/src/modules/crontask/processor/ne_alarm_state_check_license/ne_alarm_state_check_license.go @@ -10,29 +10,22 @@ import ( "be.ems/src/framework/cron" "be.ems/src/framework/logger" "be.ems/src/framework/utils/parse" + "github.com/tsmask/go-oam" - neDataModel "be.ems/src/modules/network_data/model" - neDataService "be.ems/src/modules/network_data/service" neModel "be.ems/src/modules/network_element/model" neService "be.ems/src/modules/network_element/service" - wsService "be.ems/src/modules/ws/service" + oamService "be.ems/src/modules/oam/service" ) var NewProcessor = &NeAlarmStateCheckLicenseProcessor{ - neConfigBackupService: neService.NewNeConfigBackup, - neInfoService: neService.NewNeInfo, - alarmService: neDataService.NewAlarm, - wsSendService: wsService.NewWSSend, - count: 0, + neInfoService: neService.NewNeInfo, + count: 0, } // NeAlarmStateCheckLicenseProcessor 网元告警License到期检查 type NeAlarmStateCheckLicenseProcessor struct { - neConfigBackupService *neService.NeConfigBackup // 网元配置文件备份记录服务 - neInfoService *neService.NeInfo // 网元信息服务 - alarmService *neDataService.Alarm // 告警信息服务 - wsSendService *wsService.WSSend // ws发送服务 - count int // 执行次数 + neInfoService *neService.NeInfo // 网元信息服务 + count int // 执行次数 } // alarmParams 告警参数 @@ -83,7 +76,7 @@ func (s *NeAlarmStateCheckLicenseProcessor) Execute(data any) (any, error) { } // 检查状态 - err := s.serverState(neInfo.ServerState, params.DayLt) + err := s.cheackState(neInfo.ServerState, params.DayLt) if err == nil { continue } @@ -93,50 +86,25 @@ func (s *NeAlarmStateCheckLicenseProcessor) Execute(data any) (any, error) { params.AddInfo = err.Error() } - neTypeAndId := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId) // 告警ID params.AlarmId = fmt.Sprintf("%d%d", constants.ALARM_LICENSE_CHECK, neInfo.CreateTime) - // 检查网元告警ID是否唯一 - alarmIdArr := s.alarmService.Find(neDataModel.Alarm{ - NeType: neInfo.NeType, - NeId: neInfo.NeId, - AlarmId: params.AlarmId, - }) - // 告警状态, 存在的需要手动清除 - alarmStatus := "" - if len(alarmIdArr) > 0 { - alarmStatus = fmt.Sprint(alarmIdArr[0].AlarmStatus) + // 创建告警 + alarm := oam.Alarm{ + NeUid: neInfo.RmUID, // 网元唯一标识 + AlarmTime: time.Now().UnixMilli(), // 事件产生时间 + AlarmId: params.AlarmId, // 告警ID 唯一,清除时对应 + AlarmCode: constants.ALARM_LICENSE_CHECK, // 告警状态码 + AlarmType: params.AlarmType, // 告警类型 + AlarmTitle: params.AlarmTitle, // 告警标题 + PerceivedSeverity: params.OrigSeverity, // 告警级别 + AlarmStatus: oam.ALARM_STATUS_ACTIVE, // 告警状态 + SpecificProblem: params.SpecificProblem, // 告警问题原因 + SpecificProblemID: params.SpecificProblemID, // 告警问题原因ID + AddInfo: params.AddInfo, // 告警辅助信息 + LocationInfo: "NE License: Heartbeat", // 告警定位信息 } - // 活动告警进行清除 - if alarmStatus == "1" { - clearAlarm, err := s.alarmClear(neInfo, alarmIdArr[0]) - if err != nil { - result[neTypeAndId] = err.Error() - continue - } - groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId) - s.wsSendService.ByGroupID(groupID, clearAlarm) - result[neTypeAndId] = "alarm clear" - alarmStatus = "" // 标记为未记录再次发起新告警 - } - // 未记录 - if alarmStatus == "" { - addInfo := params.AddInfo - if params.AddInfo != "" { - params.AddInfo = params.AddInfo + ", " + err.Error() - } else { - params.AddInfo = err.Error() - } - // 进行新增 - newAlarm, err := s.alarmNew(neInfo, params) - params.AddInfo = addInfo // 恢复附加信息 - if err != nil { - result[neTypeAndId] = err.Error() - continue - } - groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId) - s.wsSendService.ByGroupID(groupID, newAlarm) - result[neTypeAndId] = "alarm new" + if err = oamService.NewAlarm.Resolve(alarm); err == nil { + result[neInfo.RmUID] = "license alarm" } } @@ -144,8 +112,8 @@ func (s *NeAlarmStateCheckLicenseProcessor) Execute(data any) (any, error) { return result, nil } -// serverState 网元状态 -func (s NeAlarmStateCheckLicenseProcessor) serverState(state map[string]any, dayLt int64) error { +// cheackState 检查网元状态 +func (s NeAlarmStateCheckLicenseProcessor) cheackState(state map[string]any, dayLt int64) error { expire := fmt.Sprint(state["expire"]) if expire == "" || expire == "" || expire == "-" || expire == "2099-12-31" { return nil @@ -168,58 +136,3 @@ func (s NeAlarmStateCheckLicenseProcessor) serverState(state map[string]any, day } return nil } - -// alarmClear 清除告警 -func (s NeAlarmStateCheckLicenseProcessor) alarmClear(neInfo neModel.NeInfo, v neDataModel.Alarm) (neDataModel.Alarm, error) { - // 变更告警ID为告警清除ID - v.AlarmId = fmt.Sprintf("%d%d", v.AlarmCode, v.EventTime) - v.AlarmStatus = "0" - // 告警清除 - v.ClearType = 1 - v.ClearTime = neInfo.UpdateTime - v.ClearUser = "system" - rows := s.alarmService.Update(v) - if rows > 0 { - return v, nil - } - return neDataModel.Alarm{}, fmt.Errorf("clear alarm fail") -} - -// alarmNew 新增告警 -func (s NeAlarmStateCheckLicenseProcessor) alarmNew(neInfo neModel.NeInfo, v alarmParams) (neDataModel.Alarm, error) { - // seq 告警序号 - lastSeq := s.alarmService.FindAlarmSeqLast(neInfo.NeType, neInfo.NeId) - lastTime := neInfo.UpdateTime // 网元最后更新时间 - if lastTime < neInfo.CreateTime { - lastTime = time.Now().UnixMilli() - } - alarm := neDataModel.Alarm{ - NeType: neInfo.NeType, - NeId: neInfo.NeId, - NeName: neInfo.NeName, - Province: neInfo.Province, - PvFlag: neInfo.PvFlag, - AlarmSeq: lastSeq + 1, - AlarmId: v.AlarmId, - AlarmTitle: v.AlarmTitle, - AlarmCode: constants.ALARM_LICENSE_CHECK, - EventTime: lastTime, - AlarmType: v.AlarmType, - OrigSeverity: v.OrigSeverity, - PerceivedSeverity: v.OrigSeverity, - ObjectUid: neInfo.RmUID, - ObjectName: "NE License", - ObjectType: "license", - LocationInfo: "NE License: Heartbeat", - AlarmStatus: "1", // 活动告警 - SpecificProblem: v.SpecificProblem, - SpecificProblemId: v.SpecificProblemID, - AddInfo: v.AddInfo, - } - insertId := s.alarmService.InsertAndForword(alarm) - if insertId > 0 { - alarm.ID = insertId - return alarm, nil - } - return neDataModel.Alarm{}, fmt.Errorf("new alarm fail") -} diff --git a/src/modules/network_data/controller/all_alarm.go b/src/modules/network_data/controller/all_alarm.go index c2918524..b9e41d99 100644 --- a/src/modules/network_data/controller/all_alarm.go +++ b/src/modules/network_data/controller/all_alarm.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "be.ems/src/framework/constants" "be.ems/src/framework/i18n" "be.ems/src/framework/reqctx" "be.ems/src/framework/resp" @@ -107,7 +108,7 @@ func (s AlarmController) Clear(c *gin.Context) { } clearUser := reqctx.LoginUserToUserName(c) - rows, err := s.alarmService.AlarmClearByIds(body.Ids, clearUser) + rows, err := s.alarmService.ClearByIds(body.Ids, clearUser, constants.ALARM_CLEAR_TYPE_MANUAL_CLEAR) if err != nil { c.JSON(200, resp.ErrMsg(err.Error())) return @@ -130,7 +131,7 @@ func (s AlarmController) Ack(c *gin.Context) { } ackUser := reqctx.LoginUserToUserName(c) - rows, err := s.alarmService.AlarmAckByIds(body.Ids, ackUser, body.AckState) + rows, err := s.alarmService.AckByIds(body.Ids, ackUser, constants.ALARM_ACK_STATE_ACK) if err != nil { c.JSON(200, resp.ErrMsg(err.Error())) return diff --git a/src/modules/network_data/model/alarm.go b/src/modules/network_data/model/alarm.go index 61abd550..d0a2e104 100644 --- a/src/modules/network_data/model/alarm.go +++ b/src/modules/network_data/model/alarm.go @@ -8,26 +8,26 @@ type Alarm struct { NeName string `json:"neName" gorm:"column:ne_name"` // 网元名称 Province string `json:"province" gorm:"column:province"` // 网元省份地域 PvFlag string `json:"pvFlag" gorm:"column:pv_flag"` // 网元标识虚拟化标识 - AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 同网元类型连续递增 + AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 连续递增 AlarmId string `json:"alarmId" gorm:"column:alarm_id"` // 告警ID AlarmTitle string `json:"alarmTitle" gorm:"column:alarm_title"` // 告警标题 AlarmCode int64 `json:"alarmCode" gorm:"column:alarm_code"` // 告警状态码 - EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 秒级 - AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型 CommunicationAlarm=1,EquipmentAlarm=2,ProcessingFailure=3,EnvironmentalAlarm=4,QualityOfServiceAlarm=5 - OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF) - PerceivedSeverity string `json:"perceivedSeverity" gorm:"column:perceived_severity"` // 告警级别 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF) + EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 + AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型 + OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度 + PerceivedSeverity string `json:"perceivedSeverity" gorm:"column:perceived_severity"` // 告警级别 ObjectUid string `json:"objectUid" gorm:"column:object_uid"` // 对象ID ObjectName string `json:"objectName" gorm:"column:object_name"` // 对象名称 ObjectType string `json:"objectType" gorm:"column:object_type"` // 对象类型 LocationInfo string `json:"locationInfo" gorm:"column:location_info"` // 告警定位信息 - AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 0:clear, 1:active + AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 SpecificProblem string `json:"specificProblem" gorm:"column:specific_problem"` // 告警问题原因 SpecificProblemId string `json:"specificProblemId" gorm:"column:specific_problem_id"` // 告警问题原因ID AddInfo string `json:"addInfo" gorm:"column:add_info"` // 告警辅助信息 - AckState int64 `json:"ackState" gorm:"column:ack_state"` // 确认状态 0: Unacked, 1: Acked - AckTime int64 `json:"ackTime" gorm:"column:ack_time"` // 确认时间 秒级 + AckState string `json:"ackState" gorm:"column:ack_state"` // 确认状态 + AckTime int64 `json:"ackTime" gorm:"column:ack_time"` // 确认时间 AckUser string `json:"ackUser" gorm:"column:ack_user"` // 确认用户 - ClearType int64 `json:"clearType" gorm:"column:clear_type"` // 清除状态 0: Unclear, 1: AutoClear, 2: ManualClear + ClearType string `json:"clearType" gorm:"column:clear_type"` // 清除状态 ClearTime int64 `json:"clearTime" gorm:"column:clear_time"` // 清除时间 ClearUser string `json:"clearUser" gorm:"column:clear_user"` // 清除用户 Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 创建时间 @@ -46,9 +46,9 @@ type AlarmQuery struct { PvFlag string `json:"pvFlag" form:"pvFlag"` AlarmCode string `json:"alarmCode" form:"alarmCode"` AlarmType string `json:"alarmType" form:"alarmType"` - AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=0 1"` // 告警状态 0:clear, 1:active - OrigSeverity string `json:"origSeverity" form:"origSeverity"` // 告警类型 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF) - BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time + AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=Clear Active"` // 告警状态 + OrigSeverity string `json:"origSeverity" form:"origSeverity"` // 告警类型 + BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time EndTime int64 `json:"endTime" form:"endTime"` SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=event_time id"` // 排序字段,填写结果字段 SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc diff --git a/src/modules/network_data/model/alarm_event.go b/src/modules/network_data/model/alarm_event.go index e1190720..d157f0e3 100644 --- a/src/modules/network_data/model/alarm_event.go +++ b/src/modules/network_data/model/alarm_event.go @@ -9,16 +9,16 @@ type AlarmEvent struct { AlarmId string `json:"alarmId" gorm:"column:alarm_id"` // 告警ID AlarmTitle string `json:"alarmTitle" gorm:"column:alarm_title"` // 告警标题 AlarmCode int64 `json:"alarmCode" gorm:"column:alarm_code"` // 告警状态码 - EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 秒级 + EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 ObjectUid string `json:"objectUid" gorm:"column:object_uid"` // 对象ID ObjectName string `json:"objectName" gorm:"column:object_name"` // 对象名称 ObjectType string `json:"objectType" gorm:"column:object_type"` // 对象类型 LocationInfo string `json:"locationInfo" gorm:"column:location_info"` // 告警定位信息 - AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 0:clear, 1:active + AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 SpecificProblem string `json:"specificProblem" gorm:"column:specific_problem"` // 告警问题原因 SpecificProblemId string `json:"specificProblemId" gorm:"column:specific_problem_id"` // 告警问题原因ID AddInfo string `json:"addInfo" gorm:"column:add_info"` // 告警辅助信息 - ClearType int64 `json:"clearType" gorm:"column:clear_type"` // 清除状态 0: Unclear, 1: AutoClear, 2: ManualClear + ClearType string `json:"clearType" gorm:"column:clear_type"` // 清除状态 ClearTime int64 `json:"clearTime" gorm:"column:clear_time"` // 清除时间 ClearUser string `json:"clearUser" gorm:"column:clear_user"` // 清除用户 Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 创建时间 @@ -34,8 +34,8 @@ type AlarmEventQuery struct { NeType string `json:"neType" form:"neType"` // 网元类型 NeID string `json:"neId" form:"neId"` // 网元ID AlarmCode string `json:"alarmCode" form:"alarmCode"` - AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=0 1"` // 告警状态 0:clear, 1:active - BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time + AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=Clear Active"` // 告警状态 + BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time EndTime int64 `json:"endTime" form:"endTime"` SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=event_time id"` // 排序字段,填写结果字段 SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc diff --git a/src/modules/network_data/model/alarm_forward_log.go b/src/modules/network_data/model/alarm_forward_log.go index a79c6d1b..93e9bb11 100644 --- a/src/modules/network_data/model/alarm_forward_log.go +++ b/src/modules/network_data/model/alarm_forward_log.go @@ -5,16 +5,16 @@ type AlarmForwardLog struct { ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` NeType string `json:"neType" gorm:"column:ne_type"` NeId string `json:"neId" gorm:"column:ne_id"` - AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 同网元类型连续递增 + AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 连续递增 AlarmId string `json:"alarmId" gorm:"column:alarm_id"` // 告警ID AlarmCode int64 `json:"alarmCode" gorm:"column:alarm_code"` // 告警状态码 AlarmTitle string `json:"alarmTitle" gorm:"column:alarm_title"` // 告警标题 - AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 0:clear, 1:active - AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型 CommunicationAlarm=1,EquipmentAlarm=2,ProcessingFailure=3,EnvironmentalAlarm=4,QualityOfServiceAlarm=5 - OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF) - EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 秒级 + AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 + AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型 + OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度 + EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 创建时间 - Type string `json:"type" gorm:"column:type"` // 转发方式 SMS/EMAIL + Type string `json:"type" gorm:"column:type"` // 转发方式 SMS/EMAIL/SMSC Target string `json:"target" gorm:"column:target"` // 发送目标用户 Result string `json:"result" gorm:"column:result"` // 发送结果 } @@ -28,7 +28,7 @@ func (*AlarmForwardLog) TableName() string { type AlarmForwardLogQuery struct { NeType string `json:"neType" form:"neType"` // 网元类型 NeID string `json:"neId" form:"neId"` // 网元ID - BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time + BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 EndTime int64 `json:"endTime" form:"endTime"` SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=event_time id"` // 排序字段,填写结果字段 SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc diff --git a/src/modules/network_data/model/alarm_log.go b/src/modules/network_data/model/alarm_log.go index 8931daf4..841308bd 100644 --- a/src/modules/network_data/model/alarm_log.go +++ b/src/modules/network_data/model/alarm_log.go @@ -5,14 +5,14 @@ type AlarmLog struct { ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` NeType string `json:"neType" gorm:"column:ne_type"` NeId string `json:"neId" gorm:"column:ne_id"` - AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 同网元类型连续递增 + AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 连续递增 AlarmId string `json:"alarmId" gorm:"column:alarm_id"` // 告警ID AlarmCode int64 `json:"alarmCode" gorm:"column:alarm_code"` // 告警状态码 AlarmTitle string `json:"alarmTitle" gorm:"column:alarm_title"` // 告警标题 - AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 0:clear, 1:active - AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型 CommunicationAlarm=1,EquipmentAlarm=2,ProcessingFailure=3,EnvironmentalAlarm=4,QualityOfServiceAlarm=5 - OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF) - EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 秒级 + AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 + AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型 + OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度 + EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 创建时间 } @@ -23,11 +23,11 @@ func (*AlarmLog) TableName() string { // AlarmLogQuery 告警日志数据查询参数结构体 type AlarmLogQuery struct { - NeType string `json:"neType" form:"neType"` // 网元类型 - NeID string `json:"neId" form:"neId"` // 网元ID - AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=0 1"` // 告警状态 0:clear, 1:active - OrigSeverity string `json:"origSeverity" form:"origSeverity"` // 告警类型 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF) - BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time + NeType string `json:"neType" form:"neType"` // 网元类型 + NeID string `json:"neId" form:"neId"` // 网元ID + AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=Clear Active"` // 告警状态 + OrigSeverity string `json:"origSeverity" form:"origSeverity"` // 告警类型 + BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time EndTime int64 `json:"endTime" form:"endTime"` SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=event_time id"` // 排序字段,填写结果字段 SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc diff --git a/src/modules/network_data/service/alarm.go b/src/modules/network_data/service/alarm.go index bb98a45a..737acb0b 100644 --- a/src/modules/network_data/service/alarm.go +++ b/src/modules/network_data/service/alarm.go @@ -5,6 +5,8 @@ import ( "strconv" "time" + "github.com/tsmask/go-oam" + "be.ems/src/framework/constants" "be.ems/src/framework/i18n" "be.ems/src/framework/utils/date" @@ -65,8 +67,8 @@ func (s Alarm) FindAlarmSeqLast(neType, neId string) int64 { return s.alarmRepository.SelectAlarmSeqLast(neType, neId) } -// AlarmClearByIds 批量清除告警信息 -func (r Alarm) AlarmClearByIds(ids []int64, clearUser string) (int64, error) { +// ClearByIds 批量清除告警信息 +func (r Alarm) ClearByIds(ids []int64, clearUser, clearType string) (int64, error) { // 检查是否存在 arr := r.alarmRepository.SelectByIds(ids) if len(arr) <= 0 { @@ -80,21 +82,20 @@ func (r Alarm) AlarmClearByIds(ids []int64, clearUser string) (int64, error) { if v.AlarmCode == constants.ALARM_STATE_CHECK || v.AlarmCode == constants.ALARM_CMD_CHECK || v.AlarmCode == constants.ALARM_LICENSE_CHECK { v.AlarmId = fmt.Sprintf("%d%d", v.AlarmCode, v.EventTime) } - v.AlarmStatus = "0" + v.AlarmStatus = oam.ALARM_STATUS_CLEAR // 告警清除 - v.ClearType = 2 - v.ClearTime = time.Now().UnixMilli() + v.ClearType = clearType v.ClearUser = clearUser + v.ClearTime = time.Now().UnixMilli() rows += r.alarmRepository.Update(v) } return rows, nil } - // 清除失败! return 0, fmt.Errorf("clear fail") } -// AlarmAckByIds 批量确认清除告警信息 -func (r Alarm) AlarmAckByIds(ids []int64, ackUser string, ackState bool) (int64, error) { +// AckByIds 批量确认清除告警信息 +func (r Alarm) AckByIds(ids []int64, ackUser, ackState string) (int64, error) { // 检查是否存在 arr := r.alarmRepository.SelectByIds(ids) if len(arr) <= 0 { @@ -104,19 +105,13 @@ func (r Alarm) AlarmAckByIds(ids []int64, ackUser string, ackState bool) (int64, if len(arr) == len(ids) { var rows int64 = 0 for _, v := range arr { - // 确认清除 - if ackState { - v.AckState = 1 - } else { - v.AckState = 0 - } + v.AckState = ackState v.AckTime = time.Now().UnixMilli() v.AckUser = ackUser rows += r.alarmRepository.Update(v) } return rows, nil } - // 清除失败! return 0, fmt.Errorf("ack fail") } diff --git a/src/modules/network_data/service/alarm_event.go b/src/modules/network_data/service/alarm_event.go index e3413d81..4779e4b4 100644 --- a/src/modules/network_data/service/alarm_event.go +++ b/src/modules/network_data/service/alarm_event.go @@ -2,6 +2,9 @@ package service import ( "fmt" + "time" + + "github.com/tsmask/go-oam" "be.ems/src/modules/network_data/model" "be.ems/src/modules/network_data/repository" @@ -9,44 +12,44 @@ import ( // 实例化数据层 AlarmEvent 结构体 var NewAlarmEvent = &AlarmEvent{ - AlarmEventRepository: repository.NewAlarmEvent, + alarmEventRepository: repository.NewAlarmEvent, } // AlarmEvent 告警 服务层处理 type AlarmEvent struct { - AlarmEventRepository *repository.AlarmEvent // 告警数据信息 + alarmEventRepository *repository.AlarmEvent // 告警数据信息 } // FindByPage 根据条件分页查询 func (r AlarmEvent) FindByPage(query model.AlarmEventQuery) ([]model.AlarmEvent, int64) { - return r.AlarmEventRepository.SelectByPage(query) + return r.alarmEventRepository.SelectByPage(query) } // Find 查询 func (r AlarmEvent) Find(param model.AlarmEvent) []model.AlarmEvent { - return r.AlarmEventRepository.Select(param) + return r.alarmEventRepository.Select(param) } // Insert 新增信息 func (s AlarmEvent) Insert(param model.AlarmEvent) int64 { - return s.AlarmEventRepository.Insert(param) + return s.alarmEventRepository.Insert(param) } // Update 修改信息 func (s AlarmEvent) Update(param model.AlarmEvent) int64 { - return s.AlarmEventRepository.Update(param) + return s.alarmEventRepository.Update(param) } // DeleteByIds 批量删除信息 func (r AlarmEvent) DeleteByIds(ids []int64) (int64, error) { // 检查是否存在 - data := r.AlarmEventRepository.SelectByIds(ids) + data := r.alarmEventRepository.SelectByIds(ids) if len(data) <= 0 { return 0, fmt.Errorf("no data") } if len(data) == len(ids) { - rows := r.AlarmEventRepository.DeleteByIds(ids) + rows := r.alarmEventRepository.DeleteByIds(ids) return rows, nil } // 删除信息失败! @@ -55,5 +58,28 @@ func (r AlarmEvent) DeleteByIds(ids []int64) (int64, error) { // FindAlarmEventSeqLast 查询网元告警最后一条序号 func (s AlarmEvent) FindAlarmEventSeqLast(neType, neId string) int64 { - return s.AlarmEventRepository.SelectAlarmEventSeqLast(neType, neId) + return s.alarmEventRepository.SelectAlarmEventSeqLast(neType, neId) +} + +// ClearByIds 批量清除告警信息 +func (r AlarmEvent) ClearByIds(ids []int64, clearUser, clearType string) (int64, error) { + // 检查是否存在 + arr := r.alarmEventRepository.SelectByIds(ids) + if len(arr) <= 0 { + return 0, fmt.Errorf("no data") + } + + if len(arr) == len(ids) { + var rows int64 = 0 + for _, v := range arr { + v.AlarmStatus = oam.ALARM_STATUS_CLEAR + // 告警清除 + v.ClearType = clearType + v.ClearUser = clearUser + v.ClearTime = time.Now().UnixMilli() + rows += r.alarmEventRepository.Update(v) + } + return rows, nil + } + return 0, fmt.Errorf("clear fail") } diff --git a/src/modules/oam/service/alarm.go b/src/modules/oam/service/alarm.go new file mode 100644 index 00000000..0f28e935 --- /dev/null +++ b/src/modules/oam/service/alarm.go @@ -0,0 +1,310 @@ +package service + +import ( + "fmt" + + "be.ems/src/framework/config" + "be.ems/src/framework/constants" + "be.ems/src/framework/logger" + "be.ems/src/framework/utils/parse" + "github.com/tsmask/go-oam" + + neDataModel "be.ems/src/modules/network_data/model" + neDataService "be.ems/src/modules/network_data/service" + neService "be.ems/src/modules/network_element/service" + notificationService "be.ems/src/modules/notification/service" + traceService "be.ems/src/modules/trace/service" + wsService "be.ems/src/modules/ws/service" +) + +// 实例化服务层 Alarm 结构体 +var NewAlarm = &Alarm{ + neInfoService: neService.NewNeInfo, + wsService: wsService.NewWSSend, + alarmService: neDataService.NewAlarm, + alarmEventService: neDataService.NewAlarmEvent, + alarmLogService: neDataService.NewAlarmLog, + alarmForwardLogService: neDataService.NewAlarmForwardLog, +} + +// Alarm 消息处理 +type Alarm struct { + neInfoService *neService.NeInfo + wsService *wsService.WSSend + alarmService *neDataService.Alarm + alarmEventService *neDataService.AlarmEvent + alarmLogService *neDataService.AlarmLog + alarmForwardLogService *neDataService.AlarmForwardLog + + alarm neDataModel.Alarm +} + +// Resolve 接收处理 +func (s *Alarm) Resolve(a oam.Alarm) error { + // 是否存在网元 + neInfo := s.neInfoService.FindByRmuid(a.NeUid) + if neInfo.NeType == "" || neInfo.RmUID != a.NeUid { + logger.Warnf("resolve alarm network element does not exist %s", a.NeUid) + return fmt.Errorf("resolve alarm network element does not exist %s", a.NeUid) + } + + // seq 告警序号 + lastSeq := neDataService.NewAlarm.FindAlarmSeqLast(neInfo.NeType, neInfo.NeId) + + // 告警信息 + s.alarm = neDataModel.Alarm{ + NeType: neInfo.NeType, + NeId: neInfo.NeId, + NeName: neInfo.NeName, + Province: neInfo.Province, + PvFlag: neInfo.PvFlag, + AlarmSeq: lastSeq + 1, + AlarmId: a.AlarmId, + AlarmTitle: a.AlarmTitle, + AlarmCode: int64(a.AlarmCode), + EventTime: a.AlarmTime, + AlarmType: a.AlarmType, + OrigSeverity: a.PerceivedSeverity, + PerceivedSeverity: a.PerceivedSeverity, + ObjectUid: neInfo.RmUID, + ObjectName: neInfo.NeName, + ObjectType: neInfo.NeType, + LocationInfo: a.LocationInfo, + AlarmStatus: a.AlarmStatus, + SpecificProblem: a.SpecificProblem, + SpecificProblemId: a.SpecificProblemID, + AddInfo: a.AddInfo, + } + + // 进行清除 + if a.AlarmStatus == oam.ALARM_STATUS_CLEAR { + if a.AlarmType == oam.ALARM_SEVERITY_EVENT { + if err := s.clearEvent(); err != nil { + logger.Warnf("resolve alarm clear event failed: %s", err.Error()) + return err + } + } else { + if err := s.clear(); err != nil { + logger.Warnf("resolve alarm clear failed: %s", err.Error()) + return err + } + } + + } + // 进行新增 + if a.AlarmStatus == oam.ALARM_STATUS_ACTIVE { + if a.AlarmType == oam.ALARM_SEVERITY_EVENT { + if err := s.addEvent(); err != nil { + logger.Warnf("resolve alarm add event failed: %s", err.Error()) + return err + } + } else { + if err := s.add(); err != nil { + logger.Warnf("resolve alarm add failed: %s", err.Error()) + return err + } + } + } + + // 记录日志 + if err := s.saveLog(); err != nil { + logger.Warnf("resolve alarm save log failed: %s", err.Error()) + return err + } + // 推送 + s.wsService.ByGroupID(fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId), s.alarm) + // 通知 + go s.notify(neInfo.IP) + return nil +} + +// saveLog 记录日志 +func (s *Alarm) saveLog() error { + alarmLog := neDataModel.AlarmLog{ + NeType: s.alarm.NeType, + NeId: s.alarm.NeId, + AlarmSeq: s.alarm.AlarmSeq, + AlarmId: s.alarm.AlarmId, + AlarmTitle: s.alarm.AlarmTitle, + AlarmCode: s.alarm.AlarmCode, + AlarmStatus: s.alarm.AlarmStatus, + AlarmType: s.alarm.AlarmType, + OrigSeverity: s.alarm.PerceivedSeverity, + EventTime: s.alarm.EventTime, + } + insertId := s.alarmLogService.Insert(alarmLog) + if insertId <= 0 { + return fmt.Errorf("save alarm log fail") + } + return nil +} + +// add 新增告警 +func (s *Alarm) add() error { + // 检查网元告警ID是否唯一 + alarmIdArr := s.alarmService.Find(neDataModel.Alarm{ + NeType: s.alarm.NeType, + NeId: s.alarm.NeId, + AlarmId: s.alarm.AlarmId, + }) + if len(alarmIdArr) > 0 { + return fmt.Errorf("already exists alarmId:%s", s.alarm.AlarmId) + } + insertId := s.alarmService.Insert(s.alarm) + if insertId > 0 { + s.alarm.ID = insertId + return nil + } + return fmt.Errorf("add alarm fail") +} + +// clear 清除告警 +func (s *Alarm) clear() error { + // 检查网元告警ID是否唯一 + alarmIdArr := s.alarmService.Find(neDataModel.Alarm{ + NeType: s.alarm.NeType, + NeId: s.alarm.NeId, + AlarmId: s.alarm.AlarmId, + }) + if len(alarmIdArr) != 1 { + return fmt.Errorf("not exists alarmId:%s", s.alarm.AlarmId) + } + + // 告警清除 + rows, _ := s.alarmService.ClearByIds([]int64{alarmIdArr[0].ID}, s.alarm.ObjectUid, constants.ALARM_CLEAR_TYPE_AUTO_CLEAR) + if rows > 0 { + return nil + } + return fmt.Errorf("clear fail alarmId:%s", s.alarm.AlarmId) +} + +// addEvent 新增告警事件 +func (s *Alarm) addEvent() error { + // 检查网元告警ID是否唯一 + alarmIdArr := s.alarmEventService.Find(neDataModel.AlarmEvent{ + NeType: s.alarm.NeType, + NeId: s.alarm.NeId, + AlarmId: s.alarm.AlarmId, + }) + if len(alarmIdArr) > 0 { + return fmt.Errorf("event already exists alarmId:%s", s.alarm.AlarmId) + } + // seq 告警序号 + lastSeq := s.alarmEventService.FindAlarmEventSeqLast(s.alarm.NeType, s.alarm.NeId) + + alarmEvent := neDataModel.AlarmEvent{ + NeType: s.alarm.NeType, + NeId: s.alarm.NeId, + AlarmSeq: lastSeq + 1, + AlarmId: s.alarm.AlarmId, + AlarmTitle: s.alarm.AlarmTitle, + AlarmCode: s.alarm.AlarmCode, + EventTime: s.alarm.EventTime, + ObjectUid: s.alarm.ObjectUid, + ObjectName: s.alarm.ObjectName, + ObjectType: s.alarm.ObjectType, + LocationInfo: s.alarm.LocationInfo, + AlarmStatus: s.alarm.AlarmStatus, + SpecificProblem: s.alarm.SpecificProblem, + SpecificProblemId: s.alarm.SpecificProblemId, + AddInfo: s.alarm.AddInfo, + } + insertId := s.alarmEventService.Insert(alarmEvent) + if insertId > 0 { + alarmEvent.ID = insertId + // 网元重启后,清除活动告警 + if s.alarm.AlarmCode == constants.ALARM_EVENT_REBOOT { + rows := s.alarmService.Find(neDataModel.Alarm{ + NeType: s.alarm.NeType, + NeId: s.alarm.NeId, + AlarmStatus: oam.ALARM_STATUS_ACTIVE, + }) + ids := make([]int64, 0) + for _, v := range rows { + ids = append(ids, v.ID) + } + s.alarmService.ClearByIds(ids, s.alarm.ObjectUid, constants.ALARM_CLEAR_TYPE_AUTO_CLEAR) + } + // 网元重启后,有跟踪任务的需要重新补发启动任务 + if s.alarm.AlarmCode == constants.ALARM_EVENT_REBOOT { + traceService.NewTraceTask.RunUnstopped(s.alarm.NeType, s.alarm.NeId) + } + return nil + } + return fmt.Errorf("event add fail") +} + +// clearEvent 清除告警事件 +func (s *Alarm) clearEvent() error { + alarmEventService := neDataService.NewAlarmEvent + // 检查网元告警ID是否唯一 + alarmIdArr := alarmEventService.Find(neDataModel.AlarmEvent{ + NeType: s.alarm.NeType, + NeId: s.alarm.NeId, + AlarmId: s.alarm.AlarmId, + }) + if len(alarmIdArr) != 1 { + return fmt.Errorf("event not exists alarmId:%s", s.alarm.AlarmId) + } + + // 告警清除 + rows, _ := s.alarmEventService.ClearByIds([]int64{alarmIdArr[0].ID}, s.alarm.ObjectUid, constants.ALARM_CLEAR_TYPE_AUTO_CLEAR) + if rows > 0 { + return nil + } + return fmt.Errorf("event clear fail alarmId:%s", s.alarm.AlarmId) +} + +// notify 通知 +func (s *Alarm) notify(neIp string) { + // 邮箱 + emailEnable := parse.Boolean(config.Get("notification.email.enable")) + if emailEnable { + emailList := fmt.Sprint(config.Get("notification.email.emailList")) + emailResult := "Sent Successfully!" + emailErr := notificationService.EmailAlarm(s.alarm, neIp) + if emailErr != nil { + emailResult = emailErr.Error() + logger.Warnf("alarm notify email failed: %s", emailErr.Error()) + } + s.notifyLog("EMAIL", emailList, emailResult) + } + + // 短信 + smscEnable := parse.Boolean(config.Get("notification.smsc.enable")) + if smscEnable { + mobileList := fmt.Sprint(config.Get("notification.smsc.mobileList")) + smscResult := "Sent Successfully!" + smscErr := notificationService.SMSCAlarm(s.alarm, neIp) + if smscErr != nil { + smscResult = smscErr.Error() + logger.Warnf("alarm notify email failed: %s", smscErr.Error()) + } + s.notifyLog("SMSC", mobileList, smscResult) + } +} + +// notifyLog 通知日志 +func (s *Alarm) notifyLog(forwardBy, toUser, result string) error { + alarmForwardLog := neDataModel.AlarmForwardLog{ + NeType: s.alarm.NeType, + NeId: s.alarm.NeId, + AlarmSeq: s.alarm.AlarmSeq, + AlarmId: s.alarm.AlarmId, + AlarmTitle: s.alarm.AlarmTitle, + AlarmCode: s.alarm.AlarmCode, + AlarmStatus: s.alarm.AlarmStatus, + AlarmType: s.alarm.AlarmType, + OrigSeverity: s.alarm.OrigSeverity, + EventTime: s.alarm.EventTime, + Type: forwardBy, + Target: toUser, + Result: result, + } + // 记录日志 + insertId := s.alarmForwardLogService.Insert(alarmForwardLog) + if insertId <= 0 { + return fmt.Errorf("notify alarm log fail") + } + return nil +}