From 9c1d495eb095cee4cf42e80e00cc7d3a336b1845 Mon Sep 17 00:00:00 2001 From: Akkia Date: Thu, 14 Apr 2022 21:06:42 +0800 Subject: [PATCH 1/8] =?UTF-8?q?WIP:=20=E9=80=9A=E7=9F=A5=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E5=88=86=E7=BB=84=20=E6=94=AF=E6=8C=81=E5=B0=86=E4=B8=8D?= =?UTF-8?q?=E5=90=8C=E7=9A=84=E6=8A=A5=E8=AD=A6=EF=BD=9C=E7=9B=91=E6=8E=A7?= =?UTF-8?q?=EF=BD=9C=E8=AE=A1=E5=88=92=E4=BB=BB=E5=8A=A1=E7=9A=84=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=20=E5=8F=91=E9=80=81=E5=88=B0=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E7=9A=84=E9=80=9A=E7=9F=A5=E5=88=86=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/dashboard/controller/member_api.go | 24 +++-- model/config.go | 4 + model/cron.go | 17 ++-- model/notification.go | 1 + resource/template/component/cron.html | 4 + resource/template/component/notification.html | 4 + resource/template/dashboard/cron.html | 2 + resource/template/dashboard/notification.html | 2 + service/rpc/nezha.go | 6 +- service/singleton/crontask.go | 32 +++++-- service/singleton/notification.go | 96 ++++++++++++++----- 11 files changed, 143 insertions(+), 49 deletions(-) diff --git a/cmd/dashboard/controller/member_api.go b/cmd/dashboard/controller/member_api.go index 126f0d17ff..cf5a03f595 100644 --- a/cmd/dashboard/controller/member_api.go +++ b/cmd/dashboard/controller/member_api.go @@ -259,13 +259,14 @@ func (ma *memberAPI) addOrEditMonitor(c *gin.Context) { } type cronForm struct { - ID uint64 - Name string - Scheduler string - Command string - ServersRaw string - Cover uint8 - PushSuccessful string + ID uint64 + Name string + Scheduler string + Command string + ServersRaw string + Cover uint8 + PushSuccessful string + NotificationTag string } func (ma *memberAPI) addOrEditCron(c *gin.Context) { @@ -278,6 +279,7 @@ func (ma *memberAPI) addOrEditCron(c *gin.Context) { cr.Command = cf.Command cr.ServersRaw = cf.ServersRaw cr.PushSuccessful = cf.PushSuccessful == "on" + cr.NotificationTag = cf.NotificationTag cr.ID = cf.ID cr.Cover = cf.Cover err = utils.Json.Unmarshal([]byte(cf.ServersRaw), &cr.Servers) @@ -376,6 +378,7 @@ func (ma *memberAPI) forceUpdate(c *gin.Context) { type notificationForm struct { ID uint64 Name string + Tag string // 分组名 URL string RequestMethod int RequestType int @@ -390,6 +393,7 @@ func (ma *memberAPI) addOrEditNotification(c *gin.Context) { err := c.ShouldBindJSON(&nf) if err == nil { n.Name = nf.Name + n.Tag = nf.Tag n.RequestMethod = nf.RequestMethod n.RequestType = nf.RequestType n.RequestHeader = nf.RequestHeader @@ -401,6 +405,10 @@ func (ma *memberAPI) addOrEditNotification(c *gin.Context) { err = n.Send("这是测试消息") } if err == nil { + // 保证Tag不为空 + if n.Tag == "" { + n.Tag = "default" + } if n.ID == 0 { err = singleton.DB.Create(&n).Error } else { @@ -414,7 +422,7 @@ func (ma *memberAPI) addOrEditNotification(c *gin.Context) { }) return } - singleton.OnRefreshOrAddNotification(n) + singleton.OnRefreshOrAddNotification(&n) c.JSON(http.StatusOK, model.Response{ Code: http.StatusOK, }) diff --git a/model/config.go b/model/config.go index e7cf6b71c3..35cdd3d12a 100644 --- a/model/config.go +++ b/model/config.go @@ -72,6 +72,7 @@ type Config struct { TLS bool EnableIPChangeNotification bool + IPChangeNotificationTag string EnablePlainIPInNotification bool // IP变更提醒 @@ -102,6 +103,9 @@ func (c *Config) Read(path string) error { if c.GRPCPort == 0 { c.GRPCPort = 5555 } + if c.EnableIPChangeNotification && c.IPChangeNotificationTag == "" { + c.IPChangeNotificationTag = "default" + } c.updateIgnoredIPNotificationID() return nil diff --git a/model/cron.go b/model/cron.go index fbdf75a161..a8e756ccff 100644 --- a/model/cron.go +++ b/model/cron.go @@ -15,14 +15,15 @@ const ( type Cron struct { Common - Name string - Scheduler string //分钟 小时 天 月 星期 - Command string - Servers []uint64 `gorm:"-"` - PushSuccessful bool // 推送成功的通知 - LastExecutedAt time.Time // 最后一次执行时间 - LastResult bool // 最后一次执行结果 - Cover uint8 // 计划任务覆盖范围 (0:仅覆盖特定服务器 1:仅忽略特定服务器) + Name string + Scheduler string //分钟 小时 天 月 星期 + Command string + Servers []uint64 `gorm:"-"` + PushSuccessful bool // 推送成功的通知 + NotificationTag string // 指定通知方式的分组 + LastExecutedAt time.Time // 最后一次执行时间 + LastResult bool // 最后一次执行结果 + Cover uint8 // 计划任务覆盖范围 (0:仅覆盖特定服务器 1:仅忽略特定服务器) CronJobID cron.EntryID `gorm:"-"` ServersRaw string diff --git a/model/notification.go b/model/notification.go index 3ea2a9e0c7..fcbfb56e24 100644 --- a/model/notification.go +++ b/model/notification.go @@ -28,6 +28,7 @@ const ( type Notification struct { Common Name string + Tag string // 分组名 URL string RequestMethod int RequestType int diff --git a/resource/template/component/cron.html b/resource/template/component/cron.html index 3ee3da841f..2d3ba9de54 100644 --- a/resource/template/component/cron.html +++ b/resource/template/component/cron.html @@ -38,6 +38,10 @@ +
+ + +

diff --git a/resource/template/component/notification.html b/resource/template/component/notification.html index 9ba5a09cea..408fe785fc 100644 --- a/resource/template/component/notification.html +++ b/resource/template/component/notification.html @@ -8,6 +8,10 @@

+
+ + +
diff --git a/resource/template/dashboard/cron.html b/resource/template/dashboard/cron.html index 92b862de59..78ab201b3b 100644 --- a/resource/template/dashboard/cron.html +++ b/resource/template/dashboard/cron.html @@ -18,6 +18,7 @@ 计划 命令 成功推送 + 通知方式组 覆盖范围 特定服务器 最后执行 @@ -33,6 +34,7 @@ {{$cron.Scheduler}} {{$cron.Command}} {{$cron.PushSuccessful}} + {$cron.NotificationTag} {{if eq $cron.Cover 0}}忽略所有{{else}}覆盖所有{{end}} {{$cron.ServersRaw}} {{$cron.LastExecutedAt|tf}} diff --git a/resource/template/dashboard/notification.html b/resource/template/dashboard/notification.html index 8ebcc84cb9..c48f94d4bc 100644 --- a/resource/template/dashboard/notification.html +++ b/resource/template/dashboard/notification.html @@ -15,6 +15,7 @@ ID 名称 + 分组 URL 验证SSL 管理 @@ -25,6 +26,7 @@ {{$notification.ID}} {{$notification.Name}} + {{$notification.Tag}} {{$notification.URL}} {{$notification.VerifySSL}} diff --git a/service/rpc/nezha.go b/service/rpc/nezha.go index e48a854001..2bca2c5e7f 100644 --- a/service/rpc/nezha.go +++ b/service/rpc/nezha.go @@ -29,10 +29,10 @@ func (s *NezhaHandler) ReportTask(c context.Context, r *pb.TaskResult) (*pb.Rece singleton.ServerLock.RLock() defer singleton.ServerLock.RUnlock() if cr.PushSuccessful && r.GetSuccessful() { - singleton.SendNotification(fmt.Sprintf("[任务成功] %s ,服务器:%s,日志:\n%s", cr.Name, singleton.ServerList[clientID].Name, r.GetData()), false) + singleton.SendNotification(cr.NotificationTag, fmt.Sprintf("[任务成功] %s ,服务器:%s,日志:\n%s", cr.Name, singleton.ServerList[clientID].Name, r.GetData()), false) } if !r.GetSuccessful() { - singleton.SendNotification(fmt.Sprintf("[任务失败] %s ,服务器:%s,日志:\n%s", cr.Name, singleton.ServerList[clientID].Name, r.GetData()), false) + singleton.SendNotification(cr.NotificationTag, fmt.Sprintf("[任务失败] %s ,服务器:%s,日志:\n%s", cr.Name, singleton.ServerList[clientID].Name, r.GetData()), false) } singleton.DB.Model(cr).Updates(model.Cron{ LastExecutedAt: time.Now().Add(time.Second * -1 * time.Duration(r.GetDelay())), @@ -103,7 +103,7 @@ func (s *NezhaHandler) ReportSystemInfo(c context.Context, r *pb.Host) (*pb.Rece singleton.ServerList[clientID].Host.IP != "" && host.IP != "" && singleton.ServerList[clientID].Host.IP != host.IP { - singleton.SendNotification(fmt.Sprintf( + singleton.SendNotification(singleton.Conf.IPChangeNotificationTag, fmt.Sprintf( "[IP变更] %s ,旧IP:%s,新IP:%s。", singleton.ServerList[clientID].Name, singleton.IPDesensitize(singleton.ServerList[clientID].Host.IP), singleton.IPDesensitize(host.IP)), true) } diff --git a/service/singleton/crontask.go b/service/singleton/crontask.go index b4aafe1b34..eccc940960 100644 --- a/service/singleton/crontask.go +++ b/service/singleton/crontask.go @@ -11,7 +11,7 @@ import ( var ( Cron *cron.Cron - Crons map[uint64]*model.Cron + Crons map[uint64]*model.Cron // [CrondID] -> *model.Cron CronLock sync.RWMutex ) @@ -27,9 +27,12 @@ func LoadCronTasks() { DB.Find(&crons) var err error errMsg := new(bytes.Buffer) - for i := 0; i < len(crons); i++ { - cr := crons[i] - + var notificationTagList []string + for _, cr := range crons { + // 旧版本计划任务可能不存在通知组 为其添加默认通知组 + if cr.NotificationTag == "" { + AddDefaultCronNotificationTag(&cr) + } // 注册计划任务 cr.CronJobID, err = Cron.AddFunc(cr.Scheduler, CronTrigger(cr)) if err == nil { @@ -39,15 +42,30 @@ func LoadCronTasks() { errMsg.WriteString("调度失败的计划任务:[") } errMsg.WriteString(fmt.Sprintf("%d,", cr.ID)) + notificationTagList = append(notificationTagList, cr.NotificationTag) } } if errMsg.Len() > 0 { - msg := errMsg.String() - SendNotification(msg[:len(msg)-1]+"] 这些任务将无法正常执行,请进入后点重新修改保存。", false) + msg := errMsg.String() + "] 这些任务将无法正常执行,请进入后点重新修改保存。" + for _, tag := range notificationTagList { + // 向调度错误的计划任务所包含的所有通知组发送通知 + SendNotification(tag, msg, false) + } } Cron.Start() } +// AddDefaultCronNotificationTag 添加默认的计划任务通知组 +func AddDefaultCronNotificationTag(c *model.Cron) { + CronLock.Lock() + defer CronLock.Unlock() + + if c.NotificationTag == "" { + c.NotificationTag = "default" + } + DB.Save(c) +} + func ManualTrigger(c model.Cron) { CronTrigger(c)() } @@ -74,7 +92,7 @@ func CronTrigger(cr model.Cron) func() { Type: model.TaskTypeCommand, }) } else { - SendNotification(fmt.Sprintf("[任务失败] %s,服务器 %s 离线,无法执行。", cr.Name, s.Name), false) + SendNotification(cr.NotificationTag, fmt.Sprintf("[任务失败] %s,服务器 %s 离线,无法执行。", cr.Name, s.Name), false) } } } diff --git a/service/singleton/notification.go b/service/singleton/notification.go index 476403f417..caf3e6d33e 100644 --- a/service/singleton/notification.go +++ b/service/singleton/notification.go @@ -13,46 +13,95 @@ import ( const firstNotificationDelay = time.Minute * 15 // 通知方式 -var notifications []model.Notification -var notificationsLock sync.RWMutex +var ( + NotificationList map[string]map[uint64]*model.Notification // [NotificationMethodTag][NotificationID] -> model.Notification + NotificationIDToTag map[uint64]string // [NotificationID] -> NotificationTag + notificationsLock sync.RWMutex +) + +// InitNotification 初始化 Tag <-> ID <-> Notification 的映射 +func InitNotification() { + NotificationList = make(map[string]map[uint64]*model.Notification) + NotificationIDToTag = make(map[uint64]string) +} -// LoadNotifications 从 DB 加载通知方式到 singleton.notifications 变量 +// LoadNotifications 从 DB 初始化通知方式相关参数 func LoadNotifications() { + InitNotification() notificationsLock.Lock() + defer notificationsLock.Unlock() + + var notifications []model.Notification if err := DB.Find(¬ifications).Error; err != nil { panic(err) } - notificationsLock.Unlock() + for _, n := range notifications { + // 旧版本的Tag可能不存在 自动设置为默认值 + if n.Tag == "" { + SetDefaultNotificationTagInDB(&n) + } + AddNotificationToList(&n) + } } -func OnRefreshOrAddNotification(n model.Notification) { +// SetDefaultNotificationTagInDB 设置默认通知方式的 Tag +func SetDefaultNotificationTagInDB(n *model.Notification) { + n.Tag = "default" + if err := DB.Save(n).Error; err != nil { + log.Println("[ERROR]", err) + } +} + +// OnRefreshOrAddNotification 刷新通知方式相关参数 +func OnRefreshOrAddNotification(n *model.Notification) { notificationsLock.Lock() defer notificationsLock.Unlock() + var isEdit bool - for i := 0; i < len(notifications); i++ { - if notifications[i].ID == n.ID { - notifications[i] = n - isEdit = true - } + if _, ok := NotificationList[n.Tag][n.ID]; ok { + isEdit = true } if !isEdit { - notifications = append(notifications, n) + AddNotificationToList(n) + } else { + UpdateNotificationInList(n) } } -func OnDeleteNotification(id uint64) { +// AddNotificationToList 添加通知方式到map中 +func AddNotificationToList(n *model.Notification) { notificationsLock.Lock() defer notificationsLock.Unlock() - for i := 0; i < len(notifications); i++ { - if notifications[i].ID == id { - notifications = append(notifications[:i], notifications[i+1:]...) - i-- - } + + // 当前 Tag 不存在,创建对应该 Tag 的 子 map 后再添加 + if _, ok := NotificationList[n.Tag]; !ok { + NotificationList[n.Tag] = make(map[uint64]*model.Notification) } + NotificationList[n.Tag][n.ID] = n + NotificationIDToTag[n.ID] = n.Tag + +} + +// UpdateNotificationInList 在 map 中更新通知方式 +func UpdateNotificationInList(n *model.Notification) { + notificationsLock.Lock() + defer notificationsLock.Unlock() + + NotificationList[n.Tag][n.ID] = n } -func SendNotification(desc string, muteable bool) { - if muteable { +// OnDeleteNotification 在map中删除通知方式 +func OnDeleteNotification(id uint64) { + notificationsLock.Lock() + defer notificationsLock.Unlock() + + delete(NotificationList[NotificationIDToTag[id]], id) + delete(NotificationIDToTag, id) +} + +// SendNotification 向指定的通知方式组的所有通知方式发送通知 +func SendNotification(notificationTag string, desc string, mutable bool) { + if mutable { // 通知防骚扰策略 nID := hex.EncodeToString(md5.New().Sum([]byte(desc))) // #nosec var flag bool @@ -80,16 +129,17 @@ func SendNotification(desc string, muteable bool) { if !flag { if Conf.Debug { - log.Println("NEZHA>> 静音的重复通知:", desc, muteable) + log.Println("NEZHA>> 静音的重复通知:", desc, mutable) } return } } - // 发出通知 + // 向该通知方式组的所有通知方式发出通知 notificationsLock.RLock() defer notificationsLock.RUnlock() - for i := 0; i < len(notifications); i++ { - if err := notifications[i].Send(desc); err != nil { + + for _, n := range NotificationList[notificationTag] { + if err := n.Send(desc); err != nil { log.Println("NEZHA>> 发送通知失败:", err) } } From 322467673f4da7a1f5c0802287335fe7c8e54ddd Mon Sep 17 00:00:00 2001 From: Akkia Date: Fri, 15 Apr 2022 03:13:53 +0800 Subject: [PATCH 2/8] =?UTF-8?q?WIP:=20=E8=A1=A5=E5=85=A8=E5=90=84=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E7=9A=84=E9=80=9A=E7=9F=A5=E5=88=86=E7=BB=84=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/dashboard/controller/member_api.go | 50 +++++++++++-------- model/alertrule.go | 9 ++-- model/config.go | 7 ++- model/monitor.go | 15 +++--- resource/template/component/rule.html | 4 ++ resource/template/dashboard/notification.html | 2 + resource/template/dashboard/setting.html | 4 ++ service/singleton/alertsentinel.go | 29 +++++++---- service/singleton/notification.go | 23 ++++----- service/singleton/servicesentinel.go | 21 +++++--- service/singleton/singleton.go | 12 ++--- 11 files changed, 103 insertions(+), 73 deletions(-) diff --git a/cmd/dashboard/controller/member_api.go b/cmd/dashboard/controller/member_api.go index cf5a03f595..5c4e292c12 100644 --- a/cmd/dashboard/controller/member_api.go +++ b/cmd/dashboard/controller/member_api.go @@ -211,14 +211,15 @@ func (ma *memberAPI) addOrEditServer(c *gin.Context) { } type monitorForm struct { - ID uint64 - Name string - Target string - Type uint8 - Cover uint8 - Notify string - SkipServersRaw string - Duration uint64 + ID uint64 + Name string + Target string + Type uint8 + Cover uint8 + Notify string + NotificationTag string + SkipServersRaw string + Duration uint64 } func (ma *memberAPI) addOrEditMonitor(c *gin.Context) { @@ -233,10 +234,15 @@ func (ma *memberAPI) addOrEditMonitor(c *gin.Context) { m.SkipServersRaw = mf.SkipServersRaw m.Cover = mf.Cover m.Notify = mf.Notify == "on" + m.NotificationTag = mf.NotificationTag m.Duration = mf.Duration err = m.InitSkipServers() } if err == nil { + // 旧版本服务监控可能不存在通知组 为其添加默认的通知组 + if m.NotificationTag == "" { + m.NotificationTag = "default" + } if m.ID == 0 { err = singleton.DB.Create(&m).Error } else { @@ -429,10 +435,11 @@ func (ma *memberAPI) addOrEditNotification(c *gin.Context) { } type alertRuleForm struct { - ID uint64 - Name string - RulesRaw string - Enable string + ID uint64 + Name string + RulesRaw string + NotificationTag string + Enable string } func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) { @@ -472,6 +479,7 @@ func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) { if err == nil { r.Name = arf.Name r.RulesRaw = arf.RulesRaw + r.NotificationTag = arf.NotificationTag enable := arf.Enable == "on" r.Enable = &enable r.ID = arf.ID @@ -525,14 +533,15 @@ func (ma *memberAPI) logout(c *gin.Context) { } type settingForm struct { - Title string - Admin string - Theme string - CustomCode string - ViewPassword string - IgnoredIPNotification string - GRPCHost string - Cover uint8 + Title string + Admin string + Theme string + CustomCode string + ViewPassword string + IgnoredIPNotification string + IPChangeNotificationTag string // IP变更提醒的通知组 + GRPCHost string + Cover uint8 EnableIPChangeNotification string EnablePlainIPInNotification string @@ -552,6 +561,7 @@ func (ma *memberAPI) updateSetting(c *gin.Context) { singleton.Conf.Cover = sf.Cover singleton.Conf.GRPCHost = sf.GRPCHost singleton.Conf.IgnoredIPNotification = sf.IgnoredIPNotification + singleton.Conf.IPChangeNotificationTag = sf.IPChangeNotificationTag singleton.Conf.Site.Brand = sf.Title singleton.Conf.Site.Theme = sf.Theme singleton.Conf.Site.CustomCode = sf.CustomCode diff --git a/model/alertrule.go b/model/alertrule.go index 321480d1f4..032e6163b3 100644 --- a/model/alertrule.go +++ b/model/alertrule.go @@ -20,10 +20,11 @@ type CycleTransferStats struct { type AlertRule struct { Common - Name string - RulesRaw string - Enable *bool - Rules []Rule `gorm:"-" json:"-"` + Name string + RulesRaw string + Enable *bool + NotificationTag string // 该报警规则所在的通知组 + Rules []Rule `gorm:"-" json:"-"` } func (r *AlertRule) BeforeSave(tx *gorm.DB) error { diff --git a/model/config.go b/model/config.go index 35cdd3d12a..be32ef0631 100644 --- a/model/config.go +++ b/model/config.go @@ -71,13 +71,12 @@ type Config struct { ProxyGRPCPort uint TLS bool + // IP变更提醒 EnableIPChangeNotification bool IPChangeNotificationTag string EnablePlainIPInNotification bool - - // IP变更提醒 - Cover uint8 // 覆盖范围(0:提醒未被 IgnoredIPNotification 包含的所有服务器; 1:仅提醒被 IgnoredIPNotification 包含的服务器;) - IgnoredIPNotification string // 特定服务器IP(多个服务器用逗号分隔) + Cover uint8 // 覆盖范围(0:提醒未被 IgnoredIPNotification 包含的所有服务器; 1:仅提醒被 IgnoredIPNotification 包含的服务器;) + IgnoredIPNotification string // 特定服务器IP(多个服务器用逗号分隔) v *viper.Viper IgnoredIPNotificationServerIDs map[uint64]bool // [ServerID] -> bool(值为true代表当前ServerID在特定服务器列表内) diff --git a/model/monitor.go b/model/monitor.go index 309de376f9..0230eeb4f1 100644 --- a/model/monitor.go +++ b/model/monitor.go @@ -38,13 +38,14 @@ const ( type Monitor struct { Common - Name string - Type uint8 - Target string - SkipServersRaw string - Duration uint64 - Notify bool - Cover uint8 + Name string + Type uint8 + Target string + SkipServersRaw string + Duration uint64 + Notify bool + NotificationTag string // 当前服务监控所属的通知组 + Cover uint8 SkipServers map[uint64]bool `gorm:"-" json:"-"` CronJobID cron.EntryID `gorm:"-" json:"-"` diff --git a/resource/template/component/rule.html b/resource/template/component/rule.html index a9dd8ea774..02b96375e0 100644 --- a/resource/template/component/rule.html +++ b/resource/template/component/rule.html @@ -12,6 +12,10 @@
+
+ + +
diff --git a/resource/template/dashboard/notification.html b/resource/template/dashboard/notification.html index c48f94d4bc..d012b8c148 100644 --- a/resource/template/dashboard/notification.html +++ b/resource/template/dashboard/notification.html @@ -57,6 +57,7 @@ ID 名称 + 通知方式组 规则 启用 管理 @@ -67,6 +68,7 @@ {{$rule.ID}} {{$rule.Name}} + {{$rule.NotificationTag}} {{$rule.RulesRaw}} {{$rule.Enable}} diff --git a/resource/template/dashboard/setting.html b/resource/template/dashboard/setting.html index 601921b226..d499070b58 100644 --- a/resource/template/dashboard/setting.html +++ b/resource/template/dashboard/setting.html @@ -52,6 +52,10 @@
+
+ + +
diff --git a/service/singleton/alertsentinel.go b/service/singleton/alertsentinel.go index 8902700eba..a97397a032 100644 --- a/service/singleton/alertsentinel.go +++ b/service/singleton/alertsentinel.go @@ -21,11 +21,13 @@ type NotificationHistory struct { } // 报警规则 -var AlertsLock sync.RWMutex -var Alerts []*model.AlertRule -var alertsStore map[uint64]map[uint64][][]interface{} // [alert_id][server_id] -> 对应报警规则的检查结果 -var alertsPrevState map[uint64]map[uint64]uint // [alert_id][server_id] -> 对应报警规则的上一次报警状态 -var AlertsCycleTransferStatsStore map[uint64]*model.CycleTransferStats // [alert_id] -> 对应报警规则的周期流量统计 +var ( + AlertsLock sync.RWMutex + Alerts []*model.AlertRule + alertsStore map[uint64]map[uint64][][]interface{} // [alert_id][server_id] -> 对应报警规则的检查结果 + alertsPrevState map[uint64]map[uint64]uint // [alert_id][server_id] -> 对应报警规则的上一次报警状态 + AlertsCycleTransferStatsStore map[uint64]*model.CycleTransferStats // [alert_id] -> 对应报警规则的周期流量统计 +) // addCycleTransferStatsInfo 向AlertsCycleTransferStatsStore中添加周期流量报警统计信息 func addCycleTransferStatsInfo(alert *model.AlertRule) { @@ -62,10 +64,15 @@ func AlertSentinelStart() { if err := DB.Find(&Alerts).Error; err != nil { panic(err) } - for i := 0; i < len(Alerts); i++ { - alertsStore[Alerts[i].ID] = make(map[uint64][][]interface{}) - alertsPrevState[Alerts[i].ID] = make(map[uint64]uint) - addCycleTransferStatsInfo(Alerts[i]) + for _, alert := range Alerts { + // 旧版本可能不存在通知组 为其添加默认值 + if alert.NotificationTag == "" { + alert.NotificationTag = "default" + DB.Save(alert) + } + alertsStore[alert.ID] = make(map[uint64][][]interface{}) + alertsPrevState[alert.ID] = make(map[uint64]uint) + addCycleTransferStatsInfo(alert) } AlertsLock.Unlock() @@ -143,11 +150,11 @@ func checkStatus() { if !passed { alertsPrevState[alert.ID][server.ID] = _RuleCheckFail message := fmt.Sprintf("[主机故障] %s(%s) 规则:%s", server.Name, IPDesensitize(server.Host.IP), alert.Name) - go SendNotification(message, true) + go SendNotification(alert.NotificationTag, message, true) } else { if alertsPrevState[alert.ID][server.ID] == _RuleCheckFail { message := fmt.Sprintf("[主机恢复] %s(%s) 规则:%s", server.Name, IPDesensitize(server.Host.IP), alert.Name) - go SendNotification(message, true) + go SendNotification(alert.NotificationTag, message, true) } alertsPrevState[alert.ID][server.ID] = _RuleCheckPass } diff --git a/service/singleton/notification.go b/service/singleton/notification.go index caf3e6d33e..73efde35c7 100644 --- a/service/singleton/notification.go +++ b/service/singleton/notification.go @@ -35,12 +35,12 @@ func LoadNotifications() { if err := DB.Find(¬ifications).Error; err != nil { panic(err) } - for _, n := range notifications { + for i := range notifications { // 旧版本的Tag可能不存在 自动设置为默认值 - if n.Tag == "" { - SetDefaultNotificationTagInDB(&n) + if notifications[i].Tag == "" { + SetDefaultNotificationTagInDB(¬ifications[i]) } - AddNotificationToList(&n) + AddNotificationToList(¬ifications[i]) } } @@ -70,23 +70,16 @@ func OnRefreshOrAddNotification(n *model.Notification) { // AddNotificationToList 添加通知方式到map中 func AddNotificationToList(n *model.Notification) { - notificationsLock.Lock() - defer notificationsLock.Unlock() - // 当前 Tag 不存在,创建对应该 Tag 的 子 map 后再添加 if _, ok := NotificationList[n.Tag]; !ok { NotificationList[n.Tag] = make(map[uint64]*model.Notification) } NotificationList[n.Tag][n.ID] = n NotificationIDToTag[n.ID] = n.Tag - } // UpdateNotificationInList 在 map 中更新通知方式 func UpdateNotificationInList(n *model.Notification) { - notificationsLock.Lock() - defer notificationsLock.Unlock() - NotificationList[n.Tag][n.ID] = n } @@ -137,10 +130,14 @@ func SendNotification(notificationTag string, desc string, mutable bool) { // 向该通知方式组的所有通知方式发出通知 notificationsLock.RLock() defer notificationsLock.RUnlock() - + for _, n := range NotificationList[notificationTag] { + log.Println("尝试通知", n.Name) + } for _, n := range NotificationList[notificationTag] { if err := n.Send(desc); err != nil { - log.Println("NEZHA>> 发送通知失败:", err) + log.Println("NEZHA>> 向 ", n.Name, " 发送通知失败:", err) + } else { + log.Println("NEZHA>> 向 ", n.Name, " 发送通知成功:") } } } diff --git a/service/singleton/servicesentinel.go b/service/singleton/servicesentinel.go index cb897d5d07..23ccd76a61 100644 --- a/service/singleton/servicesentinel.go +++ b/service/singleton/servicesentinel.go @@ -149,18 +149,23 @@ func (ss *ServiceSentinel) loadMonitorHistory() { var err error ss.monitorsLock.Lock() defer ss.monitorsLock.Unlock() - for i := 0; i < len(monitors); i++ { - task := *monitors[i] + for _, monitor := range monitors { + // 旧版本可能不存在通知组 为其设置默认组 + if monitor.NotificationTag == "" { + monitor.NotificationTag = "default" + DB.Save(monitor) + } + task := *monitor // 通过cron定时将服务监控任务传递给任务调度管道 - monitors[i].CronJobID, err = Cron.AddFunc(task.CronSpec(), func() { + monitor.CronJobID, err = Cron.AddFunc(task.CronSpec(), func() { ss.dispatchBus <- task }) if err != nil { panic(err) } - ss.monitors[monitors[i].ID] = monitors[i] - ss.serviceCurrentStatusData[monitors[i].ID] = make([]model.MonitorHistory, _CurrentStatusSize) - ss.serviceStatusToday[monitors[i].ID] = &_TodayStatsOfMonitor{} + ss.monitors[monitor.ID] = monitor + ss.serviceCurrentStatusData[monitor.ID] = make([]model.MonitorHistory, _CurrentStatusSize) + ss.serviceStatusToday[monitor.ID] = &_TodayStatsOfMonitor{} } year, month, day := time.Now().Date() @@ -356,7 +361,7 @@ func (ss *ServiceSentinel) worker() { isNeedSendNotification := (ss.lastStatus[mh.MonitorID] != "" || stateStr == "故障") && ss.monitors[mh.MonitorID].Notify ss.lastStatus[mh.MonitorID] = stateStr if isNeedSendNotification { - go SendNotification(fmt.Sprintf("[服务%s] %s", stateStr, ss.monitors[mh.MonitorID].Name), true) + go SendNotification(ss.monitors[mh.MonitorID].NotificationTag, fmt.Sprintf("[服务%s] %s", stateStr, ss.monitors[mh.MonitorID].Name), true) } ss.monitorsLock.RUnlock() } @@ -400,7 +405,7 @@ func (ss *ServiceSentinel) worker() { if errMsg != "" { ss.monitorsLock.RLock() if ss.monitors[mh.MonitorID].Notify { - go SendNotification(fmt.Sprintf("[SSL] %s %s", ss.monitors[mh.MonitorID].Name, errMsg), true) + go SendNotification(ss.monitors[mh.MonitorID].NotificationTag, fmt.Sprintf("[SSL] %s %s", ss.monitors[mh.MonitorID].Name, errMsg), true) } ss.monitorsLock.RUnlock() } diff --git a/service/singleton/singleton.go b/service/singleton/singleton.go index 341bd09bb2..5e5fc8ce10 100644 --- a/service/singleton/singleton.go +++ b/service/singleton/singleton.go @@ -107,22 +107,22 @@ func CleanMonitorHistory() { var specialServerIDs []uint64 var alerts []model.AlertRule DB.Find(&alerts) - for i := 0; i < len(alerts); i++ { - for j := 0; j < len(alerts[i].Rules); j++ { + for _, alert := range alerts { + for _, rule := range alert.Rules { // 是不是流量记录规则 - if !alerts[i].Rules[j].IsTransferDurationRule() { + if !rule.IsTransferDurationRule() { continue } - dataCouldRemoveBefore := alerts[i].Rules[j].GetTransferDurationStart() + dataCouldRemoveBefore := rule.GetTransferDurationStart() // 判断规则影响的机器范围 - if alerts[i].Rules[j].Cover == model.RuleCoverAll { + if rule.Cover == model.RuleCoverAll { // 更新全局可以清理的数据点 if allServerKeep.IsZero() || allServerKeep.After(dataCouldRemoveBefore) { allServerKeep = dataCouldRemoveBefore } } else { // 更新特定机器可以清理数据点 - for id := range alerts[i].Rules[j].Ignore { + for id := range rule.Ignore { if specialServerKeep[id].IsZero() || specialServerKeep[id].After(dataCouldRemoveBefore) { specialServerKeep[id] = dataCouldRemoveBefore specialServerIDs = append(specialServerIDs, id) From 615e337b42169269a97fd9513562ad6032f559cd Mon Sep 17 00:00:00 2001 From: Akkia Date: Fri, 15 Apr 2022 03:20:42 +0800 Subject: [PATCH 3/8] fix "for range" pointer issue --- service/singleton/crontask.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/service/singleton/crontask.go b/service/singleton/crontask.go index 24e6c00521..aef120321c 100644 --- a/service/singleton/crontask.go +++ b/service/singleton/crontask.go @@ -30,21 +30,21 @@ func LoadCronTasks() { var err error errMsg := new(bytes.Buffer) var notificationTagList []string - for _, cr := range crons { + for i := range crons { // 旧版本计划任务可能不存在通知组 为其添加默认通知组 - if cr.NotificationTag == "" { - AddDefaultCronNotificationTag(&cr) + if crons[i].NotificationTag == "" { + AddDefaultCronNotificationTag(&crons[i]) } // 注册计划任务 - cr.CronJobID, err = Cron.AddFunc(cr.Scheduler, CronTrigger(cr)) + crons[i].CronJobID, err = Cron.AddFunc(crons[i].Scheduler, CronTrigger(crons[i])) if err == nil { - Crons[cr.ID] = &cr + Crons[crons[i].ID] = &crons[i] } else { if errMsg.Len() == 0 { errMsg.WriteString("调度失败的计划任务:[") } - errMsg.WriteString(fmt.Sprintf("%d,", cr.ID)) - notificationTagList = append(notificationTagList, cr.NotificationTag) + errMsg.WriteString(fmt.Sprintf("%d,", crons[i].ID)) + notificationTagList = append(notificationTagList, crons[i].NotificationTag) } } if errMsg.Len() > 0 { From ab033f3b2e4ae515e0fe1e972d649e7c221e568b Mon Sep 17 00:00:00 2001 From: Akkia Date: Fri, 15 Apr 2022 10:55:21 +0800 Subject: [PATCH 4/8] =?UTF-8?q?update:=20=E8=B0=83=E5=BA=A6=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E7=9A=84=E8=AE=A1=E5=88=92=E4=BB=BB=E5=8A=A1=E4=BB=85?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E5=85=B6=E6=89=80=E5=B1=9E=E7=9A=84=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service/singleton/crontask.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/service/singleton/crontask.go b/service/singleton/crontask.go index aef120321c..956456b7a1 100644 --- a/service/singleton/crontask.go +++ b/service/singleton/crontask.go @@ -28,8 +28,8 @@ func LoadCronTasks() { var crons []model.Cron DB.Find(&crons) var err error - errMsg := new(bytes.Buffer) var notificationTagList []string + notificationMsgMap := make(map[string]*bytes.Buffer) for i := range crons { // 旧版本计划任务可能不存在通知组 为其添加默认通知组 if crons[i].NotificationTag == "" { @@ -40,19 +40,19 @@ func LoadCronTasks() { if err == nil { Crons[crons[i].ID] = &crons[i] } else { - if errMsg.Len() == 0 { - errMsg.WriteString("调度失败的计划任务:[") + // 当前通知组首次出现 将其加入通知组列表并初始化通知组消息缓存 + if _, ok := notificationMsgMap[crons[i].NotificationTag]; !ok { + notificationTagList = append(notificationTagList, crons[i].NotificationTag) + notificationMsgMap[crons[i].NotificationTag] = bytes.NewBufferString("") + notificationMsgMap[crons[i].NotificationTag].WriteString("调度失败的计划任务:[") } - errMsg.WriteString(fmt.Sprintf("%d,", crons[i].ID)) - notificationTagList = append(notificationTagList, crons[i].NotificationTag) + notificationMsgMap[crons[i].NotificationTag].WriteString(fmt.Sprintf("%d,", crons[i].ID)) } } - if errMsg.Len() > 0 { - msg := errMsg.String() + "] 这些任务将无法正常执行,请进入后点重新修改保存。" - for _, tag := range notificationTagList { - // 向调度错误的计划任务所包含的所有通知组发送通知 - SendNotification(tag, msg, false) - } + // 向注册错误的计划任务所在通知组发送通知 + for _, tag := range notificationTagList { + notificationMsgMap[tag].WriteString("] 这些任务将无法正常执行,请进入后点重新修改保存。") + SendNotification(tag, notificationMsgMap[tag].String(), false) } Cron.Start() } From 548d25c9a61ed8cf00fc68a91e4d795591dca246 Mon Sep 17 00:00:00 2001 From: Akkia Date: Fri, 15 Apr 2022 10:56:04 +0800 Subject: [PATCH 5/8] =?UTF-8?q?update:=20=E5=89=8D=E7=AB=AF=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=80=9A=E7=9F=A5=E6=96=B9=E5=BC=8F=E7=BB=84=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resource/static/main.js | 4 ++++ resource/template/component/cron.html | 8 ++++---- resource/template/component/monitor.html | 4 ++++ resource/template/component/notification.html | 2 +- resource/template/component/rule.html | 2 +- resource/template/dashboard/cron.html | 4 ++-- resource/template/dashboard/monitor.html | 2 ++ 7 files changed, 18 insertions(+), 8 deletions(-) diff --git a/resource/static/main.js b/resource/static/main.js index c185373a14..55be2a3f24 100644 --- a/resource/static/main.js +++ b/resource/static/main.js @@ -114,6 +114,7 @@ function addOrEditAlertRule(rule) { modal.find("input[name=ID]").val(rule ? rule.ID : null); modal.find("input[name=Name]").val(rule ? rule.Name : null); modal.find("textarea[name=RulesRaw]").val(rule ? rule.RulesRaw : null); + modal.find("input[name=NotificationTag]").val(rule ? rule.NotificationTag : null); if (rule && rule.Enable) { modal.find(".ui.rule-enable.checkbox").checkbox("set checked"); } else { @@ -134,6 +135,7 @@ function addOrEditNotification(notification) { ); modal.find("input[name=ID]").val(notification ? notification.ID : null); modal.find("input[name=Name]").val(notification ? notification.Name : null); + modal.find("input[name=Tag]").val(notification ? notification.Tag : null); modal.find("input[name=URL]").val(notification ? notification.URL : null); modal .find("textarea[name=RequestHeader]") @@ -225,6 +227,7 @@ function addOrEditMonitor(monitor) { modal.find("input[name=Duration]").val(monitor && monitor.Duration ? monitor.Duration : 30); modal.find("select[name=Type]").val(monitor ? monitor.Type : 1); modal.find("select[name=Cover]").val(monitor ? monitor.Cover : 0); + modal.find("input[name=NotificationTag]").val(monitor ? monitor.NotificationTag : null); if (monitor && monitor.Notify) { modal.find(".ui.nb-notify.checkbox").checkbox("set checked"); } else { @@ -261,6 +264,7 @@ function addOrEditCron(cron) { ); modal.find("input[name=ID]").val(cron ? cron.ID : null); modal.find("input[name=Name]").val(cron ? cron.Name : null); + modal.find("input[name=NotificationTag]").val(cron ? cron.NotificationTag : null); modal.find("input[name=Scheduler]").val(cron ? cron.Scheduler : null); modal.find("a.ui.label.visible").each((i, el) => { el.remove(); diff --git a/resource/template/component/cron.html b/resource/template/component/cron.html index 2d3ba9de54..0b71952064 100644 --- a/resource/template/component/cron.html +++ b/resource/template/component/cron.html @@ -32,16 +32,16 @@
+
+ + +
-
- - -

diff --git a/resource/template/component/monitor.html b/resource/template/component/monitor.html index 332cf69a7c..98fba8a28d 100644 --- a/resource/template/component/monitor.html +++ b/resource/template/component/monitor.html @@ -44,6 +44,10 @@

+
+ + +
diff --git a/resource/template/component/notification.html b/resource/template/component/notification.html index 408fe785fc..b37d910a10 100644 --- a/resource/template/component/notification.html +++ b/resource/template/component/notification.html @@ -10,7 +10,7 @@
- +
diff --git a/resource/template/component/rule.html b/resource/template/component/rule.html index 02b96375e0..8448244c5e 100644 --- a/resource/template/component/rule.html +++ b/resource/template/component/rule.html @@ -14,7 +14,7 @@
- +
diff --git a/resource/template/dashboard/cron.html b/resource/template/dashboard/cron.html index 78ab201b3b..842d9146f0 100644 --- a/resource/template/dashboard/cron.html +++ b/resource/template/dashboard/cron.html @@ -17,8 +17,8 @@ 名称 计划 命令 - 成功推送 通知方式组 + 成功推送 覆盖范围 特定服务器 最后执行 @@ -33,8 +33,8 @@ {{$cron.Name}} {{$cron.Scheduler}} {{$cron.Command}} + {{$cron.NotificationTag}} {{$cron.PushSuccessful}} - {$cron.NotificationTag} {{if eq $cron.Cover 0}}忽略所有{{else}}覆盖所有{{end}} {{$cron.ServersRaw}} {{$cron.LastExecutedAt|tf}} diff --git a/resource/template/dashboard/monitor.html b/resource/template/dashboard/monitor.html index bc69aaa84c..2feff3aafd 100644 --- a/resource/template/dashboard/monitor.html +++ b/resource/template/dashboard/monitor.html @@ -19,6 +19,7 @@ 特定服务器 类型 请求间隔 + 通知方式组 通知 管理 @@ -36,6 +37,7 @@ 2}} ICMP Ping {{else}} TCP 端口 {{end}} {{$monitor.Duration}}秒 + {{$monitor.NotificationTag}} {{$monitor.Notify}}
From 2ccb8f34770affade0e58bd0d0c5c4d091c7557b Mon Sep 17 00:00:00 2001 From: Akkia Date: Fri, 15 Apr 2022 20:34:25 +0800 Subject: [PATCH 6/8] =?UTF-8?q?fix:=20=E5=89=8D=E5=90=91=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E6=80=A7=20=EF=BD=9C=20for=20range=20pointer=20issue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/dashboard/controller/member_api.go | 14 +++++++++++++- resource/template/dashboard/setting.html | 2 +- service/singleton/servicesentinel.go | 18 +++++++++--------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/cmd/dashboard/controller/member_api.go b/cmd/dashboard/controller/member_api.go index 5c4e292c12..88b54e4cf0 100644 --- a/cmd/dashboard/controller/member_api.go +++ b/cmd/dashboard/controller/member_api.go @@ -239,7 +239,7 @@ func (ma *memberAPI) addOrEditMonitor(c *gin.Context) { err = m.InitSkipServers() } if err == nil { - // 旧版本服务监控可能不存在通知组 为其添加默认的通知组 + // 保证NotificationTag不为空 if m.NotificationTag == "" { m.NotificationTag = "default" } @@ -292,6 +292,10 @@ func (ma *memberAPI) addOrEditCron(c *gin.Context) { } tx := singleton.DB.Begin() if err == nil { + // 保证NotificationTag不为空 + if cr.NotificationTag == "" { + cr.NotificationTag = "default" + } if cf.ID == 0 { err = tx.Create(&cr).Error } else { @@ -483,6 +487,10 @@ func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) { enable := arf.Enable == "on" r.Enable = &enable r.ID = arf.ID + //保证NotificationTag不为空 + if r.NotificationTag == "" { + r.NotificationTag = "default" + } if r.ID == 0 { err = singleton.DB.Create(&r).Error } else { @@ -567,6 +575,10 @@ func (ma *memberAPI) updateSetting(c *gin.Context) { singleton.Conf.Site.CustomCode = sf.CustomCode singleton.Conf.Site.ViewPassword = sf.ViewPassword singleton.Conf.Oauth2.Admin = sf.Admin + // 保证NotificationTag不为空 + if singleton.Conf.IPChangeNotificationTag == "" { + singleton.Conf.IPChangeNotificationTag = "default" + } if err := singleton.Conf.Save(); err != nil { c.JSON(http.StatusOK, model.Response{ Code: http.StatusBadRequest, diff --git a/resource/template/dashboard/setting.html b/resource/template/dashboard/setting.html index d499070b58..eeb25b1366 100644 --- a/resource/template/dashboard/setting.html +++ b/resource/template/dashboard/setting.html @@ -53,7 +53,7 @@ value="{{.Conf.IgnoredIPNotification}}">
- +
diff --git a/service/singleton/servicesentinel.go b/service/singleton/servicesentinel.go index 23ccd76a61..714091ae2c 100644 --- a/service/singleton/servicesentinel.go +++ b/service/singleton/servicesentinel.go @@ -149,23 +149,23 @@ func (ss *ServiceSentinel) loadMonitorHistory() { var err error ss.monitorsLock.Lock() defer ss.monitorsLock.Unlock() - for _, monitor := range monitors { + for i := range monitors { // 旧版本可能不存在通知组 为其设置默认组 - if monitor.NotificationTag == "" { - monitor.NotificationTag = "default" - DB.Save(monitor) + if monitors[i].NotificationTag == "" { + monitors[i].NotificationTag = "default" + DB.Save(monitors[i]) } - task := *monitor + task := *monitors[i] // 通过cron定时将服务监控任务传递给任务调度管道 - monitor.CronJobID, err = Cron.AddFunc(task.CronSpec(), func() { + monitors[i].CronJobID, err = Cron.AddFunc(task.CronSpec(), func() { ss.dispatchBus <- task }) if err != nil { panic(err) } - ss.monitors[monitor.ID] = monitor - ss.serviceCurrentStatusData[monitor.ID] = make([]model.MonitorHistory, _CurrentStatusSize) - ss.serviceStatusToday[monitor.ID] = &_TodayStatsOfMonitor{} + ss.monitors[monitors[i].ID] = monitors[i] + ss.serviceCurrentStatusData[monitors[i].ID] = make([]model.MonitorHistory, _CurrentStatusSize) + ss.serviceStatusToday[monitors[i].ID] = &_TodayStatsOfMonitor{} } year, month, day := time.Now().Date() From 26646bff1ad40d9f219214736da30f78d1b68641 Mon Sep 17 00:00:00 2001 From: Akkia Date: Fri, 15 Apr 2022 23:23:51 +0800 Subject: [PATCH 7/8] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E6=96=B9=E5=BC=8F=E6=89=80=E5=9C=A8=E7=BB=84?= =?UTF-8?q?=E5=90=8E=20=E4=B8=8D=E4=BC=9A=E7=A7=BB=E9=99=A4=E5=85=B6?= =?UTF-8?q?=E5=8E=9F=E6=9C=89map=E6=98=A0=E5=B0=84=E5=85=B3=E7=B3=BB?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- model/config.go | 11 ++++++----- service/singleton/crontask.go | 16 +++------------- service/singleton/notification.go | 15 ++++++++++++--- service/singleton/servicesentinel.go | 2 +- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/model/config.go b/model/config.go index be32ef0631..e509104830 100644 --- a/model/config.go +++ b/model/config.go @@ -71,12 +71,13 @@ type Config struct { ProxyGRPCPort uint TLS bool + EnablePlainIPInNotification bool // 通知信息IP不打码 + // IP变更提醒 - EnableIPChangeNotification bool - IPChangeNotificationTag string - EnablePlainIPInNotification bool - Cover uint8 // 覆盖范围(0:提醒未被 IgnoredIPNotification 包含的所有服务器; 1:仅提醒被 IgnoredIPNotification 包含的服务器;) - IgnoredIPNotification string // 特定服务器IP(多个服务器用逗号分隔) + EnableIPChangeNotification bool + IPChangeNotificationTag string + Cover uint8 // 覆盖范围(0:提醒未被 IgnoredIPNotification 包含的所有服务器; 1:仅提醒被 IgnoredIPNotification 包含的服务器;) + IgnoredIPNotification string // 特定服务器IP(多个服务器用逗号分隔) v *viper.Viper IgnoredIPNotificationServerIDs map[uint64]bool // [ServerID] -> bool(值为true代表当前ServerID在特定服务器列表内) diff --git a/service/singleton/crontask.go b/service/singleton/crontask.go index 956456b7a1..54aa65e0ba 100644 --- a/service/singleton/crontask.go +++ b/service/singleton/crontask.go @@ -30,10 +30,11 @@ func LoadCronTasks() { var err error var notificationTagList []string notificationMsgMap := make(map[string]*bytes.Buffer) - for i := range crons { + for i := 0; i < len(crons); i++ { // 旧版本计划任务可能不存在通知组 为其添加默认通知组 if crons[i].NotificationTag == "" { - AddDefaultCronNotificationTag(&crons[i]) + crons[i].NotificationTag = "default" + DB.Save(crons[i]) } // 注册计划任务 crons[i].CronJobID, err = Cron.AddFunc(crons[i].Scheduler, CronTrigger(crons[i])) @@ -57,17 +58,6 @@ func LoadCronTasks() { Cron.Start() } -// AddDefaultCronNotificationTag 添加默认的计划任务通知组 -func AddDefaultCronNotificationTag(c *model.Cron) { - CronLock.Lock() - defer CronLock.Unlock() - - if c.NotificationTag == "" { - c.NotificationTag = "default" - } - DB.Save(c) -} - func ManualTrigger(c model.Cron) { CronTrigger(c)() } diff --git a/service/singleton/notification.go b/service/singleton/notification.go index 73efde35c7..48c0099a08 100644 --- a/service/singleton/notification.go +++ b/service/singleton/notification.go @@ -35,7 +35,7 @@ func LoadNotifications() { if err := DB.Find(¬ifications).Error; err != nil { panic(err) } - for i := range notifications { + for i := 0; i < len(notifications); i++ { // 旧版本的Tag可能不存在 自动设置为默认值 if notifications[i].Tag == "" { SetDefaultNotificationTagInDB(¬ifications[i]) @@ -58,7 +58,7 @@ func OnRefreshOrAddNotification(n *model.Notification) { defer notificationsLock.Unlock() var isEdit bool - if _, ok := NotificationList[n.Tag][n.ID]; ok { + if _, ok := NotificationIDToTag[n.ID]; ok { isEdit = true } if !isEdit { @@ -80,7 +80,16 @@ func AddNotificationToList(n *model.Notification) { // UpdateNotificationInList 在 map 中更新通知方式 func UpdateNotificationInList(n *model.Notification) { - NotificationList[n.Tag][n.ID] = n + if n.Tag != NotificationIDToTag[n.ID] { + // 如果 Tag 不一致,则需要先移除原有的映射关系 + delete(NotificationList[NotificationIDToTag[n.ID]], n.ID) + delete(NotificationIDToTag, n.ID) + // 将新的 Tag 中的通知方式添加到 map 中 + AddNotificationToList(n) + } else { + // 如果 Tag 一致,则直接更新 + NotificationList[n.Tag][n.ID] = n + } } // OnDeleteNotification 在map中删除通知方式 diff --git a/service/singleton/servicesentinel.go b/service/singleton/servicesentinel.go index 714091ae2c..5049924ae0 100644 --- a/service/singleton/servicesentinel.go +++ b/service/singleton/servicesentinel.go @@ -149,7 +149,7 @@ func (ss *ServiceSentinel) loadMonitorHistory() { var err error ss.monitorsLock.Lock() defer ss.monitorsLock.Unlock() - for i := range monitors { + for i := 0; i < len(monitors); i++ { // 旧版本可能不存在通知组 为其设置默认组 if monitors[i].NotificationTag == "" { monitors[i].NotificationTag = "default" From 5e400807e08ccfae00e4e19cb88140fed73a01ee Mon Sep 17 00:00:00 2001 From: naiba Date: Sat, 16 Apr 2022 09:32:34 +0800 Subject: [PATCH 8/8] dashboard v0.12.20 Co-authored-by: AkkiaS7 <68485070+AkkiaS7@users.noreply.github.com> --- README.md | 2 +- service/singleton/singleton.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c2defc1a09..7281768579 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@
LOGO designed by 熊大 .

-    +   

:trollface: 哪吒监控 一站式轻监控轻运维系统。支持系统状态、HTTP(SSL 证书变更、即将到期、到期)、TCP、Ping 监控报警,计划任务和在线终端。

diff --git a/service/singleton/singleton.go b/service/singleton/singleton.go index 5e5fc8ce10..acd54d88bb 100644 --- a/service/singleton/singleton.go +++ b/service/singleton/singleton.go @@ -12,7 +12,7 @@ import ( "github.com/naiba/nezha/pkg/utils" ) -var Version = "v0.12.19" // !!记得修改 README 中的 badge 版本!! +var Version = "v0.12.20" // !!记得修改 README 中的 badge 版本!! var ( Conf *model.Config