feat: 报警规则支持绑定触发任务

This commit is contained in:
Akkia 2022-09-14 11:14:23 +08:00
parent ceb1b74834
commit 13d1be59b6
No known key found for this signature in database
GPG Key ID: DABE9A4AB2DD7EF3
4 changed files with 73 additions and 18 deletions

View File

@ -612,12 +612,14 @@ func (ma *memberAPI) addOrEditNotification(c *gin.Context) {
}
type alertRuleForm struct {
ID uint64
Name string
RulesRaw string
NotificationTag string
TriggerMode int
Enable string
ID uint64
Name string
RulesRaw string
FailTriggerTasksRaw string // 失败时触发的任务id
RecoverTriggerTasksRaw string // 恢复时触发的任务id
NotificationTag string
TriggerMode int
Enable string
}
func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) {
@ -657,12 +659,22 @@ func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) {
if err == nil {
r.Name = arf.Name
r.RulesRaw = arf.RulesRaw
r.FailTriggerTasksRaw = arf.FailTriggerTasksRaw
r.RecoverTriggerTasksRaw = arf.RecoverTriggerTasksRaw
r.NotificationTag = arf.NotificationTag
enable := arf.Enable == "on"
r.TriggerMode = arf.TriggerMode
r.Enable = &enable
r.ID = arf.ID
//保证NotificationTag不为空
}
if err == nil {
err = utils.Json.Unmarshal([]byte(arf.FailTriggerTasksRaw), &r.FailTriggerTasks)
}
if err == nil {
err = utils.Json.Unmarshal([]byte(arf.RecoverTriggerTasksRaw), &r.RecoverTriggerTasks)
}
//保证NotificationTag不为空
if err == nil {
if r.NotificationTag == "" {
r.NotificationTag = "default"
}

View File

@ -25,25 +25,49 @@ type CycleTransferStats struct {
type AlertRule struct {
Common
Name string
RulesRaw string
Enable *bool
TriggerMode int `gorm:"default:0"` // 触发模式: 0-始终触发(默认) 1-单次触发
NotificationTag string // 该报警规则所在的通知组
Rules []Rule `gorm:"-" json:"-"`
Name string
RulesRaw string
Enable *bool
TriggerMode int `gorm:"default:0"` // 触发模式: 0-始终触发(默认) 1-单次触发
NotificationTag string // 该报警规则所在的通知组
FailTriggerTasksRaw string
RecoverTriggerTasksRaw string
Rules []Rule `gorm:"-" json:"-"`
FailTriggerTasks []uint64 `gorm:"-" json:"-"` // 失败时执行的触发任务id
RecoverTriggerTasks []uint64 `gorm:"-" json:"-"` // 恢复时执行的触发任务id
}
func (r *AlertRule) BeforeSave(tx *gorm.DB) error {
data, err := utils.Json.Marshal(r.Rules)
if err != nil {
if data, err := utils.Json.Marshal(r.Rules); err != nil {
return err
} else {
r.RulesRaw = string(data)
}
if data, err := utils.Json.Marshal(r.FailTriggerTasks); err != nil {
return err
} else {
r.FailTriggerTasksRaw = string(data)
}
if data, err := utils.Json.Marshal(r.RecoverTriggerTasks); err != nil {
return err
} else {
r.RecoverTriggerTasksRaw = string(data)
}
r.RulesRaw = string(data)
return nil
}
func (r *AlertRule) AfterFind(tx *gorm.DB) error {
return utils.Json.Unmarshal([]byte(r.RulesRaw), &r.Rules)
var err error
if err = utils.Json.Unmarshal([]byte(r.RulesRaw), &r.Rules); err != nil {
return err
}
if err = utils.Json.Unmarshal([]byte(r.FailTriggerTasksRaw), &r.FailTriggerTasks); err != nil {
return err
}
if err = utils.Json.Unmarshal([]byte(r.RecoverTriggerTasksRaw), &r.RecoverTriggerTasks); err != nil {
return err
}
return nil
}
func (r *AlertRule) Enabled() bool {

View File

@ -162,6 +162,7 @@ func checkStatus() {
message := fmt.Sprintf("[%s] %s(%s) %s", Localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: "Incident",
}), server.Name, IPDesensitize(server.Host.IP), alert.Name)
go SendTriggerTasks(alert.FailTriggerTasks, curServer.ID)
go SendNotification(alert.NotificationTag, message, true, &curServer)
}
} else {
@ -170,6 +171,7 @@ func checkStatus() {
message := fmt.Sprintf("[%s] %s(%s) %s", Localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: "Resolved",
}), server.Name, IPDesensitize(server.Host.IP), alert.Name)
go SendTriggerTasks(alert.RecoverTriggerTasks, curServer.ID)
go SendNotification(alert.NotificationTag, message, true, &curServer)
}
alertsPrevState[alert.ID][server.ID] = _RuleCheckPass

View File

@ -35,6 +35,7 @@ func LoadCronTasks() {
for i := 0; i < len(crons); i++ {
// 触发任务类型无需注册
if crons[i].TaskType == model.CronTypeTriggerTask {
Crons[crons[i].ID] = &crons[i]
continue
}
// 旧版本计划任务可能不存在通知组 为其添加默认通知组
@ -68,6 +69,22 @@ func ManualTrigger(c model.Cron) {
CronTrigger(c)()
}
func SendTriggerTasks(taskIDs []uint64, triggerServer uint64) {
CronLock.RLock()
var cronLists []*model.Cron
for _, taskID := range taskIDs {
if c, ok := Crons[taskID]; ok {
cronLists = append(cronLists, c)
}
}
CronLock.RUnlock()
// 依次调用CronTrigger发送任务
for _, c := range cronLists {
go CronTrigger(*c, triggerServer)()
}
}
func CronTrigger(cr model.Cron, triggerServer ...uint64) func() {
crIgnoreMap := make(map[uint64]bool)
for j := 0; j < len(cr.Servers); j++ {
@ -76,7 +93,7 @@ func CronTrigger(cr model.Cron, triggerServer ...uint64) func() {
return func() {
if cr.Cover == model.CronCoverSelf {
if len(triggerServer) == 0 {
log.Println("触发任务未指定触发服务器")
log.Println("触发任务", cr.Name, "未指定触发服务器")
return
}
ServerLock.RLock()