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:
@@ -61,55 +61,55 @@ func (r *AlertRule) Enabled() bool {
|
||||
return r.Enable != nil && *r.Enable
|
||||
}
|
||||
|
||||
// Snapshot 对传入的Server进行该报警规则下所有type的检查 返回包含每项检查结果的空接口
|
||||
func (r *AlertRule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server, db *gorm.DB) []interface{} {
|
||||
var point []interface{}
|
||||
for i := 0; i < len(r.Rules); i++ {
|
||||
point = append(point, r.Rules[i].Snapshot(cycleTransferStats, server, db))
|
||||
// Snapshot 对传入的Server进行该报警规则下所有type的检查 返回每项检查结果
|
||||
func (r *AlertRule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server, db *gorm.DB) []bool {
|
||||
point := make([]bool, 0, len(r.Rules))
|
||||
for _, rule := range r.Rules {
|
||||
point = append(point, rule.Snapshot(cycleTransferStats, server, db))
|
||||
}
|
||||
return point
|
||||
}
|
||||
|
||||
// Check 传入包含当前报警规则下所有type检查结果的空接口 返回报警持续时间与是否通过报警检查(通过则返回true)
|
||||
func (r *AlertRule) Check(points [][]interface{}) (int, bool) {
|
||||
var maxNum int // 报警持续时间
|
||||
var count int // 检查未通过的个数
|
||||
for i := 0; i < len(r.Rules); i++ {
|
||||
if r.Rules[i].IsTransferDurationRule() {
|
||||
// Check 传入包含当前报警规则下所有type检查结果 返回报警持续时间与是否通过报警检查(通过则返回true)
|
||||
func (r *AlertRule) Check(points [][]bool) (maxDuration int, passed bool) {
|
||||
failCount := 0 // 检查未通过的个数
|
||||
|
||||
for i, rule := range r.Rules {
|
||||
if rule.IsTransferDurationRule() {
|
||||
// 循环区间流量报警
|
||||
if maxNum < 1 {
|
||||
maxNum = 1
|
||||
if maxDuration < 1 {
|
||||
maxDuration = 1
|
||||
}
|
||||
for j := len(points[i]) - 1; j >= 0; j-- {
|
||||
if points[i][j] != nil {
|
||||
count++
|
||||
if !points[i][j] {
|
||||
failCount++
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 常规报警
|
||||
total := 0.0
|
||||
fail := 0.0
|
||||
num := int(r.Rules[i].Duration)
|
||||
if num > maxNum {
|
||||
maxNum = num
|
||||
duration := int(rule.Duration)
|
||||
if duration > maxDuration {
|
||||
maxDuration = duration
|
||||
}
|
||||
if len(points) < num {
|
||||
if len(points) < duration {
|
||||
continue
|
||||
}
|
||||
for j := len(points) - 1; j >= 0 && len(points)-num <= j; j-- {
|
||||
|
||||
total, fail := 0.0, 0.0
|
||||
for j := len(points) - duration; j < len(points); j++ {
|
||||
total++
|
||||
if points[j][i] != nil {
|
||||
if !points[j][i] {
|
||||
fail++
|
||||
}
|
||||
}
|
||||
// 当70%以上的采样点未通过规则判断时 才认为当前检查未通过
|
||||
if fail/total > 0.7 {
|
||||
count++
|
||||
failCount++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// 仅当所有检查均未通过时 返回false
|
||||
return maxNum, count != len(r.Rules)
|
||||
return maxDuration, failCount != len(r.Rules)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package model
|
||||
|
||||
type AlertRuleForm struct {
|
||||
ID uint64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Rules []Rule `json:"rules"`
|
||||
FailTriggerTasks []uint64 `json:"fail_trigger_tasks"` // 失败时触发的任务id
|
||||
|
||||
@@ -18,19 +18,19 @@ const (
|
||||
|
||||
type Cron struct {
|
||||
Common
|
||||
Name string
|
||||
TaskType uint8 `gorm:"default:0"` // 0:计划任务 1:触发任务
|
||||
Scheduler string //分钟 小时 天 月 星期
|
||||
Command string
|
||||
Servers []uint64 `gorm:"-"`
|
||||
PushSuccessful bool // 推送成功的通知
|
||||
NotificationGroupID uint64 // 指定通知方式的分组
|
||||
LastExecutedAt time.Time // 最后一次执行时间
|
||||
LastResult bool // 最后一次执行结果
|
||||
Cover uint8 // 计划任务覆盖范围 (0:仅覆盖特定服务器 1:仅忽略特定服务器 2:由触发该计划任务的服务器执行)
|
||||
Name string `json:"name,omitempty"`
|
||||
TaskType uint8 `gorm:"default:0" json:"task_type,omitempty"` // 0:计划任务 1:触发任务
|
||||
Scheduler string `json:"scheduler,omitempty"` // 分钟 小时 天 月 星期
|
||||
Command string `json:"command,omitempty"`
|
||||
Servers []uint64 `gorm:"-" json:"servers,omitempty"`
|
||||
PushSuccessful bool `json:"push_successful,omitempty"` // 推送成功的通知
|
||||
NotificationGroupID uint64 `json:"notification_group_id,omitempty"` // 指定通知方式的分组
|
||||
LastExecutedAt time.Time `json:"last_executed_at,omitempty"` // 最后一次执行时间
|
||||
LastResult bool `json:"last_result,omitempty"` // 最后一次执行结果
|
||||
Cover uint8 `json:"cover,omitempty"` // 计划任务覆盖范围 (0:仅覆盖特定服务器 1:仅忽略特定服务器 2:由触发该计划任务的服务器执行)
|
||||
|
||||
CronJobID cron.EntryID `gorm:"-"`
|
||||
ServersRaw string
|
||||
CronJobID cron.EntryID `gorm:"-" json:"cron_job_id,omitempty"`
|
||||
ServersRaw string `json:"-"`
|
||||
}
|
||||
|
||||
func (c *Cron) AfterFind(tx *gorm.DB) error {
|
||||
|
||||
13
model/cron_api.go
Normal file
13
model/cron_api.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package model
|
||||
|
||||
type CronForm struct {
|
||||
ID uint64 `json:"id,omitempty"`
|
||||
TaskType uint8 `json:"task_type,omitempty"` // 0:计划任务 1:触发任务
|
||||
Name string `json:"name,omitempty"`
|
||||
Scheduler string `json:"scheduler,omitempty"`
|
||||
Command string `json:"command,omitempty"`
|
||||
Servers []uint64 `json:"servers,omitempty"`
|
||||
Cover uint8 `json:"cover,omitempty"`
|
||||
PushSuccessful bool `json:"push_successful,omitempty"`
|
||||
NotificationGroupID uint64 `json:"notification_group_id,omitempty"`
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package model
|
||||
|
||||
type DDNSForm struct {
|
||||
ID uint64 `json:"id,omitempty"`
|
||||
MaxRetries uint64 `json:"max_retries,omitempty"`
|
||||
EnableIPv4 bool `json:"enable_ipv4,omitempty"`
|
||||
EnableIPv6 bool `json:"enable_ipv6,omitempty"`
|
||||
|
||||
8
model/nat_api.go
Normal file
8
model/nat_api.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package model
|
||||
|
||||
type NATForm struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
ServerID uint64 `json:"server_id,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
}
|
||||
@@ -41,18 +41,6 @@ type Notification struct {
|
||||
VerifySSL *bool `json:"verify_ssl,omitempty"`
|
||||
}
|
||||
|
||||
type NotificationForm struct {
|
||||
ID uint64 `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
RequestMethod int `json:"request_method,omitempty"`
|
||||
RequestType int `json:"request_type,omitempty"`
|
||||
RequestHeader string `json:"request_header,omitempty"`
|
||||
RequestBody string `json:"request_body,omitempty"`
|
||||
VerifySSL bool `json:"verify_ssl,omitempty"`
|
||||
SkipCheck bool `json:"skip_check,omitempty"`
|
||||
}
|
||||
|
||||
func (ns *NotificationServerBundle) reqURL(message string) string {
|
||||
n := ns.Notification
|
||||
return ns.replaceParamsInString(n.URL, message, func(msg string) string {
|
||||
|
||||
12
model/notification_api.go
Normal file
12
model/notification_api.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package model
|
||||
|
||||
type NotificationForm struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
RequestMethod int `json:"request_method,omitempty"`
|
||||
RequestType int `json:"request_type,omitempty"`
|
||||
RequestHeader string `json:"request_header,omitempty"`
|
||||
RequestBody string `json:"request_body,omitempty"`
|
||||
VerifySSL bool `json:"verify_ssl,omitempty"`
|
||||
SkipCheck bool `json:"skip_check,omitempty"`
|
||||
}
|
||||
@@ -34,8 +34,8 @@ type Rule struct {
|
||||
Ignore map[uint64]bool `json:"ignore,omitempty"` // 覆盖范围的排除
|
||||
|
||||
// 只作为缓存使用,记录下次该检测的时间
|
||||
NextTransferAt map[uint64]time.Time `json:"-"`
|
||||
LastCycleStatus map[uint64]interface{} `json:"-"`
|
||||
NextTransferAt map[uint64]time.Time `json:"-"`
|
||||
LastCycleStatus map[uint64]bool `json:"-"`
|
||||
}
|
||||
|
||||
func percentage(used, total uint64) float64 {
|
||||
@@ -45,15 +45,15 @@ func percentage(used, total uint64) float64 {
|
||||
return float64(used) * 100 / float64(total)
|
||||
}
|
||||
|
||||
// Snapshot 未通过规则返回 struct{}{}, 通过返回 nil
|
||||
func (u *Rule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server, db *gorm.DB) interface{} {
|
||||
// Snapshot 未通过规则返回 false, 通过返回 true
|
||||
func (u *Rule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server, db *gorm.DB) bool {
|
||||
// 监控全部但是排除了此服务器
|
||||
if u.Cover == RuleCoverAll && u.Ignore[server.ID] {
|
||||
return nil
|
||||
return true
|
||||
}
|
||||
// 忽略全部但是指定监控了此服务器
|
||||
if u.Cover == RuleCoverIgnoreAll && !u.Ignore[server.ID] {
|
||||
return nil
|
||||
return true
|
||||
}
|
||||
|
||||
// 循环区间流量检测 · 短期无需重复检测
|
||||
@@ -147,13 +147,13 @@ func (u *Rule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server,
|
||||
u.NextTransferAt = make(map[uint64]time.Time)
|
||||
}
|
||||
if u.LastCycleStatus == nil {
|
||||
u.LastCycleStatus = make(map[uint64]interface{})
|
||||
u.LastCycleStatus = make(map[uint64]bool)
|
||||
}
|
||||
u.NextTransferAt[server.ID] = time.Now().Add(time.Second * time.Duration(seconds))
|
||||
if (u.Max > 0 && src > u.Max) || (u.Min > 0 && src < u.Min) {
|
||||
u.LastCycleStatus[server.ID] = struct{}{}
|
||||
u.LastCycleStatus[server.ID] = false
|
||||
} else {
|
||||
u.LastCycleStatus[server.ID] = nil
|
||||
u.LastCycleStatus[server.ID] = true
|
||||
}
|
||||
if cycleTransferStats.ServerName[server.ID] != server.Name {
|
||||
cycleTransferStats.ServerName[server.ID] = server.Name
|
||||
@@ -166,12 +166,12 @@ func (u *Rule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server,
|
||||
}
|
||||
|
||||
if u.Type == "offline" && float64(time.Now().Unix())-src > 6 {
|
||||
return struct{}{}
|
||||
return false
|
||||
} else if (u.Max > 0 && src > u.Max) || (u.Min > 0 && src < u.Min) {
|
||||
return struct{}{}
|
||||
return false
|
||||
}
|
||||
|
||||
return nil
|
||||
return true
|
||||
}
|
||||
|
||||
// IsTransferDurationRule 判断该规则是否属于周期流量规则 属于则返回true
|
||||
|
||||
Reference in New Issue
Block a user