@@ -407,6 +407,11 @@ func UpdateTrafficStats(serverID uint64, inTransfer, outTransfer uint64) {
407407 // 更新最后更新时间
408408 stats .NextUpdate [serverID ] = time .Now ()
409409
410+ // 检查多级流量阈值并发送通知
411+ if server := ServerList [serverID ]; server != nil {
412+ checkTrafficThresholds (alert , server , & alert .Rules [j ], totalTransfer )
413+ }
414+
410415 // 找到一个满足条件的规则即可退出循环
411416 break
412417 }
@@ -535,7 +540,7 @@ func generateDetailedAlertMessage(alert *model.AlertRule, server *model.Server,
535540 return message
536541}
537542
538- // generateTrafficAlertDetails 生成流量报警的详细信息
543+ // generateTrafficAlertDetails 生成流量报警的详细信息,支持多级阈值通知
539544func generateTrafficAlertDetails (rule * model.Rule , server * model.Server , alertID uint64 ) string {
540545 var details string
541546
@@ -549,12 +554,6 @@ func generateTrafficAlertDetails(rule *model.Rule, server *model.Server, alertID
549554 currentUsage := stats .Transfer [server .ID ]
550555 maxLimit := uint64 (rule .Max )
551556
552- // 计算超额部分
553- var overageAmount uint64
554- if currentUsage > maxLimit {
555- overageAmount = currentUsage - maxLimit
556- }
557-
558557 // 计算使用率
559558 usagePercent := float64 (0 )
560559 if maxLimit > 0 {
@@ -577,13 +576,38 @@ func generateTrafficAlertDetails(rule *model.Rule, server *model.Server, alertID
577576 stats .From .Format ("2006-01-02 15:04:05" ),
578577 stats .To .Format ("2006-01-02 15:04:05" ))
579578
579+ // 根据使用率生成不同级别的告警信息
580+ var alertLevel string
581+ var alertIcon string
582+
583+ switch {
584+ case usagePercent >= 100 :
585+ alertLevel = "🚨 流量超限告警"
586+ alertIcon = "🚨"
587+ case usagePercent >= 90 :
588+ alertLevel = "⚠️ 流量高使用率告警 (90%)"
589+ alertIcon = "⚠️"
590+ case usagePercent >= 50 :
591+ alertLevel = "📊 流量使用率提醒 (50%)"
592+ alertIcon = "📊"
593+ default :
594+ alertLevel = "📈 流量监控提醒"
595+ alertIcon = "📈"
596+ }
597+
580598 // 生成详细信息
581- details += fmt .Sprintf ("• %s超限:\n " , trafficType )
582- details += fmt .Sprintf (" - 当前使用: %s (%.2f%%)\n " , formatBytes (currentUsage ), usagePercent )
599+ details += fmt .Sprintf ("• %s %s:\n " , alertIcon , alertLevel )
600+ details += fmt .Sprintf (" - 服务器: %s\n " , server .Name )
601+ details += fmt .Sprintf (" - %s使用: %s (%.2f%%)\n " , trafficType , formatBytes (currentUsage ), usagePercent )
583602 details += fmt .Sprintf (" - 额定流量: %s\n " , formatBytes (maxLimit ))
584603
585- if overageAmount > 0 {
586- details += fmt .Sprintf (" - 超额: %s\n " , formatBytes (overageAmount ))
604+ // 计算剩余流量
605+ if currentUsage < maxLimit {
606+ remainingBytes := maxLimit - currentUsage
607+ details += fmt .Sprintf (" - 剩余流量: %s\n " , formatBytes (remainingBytes ))
608+ } else {
609+ overageAmount := currentUsage - maxLimit
610+ details += fmt .Sprintf (" - 超额流量: %s\n " , formatBytes (overageAmount ))
587611 }
588612
589613 details += fmt .Sprintf (" - %s\n " , periodInfo )
@@ -778,3 +802,94 @@ func generateDetailedRecoveryMessage(alert *model.AlertRule, server *model.Serve
778802
779803 return message
780804}
805+
806+ // checkTrafficThresholds 检查流量阈值并发送相应通知
807+ func checkTrafficThresholds (alert * model.AlertRule , server * model.Server , rule * model.Rule , currentUsage uint64 ) {
808+ if rule .Max <= 0 {
809+ return
810+ }
811+
812+ usagePercent := float64 (currentUsage ) / rule .Max * 100
813+
814+ // 定义阈值
815+ thresholds := []struct {
816+ percent float64
817+ name string
818+ icon string
819+ }{
820+ {50.0 , "50%流量使用提醒" , "📊" },
821+ {90.0 , "90%流量高使用率告警" , "⚠️" },
822+ {100.0 , "流量超限告警" , "🚨" },
823+ }
824+
825+ // 检查每个阈值(从高到低)
826+ for i := len (thresholds ) - 1 ; i >= 0 ; i -- {
827+ threshold := thresholds [i ]
828+ if usagePercent >= threshold .percent {
829+ // 生成阈值通知的静音标签,避免重复发送
830+ muteLabel := fmt .Sprintf ("traffic-threshold-%d-%d-%.0f" , alert .ID , server .ID , threshold .percent )
831+
832+ // 检查是否已经发送过此阈值的通知
833+ if _ , exists := Cache .Get (muteLabel ); exists {
834+ return // 已经发送过,跳过
835+ }
836+
837+ // 生成通知消息
838+ message := generateThresholdAlertMessage (alert , server , rule , currentUsage , threshold .percent , threshold .name , threshold .icon )
839+
840+ // 发送通知
841+ SafeSendNotification (alert .NotificationTag , message , & muteLabel , server )
842+
843+ // 设置静音缓存,避免短时间内重复发送(1小时)
844+ Cache .Set (muteLabel , true , time .Hour )
845+
846+ // 只发送最高达到的阈值通知
847+ return
848+ }
849+ }
850+ }
851+
852+ // generateThresholdAlertMessage 生成阈值告警消息
853+ func generateThresholdAlertMessage (alert * model.AlertRule , server * model.Server , rule * model.Rule , currentUsage uint64 , thresholdPercent float64 , thresholdName , icon string ) string {
854+ now := time .Now ()
855+
856+ // 获取流量统计信息
857+ stats := AlertsCycleTransferStatsStore [alert .ID ]
858+
859+ // 确定流量类型
860+ trafficType := "流量"
861+ switch rule .Type {
862+ case "transfer_in_cycle" :
863+ trafficType = "入站流量"
864+ case "transfer_out_cycle" :
865+ trafficType = "出站流量"
866+ case "transfer_all_cycle" :
867+ trafficType = "总流量"
868+ }
869+
870+ message := fmt .Sprintf ("%s %s\n " , icon , thresholdName )
871+ message += fmt .Sprintf ("时间: %s\n " , now .Format ("2006-01-02 15:04:05" ))
872+ message += fmt .Sprintf ("服务器: %s\n " , server .Name )
873+ message += fmt .Sprintf ("报警规则: %s\n \n " , alert .Name )
874+
875+ usagePercent := float64 (currentUsage ) / rule .Max * 100
876+ message += fmt .Sprintf ("• %s使用情况:\n " , trafficType )
877+ message += fmt .Sprintf (" - 当前使用: %s (%.2f%%)\n " , formatBytes (currentUsage ), usagePercent )
878+ message += fmt .Sprintf (" - 额定流量: %s\n " , formatBytes (uint64 (rule .Max )))
879+
880+ if currentUsage < uint64 (rule .Max ) {
881+ remainingBytes := uint64 (rule .Max ) - currentUsage
882+ message += fmt .Sprintf (" - 剩余流量: %s\n " , formatBytes (remainingBytes ))
883+ } else {
884+ overageAmount := currentUsage - uint64 (rule .Max )
885+ message += fmt .Sprintf (" - 超额流量: %s\n " , formatBytes (overageAmount ))
886+ }
887+
888+ if stats != nil {
889+ message += fmt .Sprintf (" - 统计周期: %s - %s\n " ,
890+ stats .From .Format ("2006-01-02 15:04:05" ),
891+ stats .To .Format ("2006-01-02 15:04:05" ))
892+ }
893+
894+ return message
895+ }
0 commit comments