diff --git a/internal/db/models/server_daily_stat_dao.go b/internal/db/models/server_daily_stat_dao.go index 8c7ddf52..f11739d6 100644 --- a/internal/db/models/server_daily_stat_dao.go +++ b/internal/db/models/server_daily_stat_dao.go @@ -309,6 +309,40 @@ func (this *ServerDailyStatDAO) SumDailyStat(tx *dbs.Tx, serverId int64, day str return } +// SumDailyStatBeforeMinute 获取某天内某个时间之前的流量 +// 用于同期流量对比 +// day 格式为YYYYMMDD +// minute 格式为HHIISS +func (this *ServerDailyStatDAO) SumDailyStatBeforeMinute(tx *dbs.Tx, serverId int64, day string, minute string) (stat *pb.ServerDailyStat, err error) { + stat = &pb.ServerDailyStat{} + + if !regexp.MustCompile(`^\d{8}$`).MatchString(day) { + return nil, errors.New("invalid day '" + day + "'") + } + + one, _, err := this.Query(tx). + Result("SUM(bytes) AS bytes, SUM(cachedBytes) AS cachedBytes, SUM(countRequests) AS countRequests, SUM(countCachedRequests) AS countCachedRequests, SUM(countAttackRequests) AS countAttackRequests, SUM(attackBytes) AS attackBytes"). + Attr("serverId", serverId). + Attr("day", day). + Lte("minute", minute). + FindOne() + if err != nil { + return nil, err + } + + if one == nil { + return + } + + stat.Bytes = one.GetInt64("bytes") + stat.CachedBytes = one.GetInt64("cachedBytes") + stat.CountRequests = one.GetInt64("countRequests") + stat.CountCachedRequests = one.GetInt64("countCachedRequests") + stat.CountAttackRequests = one.GetInt64("countAttackRequests") + stat.AttackBytes = one.GetInt64("attackBytes") + return +} + // SumMonthlyStat 获取某月内的流量 // month 格式为YYYYMM func (this *ServerDailyStatDAO) SumMonthlyStat(tx *dbs.Tx, serverId int64, month string) (stat *pb.ServerDailyStat, err error) { diff --git a/internal/db/models/stats/traffic_hourly_stat_dao.go b/internal/db/models/stats/traffic_hourly_stat_dao.go index ffe1ceae..34e11306 100644 --- a/internal/db/models/stats/traffic_hourly_stat_dao.go +++ b/internal/db/models/stats/traffic_hourly_stat_dao.go @@ -112,6 +112,31 @@ func (this *TrafficHourlyStatDAO) FindHourlyStats(tx *dbs.Tx, hourFrom string, h return result, nil } +// FindHourlyStat 查FindHourlyStat 找单个小时的统计 +func (this *TrafficHourlyStatDAO) FindHourlyStat(tx *dbs.Tx, hour string) (*TrafficHourlyStat, error) { + one, err := this.Query(tx). + Attr("hour", hour). + Find() + if err != nil || one == nil { + return nil, err + } + + return one.(*TrafficHourlyStat), err +} + +// SumHourlyStats 计算多个小时的统计总和 +func (this *TrafficHourlyStatDAO) SumHourlyStats(tx *dbs.Tx, hourFrom string, hourTo string) (*TrafficHourlyStat, error) { + one, err := this.Query(tx). + Result("SUM(bytes) AS bytes", "SUM(cachedBytes) AS cachedBytes", "SUM(countRequests) AS countRequests", "SUM(countCachedRequests) AS countCachedRequests", "SUM(countAttackRequests) AS countAttackRequests", "SUM(attackBytes) AS attackBytes"). + Between("hour", hourFrom, hourTo). + Find() + if err != nil || one == nil { + return nil, err + } + + return one.(*TrafficHourlyStat), nil +} + // Clean 清理历史数据 func (this *TrafficHourlyStatDAO) Clean(tx *dbs.Tx, days int) error { var hour = timeutil.Format("Ymd00", time.Now().AddDate(0, 0, -days)) diff --git a/internal/rpc/services/service_traffic_daily_stat.go b/internal/rpc/services/service_traffic_daily_stat.go index 7bb6869f..d366bbfa 100644 --- a/internal/rpc/services/service_traffic_daily_stat.go +++ b/internal/rpc/services/service_traffic_daily_stat.go @@ -4,9 +4,11 @@ package services import ( "context" + "fmt" "github.com/TeaOSLab/EdgeAPI/internal/db/models/stats" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" - timeutil "github.com/iwind/TeaGo/utils/time" + "github.com/iwind/TeaGo/types" + "regexp" ) // TrafficDailyStatService 按日统计服务 @@ -22,10 +24,56 @@ func (this *TrafficDailyStatService) FindTrafficDailyStatWithDay(ctx context.Con } var tx = this.NullTx() - var day = timeutil.Format("Ymd") - stat, err := stats.SharedTrafficDailyStatDAO.FindDailyStat(tx, day) - if err != nil { - return nil, err + var day = req.Day + var stat = &stats.TrafficDailyStat{ + Day: day, + } + if len(req.Minute) > 0 && regexp.MustCompile(`^\d{6}$`).MatchString(req.Minute) { + var hourString = req.Minute[:2] + var hourInt = types.Int(hourString) + var lastHourInt = hourInt - 1 + + // 过往小时 + if lastHourInt >= 0 { + var hourFrom = day + "00" + var hourTo = day + fmt.Sprintf("%02d", lastHourInt) + sumStat, err := stats.SharedTrafficHourlyStatDAO.SumHourlyStats(tx, hourFrom, hourTo) + if err != nil { + return nil, err + } + if sumStat != nil { + stat = &stats.TrafficDailyStat{ + Id: 0, + Day: day, + CachedBytes: sumStat.CachedBytes, + Bytes: sumStat.Bytes, + CountRequests: sumStat.CountRequests, + CountCachedRequests: sumStat.CountCachedRequests, + CountAttackRequests: sumStat.CountAttackRequests, + AttackBytes: sumStat.AttackBytes, + } + } + } + + // 当前小时 + hourStat, err := stats.SharedTrafficHourlyStatDAO.FindHourlyStat(tx, day+hourString) + if err != nil { + return nil, err + } + if hourStat != nil { + var seconds = types.Int(req.Minute[2:4])*60 + types.Int(req.Minute[4:]) + 1 /** 因为是0-59,所以+1 **/ + stat.Bytes += hourStat.Bytes * uint64(seconds) / 3600 + stat.CachedBytes += hourStat.CachedBytes * uint64(seconds) / 3600 + stat.CountRequests += hourStat.CountRequests * uint64(seconds) / 3600 + stat.CountCachedRequests += hourStat.CountCachedRequests * uint64(seconds) / 3600 + stat.CountAttackRequests += hourStat.CountAttackRequests * uint64(seconds) / 3600 + stat.AttackBytes += hourStat.AttackBytes * uint64(seconds) / 3600 + } + } else { + stat, err = stats.SharedTrafficDailyStatDAO.FindDailyStat(tx, day) + if err != nil { + return nil, err + } } if stat == nil {