perf: 重构接收告警功能

This commit is contained in:
TsMask
2025-07-15 14:55:47 +08:00
parent 00e8b63890
commit 6f48e0ae41
12 changed files with 538 additions and 433 deletions

View File

@@ -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" // 告警清除状态-手动清除
)

View File

@@ -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")
}

View File

@@ -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
}

View File

@@ -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 == "<nil>" || 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")
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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
}