Skip to content

Commit 82a1305

Browse files
committed
Update.
1 parent 7dfc140 commit 82a1305

File tree

5 files changed

+175
-34
lines changed

5 files changed

+175
-34
lines changed

cmd/dashboard/controller/common_page.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,8 @@ func (cp *commonPage) network(c *gin.Context) {
240240
if id == 0 || server.IsOnline {
241241
id = serverID
242242
}
243-
} else if singleton.Conf.Debug {
244-
log.Printf("network: 服务器 %d (%s) 被监控 %d 跳过 (Cover=%d)", serverID, server.Name, monitor.ID, monitor.Cover)
245243
}
244+
// 移除频繁的"服务器被监控跳过"日志输出
246245
}
247246
}
248247
singleton.ServerLock.RUnlock()
@@ -376,7 +375,7 @@ func (cp *commonPage) network(c *gin.Context) {
376375
}
377376
}
378377
monitorHistories = filteredHistories
379-
log.Printf("network: BadgerDB为服务器 %d 找到 %d 条监控历史记录", id, len(filteredHistories))
378+
// 移除频繁的监控历史记录查询日志
380379
}
381380
} else {
382381
log.Printf("network: BadgerDB未初始化或无效服务器ID,使用空数组")

resource/l10n/zh-CN.toml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,3 +837,42 @@ other = "自定义DDNS使用的公共DNS服务器(逗号分隔)"
837837

838838
[Plan]
839839
other = "套餐"
840+
841+
[TrafficAlert]
842+
other = "流量告警"
843+
844+
[SetupTrafficAlert]
845+
other = "设置流量告警"
846+
847+
[MonthlyTrafficLimit]
848+
other = "月流量限制"
849+
850+
[NotificationGroup]
851+
other = "通知组"
852+
853+
[AlertThresholds]
854+
other = "告警阈值"
855+
856+
[Alert50Percent]
857+
other = "50% 流量告警"
858+
859+
[Alert90Percent]
860+
other = "90% 流量告警"
861+
862+
[Alert100Percent]
863+
other = "100% 流量告警"
864+
865+
[CreateAlert]
866+
other = "创建告警"
867+
868+
[TrafficAlertInfo]
869+
other = "流量告警说明"
870+
871+
[TrafficAlertInfo1]
872+
other = "流量统计周期为自然月(每月1号重置)"
873+
874+
[TrafficAlertInfo2]
875+
other = "可同时启用多个阈值告警"
876+
877+
[TrafficAlertInfo3]
878+
other = "告警将发送到指定的通知组"

resource/static/main.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ function addOrEditNAT(nat) {
427427
);
428428
}
429429

430+
431+
430432
function connectToServer(id) {
431433
post('/terminal', { Host: window.location.host, Protocol: window.location.protocol, ID: id })
432434
}

service/rpc/server.go

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,7 @@ func (s *ServerHandler) RequestTask(h *pb.Host, stream pb.ServerService_RequestT
207207
if ctxErr := ctx.Err(); ctxErr != nil {
208208
// 检查是否为网络连接错误或超时错误
209209
if isConnectionError(ctxErr) || ctxErr == context.DeadlineExceeded || ctxErr == context.Canceled {
210-
// 静默处理网络连接错误、正常超时和取消,避免日志干扰
211-
if singleton.Conf.Debug {
212-
log.Printf("RequestTask连接正常断开: 客户端ID %d, 原因: %v", clientID, ctxErr)
213-
}
210+
// 静默处理网络连接错误、正常超时和取消,移除频繁的连接断开日志
214211
} else {
215212
log.Printf("RequestTask连接上下文错误: %v", ctxErr)
216213
}
@@ -282,30 +279,22 @@ func (s *ServerHandler) RequestTask(h *pb.Host, stream pb.ServerService_RequestT
282279
case err := <-closeCh:
283280
// 检查是否为网络连接错误
284281
if isConnectionError(err) {
285-
if singleton.Conf.Debug {
286-
log.Printf("客户端 %d 网络连接中断: %v", clientID, err)
287-
}
282+
// 移除频繁的网络连接中断日志
288283
return nil // 将网络连接错误视为正常断开
289284
}
290285
return err
291286
case <-ctx.Done():
292287
// 超时或连接取消,增强错误分类
293288
if ctx.Err() == context.DeadlineExceeded {
294-
if singleton.Conf.Debug {
295-
log.Printf("客户端 %d RequestTask连接超时 (5分钟)", clientID)
296-
}
289+
// 移除频繁的连接超时日志
297290
return nil // 将超时视为正常断开,不返回错误
298291
}
299292
// 检查是否为网络连接错误或取消
300293
if isConnectionError(ctx.Err()) || ctx.Err() == context.Canceled {
301-
if singleton.Conf.Debug {
302-
log.Printf("客户端 %d 连接正常断开: %v", clientID, ctx.Err())
303-
}
294+
// 移除频繁的连接正常断开日志
304295
return nil // 将网络连接错误和取消视为正常断开
305296
}
306-
if singleton.Conf.Debug {
307-
log.Printf("客户端 %d RequestTask异常断开: %v", clientID, ctx.Err())
308-
}
297+
// 移除频繁的RequestTask异常断开日志
309298
return nil // 即使异常也不返回错误,避免程序重启
310299
case <-ticker.C:
311300
// 定期检查连接状态和服务器存在性
@@ -318,10 +307,7 @@ func (s *ServerHandler) RequestTask(h *pb.Host, stream pb.ServerService_RequestT
318307
serverExists := singleton.ServerList[clientID] != nil
319308
singleton.ServerLock.RUnlock()
320309
if !serverExists {
321-
// 服务器已被删除,正常退出
322-
if singleton.Conf.Debug {
323-
log.Printf("客户端 %d 服务器已删除,RequestTask正常退出", clientID)
324-
}
310+
// 服务器已被删除,正常退出,移除频繁的退出日志
325311
return nil
326312
}
327313
}

service/singleton/alertsentinel.go

Lines changed: 126 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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 生成流量报警的详细信息,支持多级阈值通知
539544
func 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

Comments
 (0)