@@ -18,6 +18,7 @@ import (
1818 "github.com/hashicorp/go-uuid"
1919 "github.com/nicksnyder/go-i18n/v2/i18n"
2020
21+ "github.com/jinzhu/copier"
2122 "github.com/xos/serverstatus/model"
2223 "github.com/xos/serverstatus/pkg/mygin"
2324 "github.com/xos/serverstatus/pkg/utils"
@@ -367,41 +368,120 @@ func natGateway(c *gin.Context) {
367368}
368369
369370// buildTrafficData 构建用于前端显示的流量数据
371+ // 返回的数据符合周期配置的cycle_start和cycle_unit
370372func buildTrafficData () []map [string ]interface {} {
371- trafficData := make ([]map [string ]interface {}, 0 )
372-
373- singleton .ServerLock .RLock ()
374- defer singleton .ServerLock .RUnlock ()
375-
376- // 遍历所有服务器,生成流量数据
377- for _ , server := range singleton .ServerList {
378- // 跳过没有状态数据的服务器
379- if server .State == nil {
380- continue
381- }
373+ singleton .AlertsLock .RLock ()
374+ defer singleton .AlertsLock .RUnlock ()
375+
376+ // 创建一个AlertsCycleTransferStatsStore的副本
377+ var statsStore map [uint64 ]model.CycleTransferStats
378+ copier .Copy (& statsStore , singleton .AlertsCycleTransferStatsStore )
379+
380+ // 从statsStore构建流量数据
381+ var trafficData []map [string ]interface {}
382+
383+ if statsStore != nil {
384+ for cycleID , stats := range statsStore {
385+ // 查找对应的Alert规则,用于获取周期设置
386+ var alert * model.AlertRule
387+ for _ , a := range singleton .Alerts {
388+ if a .ID == cycleID {
389+ alert = a
390+ break
391+ }
392+ }
382393
383- // 计算已使用流量和总流量
384- traffic := map [string ]interface {}{
385- "server_id" : server .ID ,
386- "server_name" : server .Name ,
387- "cycle_name" : "Monthly" , // 默认周期名称
394+ // 如果找不到Alert规则,跳过此项
395+ if alert == nil {
396+ continue
397+ }
388398
389- // 使用字节数据作为源
390- "is_bytes_source" : true ,
391- "used_bytes" : server .State .NetInTransfer + server .State .NetOutTransfer ,
392- "max_bytes" : uint64 (1099511627776 ), // 默认1TB限额,可根据实际情况调整
399+ // 找到与流量相关的Rule
400+ var flowRule * model.Rule
401+ for i := range alert .Rules {
402+ if alert .Rules [i ].IsTransferDurationRule () {
403+ flowRule = & alert .Rules [i ]
404+ break
405+ }
406+ }
393407
394- // 提供格式化的流量字符串,兼容旧版本
395- "used_formatted" : formatBytes ( server . State . NetInTransfer + server . State . NetOutTransfer ),
396- "max_formatted" : "1TB" ,
397- }
408+ // 如果没有流量相关规则,跳过
409+ if flowRule == nil {
410+ continue
411+ }
398412
399- // 计算使用百分比
400- if traffic ["max_bytes" ].(uint64 ) > 0 {
401- traffic ["used_percent" ] = float64 (traffic ["used_bytes" ].(uint64 )) / float64 (traffic ["max_bytes" ].(uint64 )) * 100
413+ // 确保周期开始和结束时间正确设置
414+ from := flowRule .GetTransferDurationStart ()
415+ to := flowRule .GetTransferDurationEnd ()
416+
417+ // 更新stats中的周期时间,确保与规则一致
418+ stats .From = from
419+ stats .To = to
420+ stats .Max = uint64 (flowRule .Max )
421+ stats .Name = alert .Name
422+
423+ // 更新主存储(需要写锁)
424+ go func (id uint64 , start , end time.Time , max uint64 , name string ) {
425+ singleton .AlertsLock .Lock ()
426+ defer singleton .AlertsLock .Unlock ()
427+ if store , ok := singleton .AlertsCycleTransferStatsStore [id ]; ok {
428+ store .From = start
429+ store .To = end
430+ store .Max = max
431+ store .Name = name
432+ }
433+ }(cycleID , from , to , uint64 (flowRule .Max ), alert .Name )
434+
435+ // 生成流量数据条目
436+ for serverID , transfer := range stats .Transfer {
437+ serverName := ""
438+ if stats .ServerName != nil {
439+ if name , exists := stats .ServerName [serverID ]; exists {
440+ serverName = name
441+ }
442+ }
443+
444+ // 如果没有名称,尝试从ServerList获取
445+ if serverName == "" {
446+ singleton .ServerLock .RLock ()
447+ if server := singleton .ServerList [serverID ]; server != nil {
448+ serverName = server .Name
449+ }
450+ singleton .ServerLock .RUnlock ()
451+ }
452+
453+ // 计算使用百分比
454+ usedPercent := float64 (0 )
455+ if stats .Max > 0 {
456+ usedPercent = (float64 (transfer ) / float64 (stats .Max )) * 100
457+ usedPercent = math .Max (0 , math .Min (100 , usedPercent )) // 限制在0-100范围
458+ }
459+
460+ // 获取周期单位和开始时间,用于前端展示
461+ cycleUnit := flowRule .CycleUnit
462+
463+ // 构建完整的流量数据项,包含周期信息
464+ trafficItem := map [string ]interface {}{
465+ "server_id" : serverID ,
466+ "server_name" : serverName ,
467+ "max_bytes" : stats .Max ,
468+ "used_bytes" : transfer ,
469+ "max_formatted" : formatBytes (stats .Max ),
470+ "used_formatted" : formatBytes (transfer ),
471+ "used_percent" : math .Round (usedPercent * 100 ) / 100 ,
472+ "cycle_name" : stats .Name ,
473+ "cycle_id" : strconv .FormatUint (cycleID , 10 ),
474+ "cycle_start" : stats .From .Format (time .RFC3339 ),
475+ "cycle_end" : stats .To .Format (time .RFC3339 ),
476+ "cycle_unit" : cycleUnit ,
477+ "cycle_interval" : flowRule .CycleInterval ,
478+ "is_bytes_source" : true ,
479+ "now" : time .Now ().Unix () * 1000 ,
480+ }
481+
482+ trafficData = append (trafficData , trafficItem )
483+ }
402484 }
403-
404- trafficData = append (trafficData , traffic )
405485 }
406486
407487 return trafficData
0 commit comments