mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-02-06 05:30:05 +00:00
add cron, nat api & refactor alert rule (#459)
* add cron api & refactor alert rule * add nat api * fix swagger * remove unnecessary steps
This commit is contained in:
@@ -26,9 +26,9 @@ type NotificationHistory struct {
|
||||
var (
|
||||
AlertsLock sync.RWMutex
|
||||
Alerts []*model.AlertRule
|
||||
alertsStore map[uint64]map[uint64][][]interface{} // [alert_id][server_id] -> 对应报警规则的检查结果
|
||||
alertsPrevState map[uint64]map[uint64]uint8 // [alert_id][server_id] -> 对应报警规则的上一次报警状态
|
||||
AlertsCycleTransferStatsStore map[uint64]*model.CycleTransferStats // [alert_id] -> 对应报警规则的周期流量统计
|
||||
alertsStore map[uint64]map[uint64][][]bool // [alert_id][server_id] -> 对应报警规则的检查结果
|
||||
alertsPrevState map[uint64]map[uint64]uint8 // [alert_id][server_id] -> 对应报警规则的上一次报警状态
|
||||
AlertsCycleTransferStatsStore map[uint64]*model.CycleTransferStats // [alert_id] -> 对应报警规则的周期流量统计
|
||||
)
|
||||
|
||||
// addCycleTransferStatsInfo 向AlertsCycleTransferStatsStore中添加周期流量报警统计信息
|
||||
@@ -59,7 +59,7 @@ func addCycleTransferStatsInfo(alert *model.AlertRule) {
|
||||
|
||||
// AlertSentinelStart 报警器启动
|
||||
func AlertSentinelStart() {
|
||||
alertsStore = make(map[uint64]map[uint64][][]interface{})
|
||||
alertsStore = make(map[uint64]map[uint64][][]bool)
|
||||
alertsPrevState = make(map[uint64]map[uint64]uint8)
|
||||
AlertsCycleTransferStatsStore = make(map[uint64]*model.CycleTransferStats)
|
||||
AlertsLock.Lock()
|
||||
@@ -67,7 +67,7 @@ func AlertSentinelStart() {
|
||||
panic(err)
|
||||
}
|
||||
for _, alert := range Alerts {
|
||||
alertsStore[alert.ID] = make(map[uint64][][]interface{})
|
||||
alertsStore[alert.ID] = make(map[uint64][][]bool)
|
||||
alertsPrevState[alert.ID] = make(map[uint64]uint8)
|
||||
addCycleTransferStatsInfo(alert)
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func AlertSentinelStart() {
|
||||
}
|
||||
}
|
||||
|
||||
func OnRefreshOrAddAlert(alert model.AlertRule) {
|
||||
func OnRefreshOrAddAlert(alert *model.AlertRule) {
|
||||
AlertsLock.Lock()
|
||||
defer AlertsLock.Unlock()
|
||||
delete(alertsStore, alert.ID)
|
||||
@@ -99,17 +99,17 @@ func OnRefreshOrAddAlert(alert model.AlertRule) {
|
||||
var isEdit bool
|
||||
for i := 0; i < len(Alerts); i++ {
|
||||
if Alerts[i].ID == alert.ID {
|
||||
Alerts[i] = &alert
|
||||
Alerts[i] = alert
|
||||
isEdit = true
|
||||
}
|
||||
}
|
||||
if !isEdit {
|
||||
Alerts = append(Alerts, &alert)
|
||||
Alerts = append(Alerts, alert)
|
||||
}
|
||||
alertsStore[alert.ID] = make(map[uint64][][]interface{})
|
||||
alertsStore[alert.ID] = make(map[uint64][][]bool)
|
||||
alertsPrevState[alert.ID] = make(map[uint64]uint8)
|
||||
delete(AlertsCycleTransferStatsStore, alert.ID)
|
||||
addCycleTransferStatsInfo(&alert)
|
||||
addCycleTransferStatsInfo(alert)
|
||||
}
|
||||
|
||||
func OnDeleteAlert(id []uint64) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package singleton
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"github.com/jinzhu/copier"
|
||||
@@ -15,8 +16,10 @@ import (
|
||||
|
||||
var (
|
||||
Cron *cron.Cron
|
||||
Crons map[uint64]*model.Cron // [CrondID] -> *model.Cron
|
||||
Crons map[uint64]*model.Cron // [CronID] -> *model.Cron
|
||||
CronLock sync.RWMutex
|
||||
|
||||
CronList []*model.Cron
|
||||
)
|
||||
|
||||
func InitCronTask() {
|
||||
@@ -27,29 +30,28 @@ func InitCronTask() {
|
||||
// loadCronTasks 加载计划任务
|
||||
func loadCronTasks() {
|
||||
InitCronTask()
|
||||
var crons []model.Cron
|
||||
DB.Find(&crons)
|
||||
DB.Find(&CronList)
|
||||
var err error
|
||||
var notificationGroupList []uint64
|
||||
notificationMsgMap := make(map[uint64]*bytes.Buffer)
|
||||
for i := 0; i < len(crons); i++ {
|
||||
for i := 0; i < len(CronList); i++ {
|
||||
// 触发任务类型无需注册
|
||||
if crons[i].TaskType == model.CronTypeTriggerTask {
|
||||
Crons[crons[i].ID] = &crons[i]
|
||||
if CronList[i].TaskType == model.CronTypeTriggerTask {
|
||||
Crons[CronList[i].ID] = CronList[i]
|
||||
continue
|
||||
}
|
||||
// 注册计划任务
|
||||
crons[i].CronJobID, err = Cron.AddFunc(crons[i].Scheduler, CronTrigger(crons[i]))
|
||||
CronList[i].CronJobID, err = Cron.AddFunc(CronList[i].Scheduler, CronTrigger(CronList[i]))
|
||||
if err == nil {
|
||||
Crons[crons[i].ID] = &crons[i]
|
||||
Crons[CronList[i].ID] = CronList[i]
|
||||
} else {
|
||||
// 当前通知组首次出现 将其加入通知组列表并初始化通知组消息缓存
|
||||
if _, ok := notificationMsgMap[crons[i].NotificationGroupID]; !ok {
|
||||
notificationGroupList = append(notificationGroupList, crons[i].NotificationGroupID)
|
||||
notificationMsgMap[crons[i].NotificationGroupID] = bytes.NewBufferString("")
|
||||
notificationMsgMap[crons[i].NotificationGroupID].WriteString("调度失败的计划任务:[")
|
||||
if _, ok := notificationMsgMap[CronList[i].NotificationGroupID]; !ok {
|
||||
notificationGroupList = append(notificationGroupList, CronList[i].NotificationGroupID)
|
||||
notificationMsgMap[CronList[i].NotificationGroupID] = bytes.NewBufferString("")
|
||||
notificationMsgMap[CronList[i].NotificationGroupID].WriteString("调度失败的计划任务:[")
|
||||
}
|
||||
notificationMsgMap[crons[i].NotificationGroupID].WriteString(fmt.Sprintf("%d,", crons[i].ID))
|
||||
notificationMsgMap[CronList[i].NotificationGroupID].WriteString(fmt.Sprintf("%d,", CronList[i].ID))
|
||||
}
|
||||
}
|
||||
// 向注册错误的计划任务所在通知组发送通知
|
||||
@@ -60,7 +62,49 @@ func loadCronTasks() {
|
||||
Cron.Start()
|
||||
}
|
||||
|
||||
func ManualTrigger(c model.Cron) {
|
||||
func OnRefreshOrAddCron(c *model.Cron) {
|
||||
CronLock.Lock()
|
||||
defer CronLock.Unlock()
|
||||
crOld := Crons[c.ID]
|
||||
if crOld != nil && crOld.CronJobID != 0 {
|
||||
Cron.Remove(crOld.CronJobID)
|
||||
}
|
||||
|
||||
delete(Crons, c.ID)
|
||||
Crons[c.ID] = c
|
||||
}
|
||||
|
||||
func UpdateCronList() {
|
||||
CronLock.RLock()
|
||||
defer CronLock.RUnlock()
|
||||
|
||||
CronList = make([]*model.Cron, 0, len(Crons))
|
||||
for _, c := range Crons {
|
||||
CronList = append(CronList, c)
|
||||
}
|
||||
slices.SortFunc(CronList, func(a, b *model.Cron) int {
|
||||
if a.ID < b.ID {
|
||||
return -1
|
||||
} else if a.ID == b.ID {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
})
|
||||
}
|
||||
|
||||
func OnDeleteCron(id []uint64) {
|
||||
CronLock.Lock()
|
||||
defer CronLock.Unlock()
|
||||
for _, i := range id {
|
||||
cr := Crons[i]
|
||||
if cr != nil && cr.CronJobID != 0 {
|
||||
Cron.Remove(cr.CronJobID)
|
||||
}
|
||||
delete(Crons, i)
|
||||
}
|
||||
}
|
||||
|
||||
func ManualTrigger(c *model.Cron) {
|
||||
CronTrigger(c)()
|
||||
}
|
||||
|
||||
@@ -76,11 +120,11 @@ func SendTriggerTasks(taskIDs []uint64, triggerServer uint64) {
|
||||
|
||||
// 依次调用CronTrigger发送任务
|
||||
for _, c := range cronLists {
|
||||
go CronTrigger(*c, triggerServer)()
|
||||
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)
|
||||
for j := 0; j < len(cr.Servers); j++ {
|
||||
crIgnoreMap[cr.Servers[j]] = true
|
||||
|
||||
@@ -21,16 +21,14 @@ var (
|
||||
)
|
||||
|
||||
func initDDNS() {
|
||||
var ddns []*model.DDNSProfile
|
||||
DB.Find(&ddns)
|
||||
DB.Find(&DDNSList)
|
||||
DDNSCacheLock.Lock()
|
||||
DDNSCache = make(map[uint64]*model.DDNSProfile)
|
||||
for i := 0; i < len(ddns); i++ {
|
||||
DDNSCache[ddns[i].ID] = ddns[i]
|
||||
for i := 0; i < len(DDNSList); i++ {
|
||||
DDNSCache[DDNSList[i].ID] = DDNSList[i]
|
||||
}
|
||||
DDNSCacheLock.Unlock()
|
||||
|
||||
UpdateDDNSList()
|
||||
OnNameserverUpdate()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,75 @@
|
||||
package singleton
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"github.com/naiba/nezha/model"
|
||||
)
|
||||
|
||||
var natCache = make(map[string]*model.NAT)
|
||||
var natCacheRwLock = new(sync.RWMutex)
|
||||
var (
|
||||
NATCache = make(map[string]*model.NAT)
|
||||
NATCacheRwLock sync.RWMutex
|
||||
|
||||
NATIDToDomain = make(map[uint64]string)
|
||||
NATList []*model.NAT
|
||||
)
|
||||
|
||||
func initNAT() {
|
||||
OnNATUpdate()
|
||||
}
|
||||
|
||||
func OnNATUpdate() {
|
||||
natCacheRwLock.Lock()
|
||||
defer natCacheRwLock.Unlock()
|
||||
var nats []*model.NAT
|
||||
DB.Find(&nats)
|
||||
natCache = make(map[string]*model.NAT)
|
||||
for i := 0; i < len(nats); i++ {
|
||||
natCache[nats[i].Domain] = nats[i]
|
||||
DB.Find(&NATList)
|
||||
NATCacheRwLock.Lock()
|
||||
defer NATCacheRwLock.Unlock()
|
||||
NATCache = make(map[string]*model.NAT)
|
||||
for i := 0; i < len(NATList); i++ {
|
||||
NATCache[NATList[i].Domain] = NATList[i]
|
||||
NATIDToDomain[NATList[i].ID] = NATList[i].Domain
|
||||
}
|
||||
}
|
||||
|
||||
func GetNATConfigByDomain(domain string) *model.NAT {
|
||||
natCacheRwLock.RLock()
|
||||
defer natCacheRwLock.RUnlock()
|
||||
return natCache[domain]
|
||||
func OnNATUpdate(n *model.NAT) {
|
||||
NATCacheRwLock.Lock()
|
||||
defer NATCacheRwLock.Unlock()
|
||||
|
||||
if oldDomain, ok := NATIDToDomain[n.ID]; ok && oldDomain != n.Domain {
|
||||
delete(NATCache, oldDomain)
|
||||
}
|
||||
|
||||
NATCache[n.Domain] = n
|
||||
NATIDToDomain[n.ID] = n.Domain
|
||||
}
|
||||
|
||||
func OnNATDelete(id []uint64) {
|
||||
NATCacheRwLock.Lock()
|
||||
defer NATCacheRwLock.Unlock()
|
||||
|
||||
for _, i := range id {
|
||||
if domain, ok := NATIDToDomain[i]; ok {
|
||||
delete(NATCache, domain)
|
||||
delete(NATIDToDomain, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateNATList() {
|
||||
NATCacheRwLock.RLock()
|
||||
defer NATCacheRwLock.RUnlock()
|
||||
|
||||
NATList = make([]*model.NAT, 0, len(NATCache))
|
||||
for _, n := range NATCache {
|
||||
NATList = append(NATList, n)
|
||||
}
|
||||
slices.SortFunc(NATList, func(a, b *model.NAT) int {
|
||||
if a.ID < b.ID {
|
||||
return -1
|
||||
} else if a.ID == b.ID {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
})
|
||||
}
|
||||
|
||||
func GetNATConfigByDomain(domain string) *model.NAT {
|
||||
NATCacheRwLock.RLock()
|
||||
defer NATCacheRwLock.RUnlock()
|
||||
return NATCache[domain]
|
||||
}
|
||||
|
||||
@@ -49,14 +49,13 @@ func loadNotifications() {
|
||||
groupNotifications[n.NotificationGroupID] = append(groupNotifications[n.NotificationGroupID], n.NotificationID)
|
||||
}
|
||||
|
||||
var notifications []model.Notification
|
||||
if err := DB.Find(¬ifications).Error; err != nil {
|
||||
if err := DB.Find(&NotificationListSorted).Error; err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
NotificationMap = make(map[uint64]*model.Notification, len(notifications))
|
||||
for i := range notifications {
|
||||
NotificationMap[notifications[i].ID] = ¬ifications[i]
|
||||
NotificationMap = make(map[uint64]*model.Notification, len(NotificationListSorted))
|
||||
for i := range NotificationListSorted {
|
||||
NotificationMap[NotificationListSorted[i].ID] = NotificationListSorted[i]
|
||||
}
|
||||
|
||||
for gid, nids := range groupNotifications {
|
||||
@@ -75,7 +74,6 @@ func loadNotifications() {
|
||||
}
|
||||
|
||||
NotificationsLock.Unlock()
|
||||
UpdateNotificationList()
|
||||
}
|
||||
|
||||
func UpdateNotificationList() {
|
||||
|
||||
@@ -45,8 +45,8 @@ func ReSortServer() {
|
||||
SortedServerLock.Lock()
|
||||
defer SortedServerLock.Unlock()
|
||||
|
||||
SortedServerList = []*model.Server{}
|
||||
SortedServerListForGuest = []*model.Server{}
|
||||
SortedServerList = make([]*model.Server, 0, len(ServerList))
|
||||
var SortedServerListForGuest []*model.Server
|
||||
for _, s := range ServerList {
|
||||
SortedServerList = append(SortedServerList, s)
|
||||
if !s.HideForGuest {
|
||||
|
||||
Reference in New Issue
Block a user