mirror of
https://github.com/nezhahq/nezha.git
synced 2025-01-22 20:58:14 -05:00
feat: 报警规则支持绑定触发任务
This commit is contained in:
parent
ceb1b74834
commit
13d1be59b6
@ -612,12 +612,14 @@ func (ma *memberAPI) addOrEditNotification(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type alertRuleForm struct {
|
type alertRuleForm struct {
|
||||||
ID uint64
|
ID uint64
|
||||||
Name string
|
Name string
|
||||||
RulesRaw string
|
RulesRaw string
|
||||||
NotificationTag string
|
FailTriggerTasksRaw string // 失败时触发的任务id
|
||||||
TriggerMode int
|
RecoverTriggerTasksRaw string // 恢复时触发的任务id
|
||||||
Enable string
|
NotificationTag string
|
||||||
|
TriggerMode int
|
||||||
|
Enable string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) {
|
func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) {
|
||||||
@ -657,12 +659,22 @@ func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
r.Name = arf.Name
|
r.Name = arf.Name
|
||||||
r.RulesRaw = arf.RulesRaw
|
r.RulesRaw = arf.RulesRaw
|
||||||
|
r.FailTriggerTasksRaw = arf.FailTriggerTasksRaw
|
||||||
|
r.RecoverTriggerTasksRaw = arf.RecoverTriggerTasksRaw
|
||||||
r.NotificationTag = arf.NotificationTag
|
r.NotificationTag = arf.NotificationTag
|
||||||
enable := arf.Enable == "on"
|
enable := arf.Enable == "on"
|
||||||
r.TriggerMode = arf.TriggerMode
|
r.TriggerMode = arf.TriggerMode
|
||||||
r.Enable = &enable
|
r.Enable = &enable
|
||||||
r.ID = arf.ID
|
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 == "" {
|
if r.NotificationTag == "" {
|
||||||
r.NotificationTag = "default"
|
r.NotificationTag = "default"
|
||||||
}
|
}
|
||||||
|
@ -25,25 +25,49 @@ type CycleTransferStats struct {
|
|||||||
|
|
||||||
type AlertRule struct {
|
type AlertRule struct {
|
||||||
Common
|
Common
|
||||||
Name string
|
Name string
|
||||||
RulesRaw string
|
RulesRaw string
|
||||||
Enable *bool
|
Enable *bool
|
||||||
TriggerMode int `gorm:"default:0"` // 触发模式: 0-始终触发(默认) 1-单次触发
|
TriggerMode int `gorm:"default:0"` // 触发模式: 0-始终触发(默认) 1-单次触发
|
||||||
NotificationTag string // 该报警规则所在的通知组
|
NotificationTag string // 该报警规则所在的通知组
|
||||||
Rules []Rule `gorm:"-" json:"-"`
|
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 {
|
func (r *AlertRule) BeforeSave(tx *gorm.DB) error {
|
||||||
data, err := utils.Json.Marshal(r.Rules)
|
if data, err := utils.Json.Marshal(r.Rules); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AlertRule) AfterFind(tx *gorm.DB) error {
|
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 {
|
func (r *AlertRule) Enabled() bool {
|
||||||
|
@ -162,6 +162,7 @@ func checkStatus() {
|
|||||||
message := fmt.Sprintf("[%s] %s(%s) %s", Localizer.MustLocalize(&i18n.LocalizeConfig{
|
message := fmt.Sprintf("[%s] %s(%s) %s", Localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||||
MessageID: "Incident",
|
MessageID: "Incident",
|
||||||
}), server.Name, IPDesensitize(server.Host.IP), alert.Name)
|
}), server.Name, IPDesensitize(server.Host.IP), alert.Name)
|
||||||
|
go SendTriggerTasks(alert.FailTriggerTasks, curServer.ID)
|
||||||
go SendNotification(alert.NotificationTag, message, true, &curServer)
|
go SendNotification(alert.NotificationTag, message, true, &curServer)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -170,6 +171,7 @@ func checkStatus() {
|
|||||||
message := fmt.Sprintf("[%s] %s(%s) %s", Localizer.MustLocalize(&i18n.LocalizeConfig{
|
message := fmt.Sprintf("[%s] %s(%s) %s", Localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||||
MessageID: "Resolved",
|
MessageID: "Resolved",
|
||||||
}), server.Name, IPDesensitize(server.Host.IP), alert.Name)
|
}), server.Name, IPDesensitize(server.Host.IP), alert.Name)
|
||||||
|
go SendTriggerTasks(alert.RecoverTriggerTasks, curServer.ID)
|
||||||
go SendNotification(alert.NotificationTag, message, true, &curServer)
|
go SendNotification(alert.NotificationTag, message, true, &curServer)
|
||||||
}
|
}
|
||||||
alertsPrevState[alert.ID][server.ID] = _RuleCheckPass
|
alertsPrevState[alert.ID][server.ID] = _RuleCheckPass
|
||||||
|
@ -35,6 +35,7 @@ func LoadCronTasks() {
|
|||||||
for i := 0; i < len(crons); i++ {
|
for i := 0; i < len(crons); i++ {
|
||||||
// 触发任务类型无需注册
|
// 触发任务类型无需注册
|
||||||
if crons[i].TaskType == model.CronTypeTriggerTask {
|
if crons[i].TaskType == model.CronTypeTriggerTask {
|
||||||
|
Crons[crons[i].ID] = &crons[i]
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 旧版本计划任务可能不存在通知组 为其添加默认通知组
|
// 旧版本计划任务可能不存在通知组 为其添加默认通知组
|
||||||
@ -68,6 +69,22 @@ func ManualTrigger(c model.Cron) {
|
|||||||
CronTrigger(c)()
|
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() {
|
func CronTrigger(cr model.Cron, triggerServer ...uint64) func() {
|
||||||
crIgnoreMap := make(map[uint64]bool)
|
crIgnoreMap := make(map[uint64]bool)
|
||||||
for j := 0; j < len(cr.Servers); j++ {
|
for j := 0; j < len(cr.Servers); j++ {
|
||||||
@ -76,7 +93,7 @@ func CronTrigger(cr model.Cron, triggerServer ...uint64) func() {
|
|||||||
return func() {
|
return func() {
|
||||||
if cr.Cover == model.CronCoverSelf {
|
if cr.Cover == model.CronCoverSelf {
|
||||||
if len(triggerServer) == 0 {
|
if len(triggerServer) == 0 {
|
||||||
log.Println("触发任务未指定触发服务器")
|
log.Println("触发任务", cr.Name, "未指定触发服务器")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ServerLock.RLock()
|
ServerLock.RLock()
|
||||||
|
Loading…
Reference in New Issue
Block a user