- 三个新事件(默认关闭):公网服务端掉线、公网 agent 不可达、配置漂移;连续失败阈值与漂移提醒间隔均可配,达标与恢复各报一次 - 避免误报:只在「用户要服务端运行」时判定掉线;ConnectionState=unknown 按健康处理;没配 agent 的服务端不参与可达性判定 - internal/monitor 改 Source 接口(Routes/Servers/Agents/Drift),frp 适配在 internal/app/monitor_source.go;「连续 N 次」抽成共用 failureTransition,通知一律在锁外调用 - 通知图标分类补齐;通知方式标签改「Webhook / IM 机器人」;新增 6 个设置项;补 serverDown/serverLabel/stateOr 测试 - agent 无改动,AgentVersion 保持 0.12.2
This commit is contained in:
@@ -11,6 +11,9 @@ const (
|
||||
EventNginxReloadFailure = "nginx_reload_failure"
|
||||
EventResourceThreshold = "resource_threshold"
|
||||
EventTunnelDown = "tunnel_down"
|
||||
EventFrpsServerDown = "frps_server_down"
|
||||
EventAgentUnreachable = "agent_unreachable"
|
||||
EventRouteDrift = "route_drift"
|
||||
|
||||
MaskedSecret = "********"
|
||||
|
||||
@@ -29,6 +32,9 @@ const (
|
||||
DefaultMemoryThreshold = 90
|
||||
DefaultDiskThreshold = 85
|
||||
DefaultTunnelFailThreshold = 3
|
||||
DefaultFrpsFailThreshold = 2
|
||||
DefaultAgentFailThreshold = 3
|
||||
DefaultDriftCooldownHours = 24
|
||||
// DefaultResourceAlertCooldown 是资源类告警的静默期:持续高占用时每半小时提醒一次,
|
||||
// 期间恢复正常会清掉冷却,再次超标可立即再报。
|
||||
DefaultResourceAlertCooldown = 30 * 60 // seconds
|
||||
@@ -113,6 +119,12 @@ type Config struct {
|
||||
MemoryThreshold int `json:"memory_threshold"`
|
||||
DiskThreshold int `json:"disk_threshold"`
|
||||
TunnelFailThreshold int `json:"tunnel_fail_threshold"`
|
||||
OnFrpsDown bool `json:"on_frps_down"`
|
||||
OnAgentUnreachable bool `json:"on_agent_unreachable"`
|
||||
OnRouteDrift bool `json:"on_route_drift"`
|
||||
FrpsFailThreshold int `json:"frps_fail_threshold"`
|
||||
AgentFailThreshold int `json:"agent_fail_threshold"`
|
||||
DriftCooldownHours int `json:"drift_cooldown_hours"`
|
||||
}
|
||||
|
||||
type RuntimeConfig struct {
|
||||
@@ -148,6 +160,12 @@ type SaveInput struct {
|
||||
MemoryThreshold int
|
||||
DiskThreshold int
|
||||
TunnelFailThreshold int
|
||||
OnFrpsDown bool
|
||||
OnAgentUnreachable bool
|
||||
OnRouteDrift bool
|
||||
FrpsFailThreshold int
|
||||
AgentFailThreshold int
|
||||
DriftCooldownHours int
|
||||
}
|
||||
|
||||
type TestInput struct {
|
||||
|
||||
@@ -86,6 +86,16 @@ func eventMetaFor(event string) eventMeta {
|
||||
return eventMeta{"🔐", "安全"}
|
||||
case EventNginxReloadFailure:
|
||||
return eventMeta{"⚙️", "系统"}
|
||||
case EventResourceThreshold:
|
||||
return eventMeta{"📈", "系统"}
|
||||
case EventTunnelDown:
|
||||
return eventMeta{"🔌", "隧道"}
|
||||
case EventFrpsServerDown:
|
||||
return eventMeta{"🛑", "隧道"}
|
||||
case EventAgentUnreachable:
|
||||
return eventMeta{"📡", "隧道"}
|
||||
case EventRouteDrift:
|
||||
return eventMeta{"🧭", "配置"}
|
||||
case "test":
|
||||
return eventMeta{"🔔", "系统"}
|
||||
default:
|
||||
|
||||
@@ -246,6 +246,12 @@ func (s *Service) enabledFor(cfg RuntimeConfig, event string) bool {
|
||||
return cfg.OnResourceThreshold
|
||||
case EventTunnelDown:
|
||||
return cfg.OnTunnelDown
|
||||
case EventFrpsServerDown:
|
||||
return cfg.OnFrpsDown
|
||||
case EventAgentUnreachable:
|
||||
return cfg.OnAgentUnreachable
|
||||
case EventRouteDrift:
|
||||
return cfg.OnRouteDrift
|
||||
default:
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -80,6 +80,9 @@ func (s *Store) load(ctx context.Context, decrypt bool) (Config, runtimeSecrets,
|
||||
cfg.MemoryThreshold = intSetting(s.settings, ctx, settings.KeyNotifyMemoryThreshold, DefaultMemoryThreshold)
|
||||
cfg.DiskThreshold = intSetting(s.settings, ctx, settings.KeyNotifyDiskThreshold, DefaultDiskThreshold)
|
||||
cfg.TunnelFailThreshold = intSetting(s.settings, ctx, settings.KeyNotifyTunnelFailThreshold, DefaultTunnelFailThreshold)
|
||||
cfg.FrpsFailThreshold = intSetting(s.settings, ctx, settings.KeyNotifyFrpsFailThreshold, DefaultFrpsFailThreshold)
|
||||
cfg.AgentFailThreshold = intSetting(s.settings, ctx, settings.KeyNotifyAgentFailThreshold, DefaultAgentFailThreshold)
|
||||
cfg.DriftCooldownHours = intSetting(s.settings, ctx, settings.KeyNotifyDriftCooldownHours, DefaultDriftCooldownHours)
|
||||
|
||||
if hasNotifyEventSettings(ctx, s.settings) {
|
||||
cfg.OnDDNSIPChange = flag(s.settings, ctx, settings.KeyNotifyOnDDNSIPChange, true)
|
||||
@@ -93,6 +96,9 @@ func (s *Store) load(ctx context.Context, decrypt bool) (Config, runtimeSecrets,
|
||||
// 资源与隧道告警默认关闭:升级后不改变现有用户收到的通知
|
||||
cfg.OnResourceThreshold = flag(s.settings, ctx, settings.KeyNotifyOnResourceThreshold, false)
|
||||
cfg.OnTunnelDown = flag(s.settings, ctx, settings.KeyNotifyOnTunnelDown, false)
|
||||
cfg.OnFrpsDown = flag(s.settings, ctx, settings.KeyNotifyOnFrpsDown, false)
|
||||
cfg.OnAgentUnreachable = flag(s.settings, ctx, settings.KeyNotifyOnAgentUnreachable, false)
|
||||
cfg.OnRouteDrift = flag(s.settings, ctx, settings.KeyNotifyOnRouteDrift, false)
|
||||
} else {
|
||||
legacyDDNS := flag(s.settings, ctx, settings.KeyNotifyOnDDNSError, true)
|
||||
legacyCert := flag(s.settings, ctx, settings.KeyNotifyOnCertError, true)
|
||||
@@ -193,6 +199,9 @@ func hasNotifyEventSettings(ctx context.Context, store *settings.Store) bool {
|
||||
settings.KeyNotifyOnNginxReloadFailure,
|
||||
settings.KeyNotifyOnResourceThreshold,
|
||||
settings.KeyNotifyOnTunnelDown,
|
||||
settings.KeyNotifyOnFrpsDown,
|
||||
settings.KeyNotifyOnAgentUnreachable,
|
||||
settings.KeyNotifyOnRouteDrift,
|
||||
}
|
||||
for _, key := range keys {
|
||||
raw, err := store.Get(ctx, key)
|
||||
@@ -253,6 +262,24 @@ func (s *Store) Save(ctx context.Context, in SaveInput) error {
|
||||
if err := s.settings.SetInt(ctx, settings.KeyNotifyTunnelFailThreshold, clampThreshold(in.TunnelFailThreshold, DefaultTunnelFailThreshold)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.settings.SetBool(ctx, settings.KeyNotifyOnFrpsDown, in.OnFrpsDown); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.settings.SetBool(ctx, settings.KeyNotifyOnAgentUnreachable, in.OnAgentUnreachable); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.settings.SetBool(ctx, settings.KeyNotifyOnRouteDrift, in.OnRouteDrift); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.settings.SetInt(ctx, settings.KeyNotifyFrpsFailThreshold, clampThreshold(in.FrpsFailThreshold, DefaultFrpsFailThreshold)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.settings.SetInt(ctx, settings.KeyNotifyAgentFailThreshold, clampThreshold(in.AgentFailThreshold, DefaultAgentFailThreshold)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.settings.SetInt(ctx, settings.KeyNotifyDriftCooldownHours, clampThreshold(in.DriftCooldownHours, DefaultDriftCooldownHours)); err != nil {
|
||||
return err
|
||||
}
|
||||
threshold := in.IPFrequentThreshold
|
||||
if threshold <= 0 {
|
||||
threshold = DefaultIPFrequentThreshold
|
||||
@@ -493,6 +520,12 @@ func ParseSaveInputFromMap(values map[string]string) (SaveInput, bool) {
|
||||
in.MemoryThreshold = intSettingFromMap(values, settings.KeyNotifyMemoryThreshold, DefaultMemoryThreshold)
|
||||
in.DiskThreshold = intSettingFromMap(values, settings.KeyNotifyDiskThreshold, DefaultDiskThreshold)
|
||||
in.TunnelFailThreshold = intSettingFromMap(values, settings.KeyNotifyTunnelFailThreshold, DefaultTunnelFailThreshold)
|
||||
in.OnFrpsDown = values[settings.KeyNotifyOnFrpsDown] == "1" || strings.EqualFold(values[settings.KeyNotifyOnFrpsDown], "true")
|
||||
in.OnAgentUnreachable = values[settings.KeyNotifyOnAgentUnreachable] == "1" || strings.EqualFold(values[settings.KeyNotifyOnAgentUnreachable], "true")
|
||||
in.OnRouteDrift = values[settings.KeyNotifyOnRouteDrift] == "1" || strings.EqualFold(values[settings.KeyNotifyOnRouteDrift], "true")
|
||||
in.FrpsFailThreshold = intSettingFromMap(values, settings.KeyNotifyFrpsFailThreshold, DefaultFrpsFailThreshold)
|
||||
in.AgentFailThreshold = intSettingFromMap(values, settings.KeyNotifyAgentFailThreshold, DefaultAgentFailThreshold)
|
||||
in.DriftCooldownHours = intSettingFromMap(values, settings.KeyNotifyDriftCooldownHours, DefaultDriftCooldownHours)
|
||||
return in, true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user