2020-12-11 17:28:20 +08:00
package models
import (
2022-10-03 19:28:03 +08:00
"fmt"
2021-10-21 17:10:53 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/errors"
2021-12-14 10:49:29 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/goman"
2021-07-07 19:55:37 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/utils"
2022-10-14 10:03:29 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
2020-12-11 17:28:20 +08:00
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
2021-07-05 11:37:22 +08:00
"github.com/iwind/TeaGo/logs"
2020-12-11 17:28:20 +08:00
"github.com/iwind/TeaGo/maps"
2021-07-19 21:01:26 +08:00
"github.com/iwind/TeaGo/rands"
2022-10-03 19:28:03 +08:00
"github.com/iwind/TeaGo/types"
2020-12-11 17:28:20 +08:00
timeutil "github.com/iwind/TeaGo/utils/time"
2021-06-08 11:18:27 +08:00
"regexp"
2022-01-23 19:16:52 +08:00
"strings"
2021-07-05 11:37:22 +08:00
"time"
2020-12-11 17:28:20 +08:00
)
type ServerDailyStatDAO dbs . DAO
2021-07-05 11:37:22 +08:00
func init ( ) {
dbs . OnReadyDone ( func ( ) {
// 清理数据任务
2021-07-19 21:01:26 +08:00
var ticker = time . NewTicker ( time . Duration ( rands . Int ( 24 , 48 ) ) * time . Hour )
2021-12-14 10:49:29 +08:00
goman . New ( func ( ) {
2021-07-05 11:37:22 +08:00
for range ticker . C {
2022-01-23 19:16:52 +08:00
err := SharedServerDailyStatDAO . Clean ( nil , 60 ) // 只保留 N 天,时间需要长一些,因为需要用来生成账单
2021-07-05 11:37:22 +08:00
if err != nil {
logs . Println ( "ServerDailyStatDAO" , "clean expired data failed: " + err . Error ( ) )
}
}
2021-12-14 10:49:29 +08:00
} )
2021-07-05 11:37:22 +08:00
} )
}
2020-12-11 17:28:20 +08:00
func NewServerDailyStatDAO ( ) * ServerDailyStatDAO {
return dbs . NewDAO ( & ServerDailyStatDAO {
DAOObject : dbs . DAOObject {
DB : Tea . Env ,
Table : "edgeServerDailyStats" ,
Model : new ( ServerDailyStat ) ,
PkName : "id" ,
} ,
} ) . ( * ServerDailyStatDAO )
}
var SharedServerDailyStatDAO * ServerDailyStatDAO
func init ( ) {
dbs . OnReady ( func ( ) {
SharedServerDailyStatDAO = NewServerDailyStatDAO ( )
} )
}
2021-06-08 11:18:27 +08:00
// SaveStats 提交数据
2021-01-01 23:31:30 +08:00
func ( this * ServerDailyStatDAO ) SaveStats ( tx * dbs . Tx , stats [ ] * pb . ServerDailyStat ) error {
2021-07-11 18:05:57 +08:00
var serverUserMap = map [ int64 ] int64 { } // serverId => userId
2021-11-11 14:16:42 +08:00
var cacheMap = utils . NewCacheMap ( )
2020-12-11 17:28:20 +08:00
for _ , stat := range stats {
2023-03-22 19:33:25 +08:00
var day = timeutil . FormatTime ( "Ymd" , stat . CreatedAt )
var hour = timeutil . FormatTime ( "YmdH" , stat . CreatedAt )
var timeFrom = timeutil . FormatTime ( "His" , stat . CreatedAt )
var timeTo = timeutil . FormatTime ( "His" , stat . CreatedAt + 5 * 60 - 1 ) // 5分钟
2020-12-11 17:28:20 +08:00
2023-03-22 19:33:25 +08:00
// 用户ID
var serverUserId = stat . UserId
if serverUserId == 0 {
var ok bool
serverUserId , ok = serverUserMap [ stat . ServerId ]
if ! ok {
userId , err := SharedServerDAO . FindServerUserId ( tx , stat . ServerId )
if err != nil {
return err
}
serverUserMap [ stat . ServerId ] = userId
serverUserId = userId
2021-07-11 18:05:57 +08:00
}
}
2021-01-01 23:31:30 +08:00
_ , _ , err := this . Query ( tx ) .
2020-12-11 17:28:20 +08:00
Param ( "bytes" , stat . Bytes ) .
2021-06-08 11:18:27 +08:00
Param ( "cachedBytes" , stat . CachedBytes ) .
Param ( "countRequests" , stat . CountRequests ) .
Param ( "countCachedRequests" , stat . CountCachedRequests ) .
2021-07-13 11:04:45 +08:00
Param ( "countAttackRequests" , stat . CountAttackRequests ) .
Param ( "attackBytes" , stat . AttackBytes ) .
2020-12-11 17:28:20 +08:00
InsertOrUpdate ( maps . Map {
2021-07-11 18:05:57 +08:00
"userId" : serverUserId ,
2021-06-08 11:18:27 +08:00
"serverId" : stat . ServerId ,
2022-10-14 16:16:42 +08:00
"regionId" : stat . NodeRegionId ,
2021-07-13 11:04:45 +08:00
"bytes" : stat . Bytes ,
"cachedBytes" : stat . CachedBytes ,
"countRequests" : stat . CountRequests ,
"countCachedRequests" : stat . CountCachedRequests ,
"countAttackRequests" : stat . CountAttackRequests ,
"attackBytes" : stat . AttackBytes ,
2021-11-11 08:30:53 +08:00
"planId" : stat . PlanId ,
2021-06-08 11:18:27 +08:00
"day" : day ,
2021-07-05 11:37:22 +08:00
"hour" : hour ,
2021-06-08 11:18:27 +08:00
"timeFrom" : timeFrom ,
"timeTo" : timeTo ,
2020-12-11 17:28:20 +08:00
} , maps . Map {
2021-06-08 11:18:27 +08:00
"bytes" : dbs . SQL ( "bytes+:bytes" ) ,
"cachedBytes" : dbs . SQL ( "cachedBytes+:cachedBytes" ) ,
"countRequests" : dbs . SQL ( "countRequests+:countRequests" ) ,
"countCachedRequests" : dbs . SQL ( "countCachedRequests+:countCachedRequests" ) ,
2021-07-13 11:04:45 +08:00
"countAttackRequests" : dbs . SQL ( "countAttackRequests+:countAttackRequests" ) ,
"attackBytes" : dbs . SQL ( "attackBytes+:attackBytes" ) ,
2021-11-11 08:30:53 +08:00
"planId" : stat . PlanId ,
2020-12-11 17:28:20 +08:00
} )
if err != nil {
return err
}
2021-10-21 17:10:53 +08:00
2021-11-09 17:36:54 +08:00
// 更新流量限制状态
2021-11-10 14:54:27 +08:00
if stat . CheckTrafficLimiting {
trafficLimitConfig , err := SharedServerDAO . CalculateServerTrafficLimitConfig ( tx , stat . ServerId , cacheMap )
2021-10-21 17:10:53 +08:00
if err != nil {
return err
}
2021-11-10 14:54:27 +08:00
if trafficLimitConfig != nil && trafficLimitConfig . IsOn && ! trafficLimitConfig . IsEmpty ( ) {
err = SharedServerDAO . IncreaseServerTotalTraffic ( tx , stat . ServerId , stat . Bytes )
if err != nil {
return err
}
err = SharedServerDAO . UpdateServerTrafficLimitStatus ( tx , trafficLimitConfig , stat . ServerId , false )
if err != nil {
return err
}
}
2021-10-21 17:10:53 +08:00
}
2020-12-11 17:28:20 +08:00
}
2021-10-21 17:10:53 +08:00
2020-12-11 17:28:20 +08:00
return nil
}
2020-12-11 21:39:10 +08:00
2022-04-15 12:14:59 +08:00
// SumCurrentDailyStat 查找当前时刻的数据统计
func ( this * ServerDailyStatDAO ) SumCurrentDailyStat ( tx * dbs . Tx , serverId int64 ) ( * ServerDailyStat , error ) {
var day = timeutil . Format ( "Ymd" )
var minute = timeutil . FormatTime ( "His" , time . Now ( ) . Unix ( ) / 300 * 300 - 300 )
one , err := this . Query ( tx ) .
Result ( "MIN(id)" , "MIN(serverId)" , "SUM(bytes) AS bytes" , "SUM(cachedBytes) AS cachedBytes" , "SUM(attackBytes) AS attackBytes" , "SUM(countRequests) AS countRequests" , "SUM(countCachedRequests) AS countCachedRequests" , "SUM(countAttackRequests) AS countAttackRequests" ) .
Attr ( "serverId" , serverId ) .
Attr ( "day" , day ) .
Attr ( "timeFrom" , minute ) .
Find ( )
if err != nil || one == nil {
return nil , err
}
return one . ( * ServerDailyStat ) , nil
}
2022-01-23 19:16:52 +08:00
// SumServerMonthlyWithRegion 根据服务计算某月合计
2020-12-11 21:39:10 +08:00
// month 格式为YYYYMM
2022-01-23 19:16:52 +08:00
func ( this * ServerDailyStatDAO ) SumServerMonthlyWithRegion ( tx * dbs . Tx , serverId int64 , regionId int64 , month string ) ( int64 , error ) {
2021-01-01 23:31:30 +08:00
query := this . Query ( tx )
2020-12-15 16:53:31 +08:00
if regionId > 0 {
query . Attr ( "regionId" , regionId )
}
return query . Between ( "day" , month + "01" , month + "32" ) .
2022-01-23 19:16:52 +08:00
Attr ( "serverId" , serverId ) .
2020-12-15 16:53:31 +08:00
SumInt64 ( "bytes" , 0 )
}
2021-11-11 08:30:53 +08:00
// SumUserMonthlyWithoutPlan 根据用户计算某月合计并排除套餐
// month 格式为YYYYMM
func ( this * ServerDailyStatDAO ) SumUserMonthlyWithoutPlan ( tx * dbs . Tx , userId int64 , regionId int64 , month string ) ( int64 , error ) {
query := this . Query ( tx )
if regionId > 0 {
query . Attr ( "regionId" , regionId )
}
return query .
Attr ( "planId" , 0 ) .
Between ( "day" , month + "01" , month + "32" ) .
Attr ( "userId" , userId ) .
SumInt64 ( "bytes" , 0 )
}
2021-06-08 11:18:27 +08:00
// SumUserMonthlyPeek 获取某月带宽峰值
2020-12-15 16:53:31 +08:00
// month 格式为YYYYMM
2021-01-01 23:31:30 +08:00
func ( this * ServerDailyStatDAO ) SumUserMonthlyPeek ( tx * dbs . Tx , userId int64 , regionId int64 , month string ) ( int64 , error ) {
query := this . Query ( tx )
2020-12-15 16:53:31 +08:00
if regionId > 0 {
query . Attr ( "regionId" , regionId )
}
max , err := query . Between ( "day" , month + "01" , month + "32" ) .
2021-07-11 18:05:57 +08:00
Attr ( "userId" , userId ) .
2020-12-15 16:53:31 +08:00
Max ( "bytes" , 0 )
if err != nil {
return 0 , err
}
return int64 ( max ) , nil
}
2021-06-08 11:18:27 +08:00
// SumUserDaily 获取某天流量总和
2020-12-15 16:53:31 +08:00
// day 格式为YYYYMMDD
2023-03-22 17:54:44 +08:00
func ( this * ServerDailyStatDAO ) compatSumUserDaily ( tx * dbs . Tx , userId int64 , regionId int64 , day string ) ( stat * ServerDailyStat , err error ) {
2022-10-14 10:03:29 +08:00
var query = this . Query ( tx )
2020-12-15 16:53:31 +08:00
if regionId > 0 {
query . Attr ( "regionId" , regionId )
}
2023-01-08 11:50:47 +08:00
one , err := query . Attr ( "day" , day ) .
2021-07-11 18:05:57 +08:00
Attr ( "userId" , userId ) .
2023-01-08 11:50:47 +08:00
Result ( "SUM(bytes) AS bytes" , "SUM(cachedBytes) AS cachedBytes" , "SUM(attackBytes) AS attackBytes" , "SUM(countRequests) AS countRequests" , "SUM(countCachedRequests) AS countCachedRequests" , "SUM(countAttackRequests) AS countAttackRequests" ) .
Find ( )
if err != nil || one == nil {
return nil , err
}
return one . ( * ServerDailyStat ) , nil
2020-12-11 21:39:10 +08:00
}
2020-12-15 16:53:31 +08:00
2022-10-14 10:03:29 +08:00
// SumUserTrafficBytesBetweenDays 获取用户某个日期段内的流量总和
func ( this * ServerDailyStatDAO ) SumUserTrafficBytesBetweenDays ( tx * dbs . Tx , userId int64 , regionId int64 , dayFrom string , dayTo string ) ( int64 , error ) {
if ! regexputils . YYYYMMDD . MatchString ( dayFrom ) {
return 0 , errors . New ( "invalid 'dayFrom':" + dayFrom )
}
if ! regexputils . YYYYMMDD . MatchString ( dayTo ) {
return 0 , errors . New ( "invalid 'dayTo':" + dayTo )
}
var query = this . Query ( tx )
if regionId > 0 {
query . Attr ( "regionId" , regionId )
} else if regionId < 0 { // 表示没有分配区域的流量
query . Attr ( "regionId" , 0 )
}
return query .
Attr ( "userId" , userId ) .
Between ( "day" , dayFrom , dayTo ) .
SumInt64 ( "bytes" , 0 )
}
2022-01-23 19:16:52 +08:00
// SumUserMonthly 获取某月流量总和
// month 格式为YYYYMM
2023-03-22 17:54:44 +08:00
func ( this * ServerDailyStatDAO ) compatSumUserMonthly ( tx * dbs . Tx , userId int64 , month string ) ( int64 , error ) {
2022-01-23 19:16:52 +08:00
return this . Query ( tx ) .
Between ( "day" , month + "01" , month + "31" ) .
Attr ( "userId" , userId ) .
SumInt64 ( "bytes" , 0 )
}
2021-06-08 11:18:27 +08:00
// SumUserDailyPeek 获取某天带宽峰值
2020-12-15 16:53:31 +08:00
// day 格式为YYYYMMDD
2021-01-01 23:31:30 +08:00
func ( this * ServerDailyStatDAO ) SumUserDailyPeek ( tx * dbs . Tx , userId int64 , regionId int64 , day string ) ( int64 , error ) {
query := this . Query ( tx )
2020-12-15 16:53:31 +08:00
if regionId > 0 {
query . Attr ( "regionId" , regionId )
}
max , err := query .
Attr ( "day" , day ) .
2021-07-11 18:05:57 +08:00
Attr ( "userId" , userId ) .
2020-12-15 16:53:31 +08:00
Max ( "bytes" , 0 )
if err != nil {
return 0 , err
}
return int64 ( max ) , nil
}
2021-06-08 11:18:27 +08:00
2021-06-08 15:10:08 +08:00
// SumMinutelyStat 获取某个分钟内的流量
// minute 格式为YYYYMMDDHHMM, 并且已经格式化成每5分钟一个值
func ( this * ServerDailyStatDAO ) SumMinutelyStat ( tx * dbs . Tx , serverId int64 , minute string ) ( stat * pb . ServerDailyStat , err error ) {
stat = & pb . ServerDailyStat { }
if ! regexp . MustCompile ( ` ^\d { 12}$ ` ) . MatchString ( minute ) {
return
}
one , _ , err := this . Query ( tx ) .
2021-07-13 11:04:45 +08:00
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" ) .
2021-06-08 15:10:08 +08:00
Attr ( "serverId" , serverId ) .
Attr ( "day" , minute [ : 8 ] ) .
Attr ( "timeFrom" , minute [ 8 : ] + "00" ) .
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" )
2021-07-13 11:04:45 +08:00
stat . CountAttackRequests = one . GetInt64 ( "countAttackRequests" )
stat . AttackBytes = one . GetInt64 ( "attackBytes" )
2021-06-08 15:10:08 +08:00
return
}
// SumHourlyStat 获取某个小时内的流量
2021-06-08 11:18:27 +08:00
// hour 格式为YYYYMMDDHH
func ( this * ServerDailyStatDAO ) SumHourlyStat ( tx * dbs . Tx , serverId int64 , hour string ) ( stat * pb . ServerDailyStat , err error ) {
stat = & pb . ServerDailyStat { }
if ! regexp . MustCompile ( ` ^\d { 10}$ ` ) . MatchString ( hour ) {
return
}
one , _ , err := this . Query ( tx ) .
2021-07-13 11:04:45 +08:00
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" ) .
2021-06-08 11:18:27 +08:00
Attr ( "serverId" , serverId ) .
Attr ( "day" , hour [ : 8 ] ) .
Gte ( "timeFrom" , hour [ 8 : ] + "0000" ) .
Lte ( "timeTo" , hour [ 8 : ] + "5959" ) .
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" )
2021-07-13 11:04:45 +08:00
stat . CountAttackRequests = one . GetInt64 ( "countAttackRequests" )
stat . AttackBytes = one . GetInt64 ( "attackBytes" )
2021-06-08 11:18:27 +08:00
return
}
2021-06-08 15:10:08 +08:00
2023-03-22 17:54:44 +08:00
// compatSumDailyStat 获取某天内的流量
2022-10-03 19:28:03 +08:00
// dayFrom 格式为YYYYMMDD
// dayTo 格式为YYYYMMDD
2023-03-22 17:54:44 +08:00
func ( this * ServerDailyStatDAO ) compatSumDailyStat ( tx * dbs . Tx , userId int64 , serverId int64 , regionId int64 , dayFrom string , dayTo string ) ( stat * pb . ServerDailyStat , err error ) {
2021-06-08 15:10:08 +08:00
stat = & pb . ServerDailyStat { }
2022-10-03 19:28:03 +08:00
if userId <= 0 && serverId <= 0 {
return
2021-06-08 15:10:08 +08:00
}
2022-10-14 10:03:29 +08:00
if ! regexputils . YYYYMMDD . MatchString ( dayFrom ) {
2022-10-03 19:28:03 +08:00
return nil , errors . New ( "invalid dayFrom '" + dayFrom + "'" )
}
2022-10-14 10:03:29 +08:00
if ! regexputils . YYYYMMDD . MatchString ( dayTo ) {
2022-10-03 19:28:03 +08:00
return nil , errors . New ( "invalid dayTo '" + dayTo + "'" )
}
if dayFrom > dayTo {
dayFrom , dayTo = dayTo , dayFrom
}
var query = 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" )
if userId > 0 {
query . Attr ( "userId" , userId )
}
if serverId > 0 {
query . Attr ( "serverId" , serverId )
}
2022-10-14 10:03:29 +08:00
if regionId > 0 {
query . Attr ( "regionId" , regionId )
}
2022-10-03 19:28:03 +08:00
if dayFrom == dayTo {
query . Attr ( "day" , dayFrom )
} else {
query . Between ( "day" , dayFrom , dayTo )
}
one , _ , err := query . FindOne ( )
2021-06-08 15:10:08 +08:00
if err != nil {
return nil , err
}
2021-10-21 17:10:53 +08:00
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
}
2022-04-10 21:25:24 +08:00
// 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 { }
2022-10-14 10:03:29 +08:00
if ! regexputils . YYYYMMDD . MatchString ( day ) {
2022-04-10 21:25:24 +08:00
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
}
2021-10-21 17:10:53 +08:00
// SumMonthlyStat 获取某月内的流量
// month 格式为YYYYMM
func ( this * ServerDailyStatDAO ) SumMonthlyStat ( tx * dbs . Tx , serverId int64 , month string ) ( stat * pb . ServerDailyStat , err error ) {
stat = & pb . ServerDailyStat { }
2022-10-14 10:03:29 +08:00
if ! regexputils . YYYYMM . MatchString ( month ) {
2021-10-21 17:10:53 +08:00
return
}
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 ) .
Between ( "day" , month + "01" , month + "31" ) .
FindOne ( )
if err != nil {
return nil , err
}
2021-06-08 15:10:08 +08:00
if one == nil {
return
}
stat . Bytes = one . GetInt64 ( "bytes" )
stat . CachedBytes = one . GetInt64 ( "cachedBytes" )
stat . CountRequests = one . GetInt64 ( "countRequests" )
stat . CountCachedRequests = one . GetInt64 ( "countCachedRequests" )
2021-07-13 11:04:45 +08:00
stat . CountAttackRequests = one . GetInt64 ( "countAttackRequests" )
stat . AttackBytes = one . GetInt64 ( "attackBytes" )
2021-06-08 15:10:08 +08:00
return
}
2021-07-05 11:37:22 +08:00
2022-01-23 19:16:52 +08:00
// SumMonthlyBytes 获取某月内的流量
// month 格式为YYYYMM
func ( this * ServerDailyStatDAO ) SumMonthlyBytes ( tx * dbs . Tx , serverId int64 , month string ) ( result int64 , err error ) {
2022-10-14 10:03:29 +08:00
if ! regexputils . YYYYMM . MatchString ( month ) {
2022-01-23 19:16:52 +08:00
return
}
return this . Query ( tx ) .
Result ( "SUM(bytes) AS bytes" ) .
Attr ( "serverId" , serverId ) .
Between ( "day" , month + "01" , month + "31" ) .
FindInt64Col ( 0 )
}
2021-07-07 19:55:37 +08:00
// FindDailyStats 按天统计
2023-03-22 17:54:44 +08:00
func ( this * ServerDailyStatDAO ) compatFindDailyStats ( tx * dbs . Tx , serverId int64 , dayFrom string , dayTo string ) ( result [ ] * ServerDailyStat , err error ) {
2021-07-07 19:55:37 +08:00
ones , err := this . Query ( tx ) .
2021-07-13 11:04:45 +08:00
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" , "day" ) .
2021-07-07 19:55:37 +08:00
Attr ( "serverId" , serverId ) .
Between ( "day" , dayFrom , dayTo ) .
Group ( "day" ) .
FindAll ( )
if err != nil {
return nil , err
}
dayMap := map [ string ] * ServerDailyStat { } // day => Stat
for _ , one := range ones {
stat := one . ( * ServerDailyStat )
dayMap [ stat . Day ] = stat
}
days , err := utils . RangeDays ( dayFrom , dayTo )
if err != nil {
return nil , err
}
for _ , day := range days {
stat , ok := dayMap [ day ]
if ok {
result = append ( result , stat )
} else {
result = append ( result , & ServerDailyStat { Day : day } )
}
}
return
}
2022-09-24 18:36:27 +08:00
// FindStatsWithDay 按天查找5分钟级统计
// day YYYYMMDD
2022-10-14 10:03:29 +08:00
// timeFrom HHII00
// timeTo HHII59
2022-09-24 18:55:33 +08:00
func ( this * ServerDailyStatDAO ) FindStatsWithDay ( tx * dbs . Tx , serverId int64 , day string , timeFrom string , timeTo string ) ( result [ ] * ServerDailyStat , err error ) {
2022-10-14 10:03:29 +08:00
if ! regexputils . YYYYMMDD . MatchString ( day ) {
2022-09-24 18:36:27 +08:00
return
}
2022-09-24 18:55:33 +08:00
var query = this . Query ( tx ) .
2022-10-14 10:03:29 +08:00
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" , "day" , "timeFrom" , "MIN(timeTo) AS timeTo" ) .
2022-09-24 18:36:27 +08:00
Attr ( "serverId" , serverId ) .
Attr ( "day" , day ) .
2022-10-14 10:03:29 +08:00
Group ( "day" ) . Group ( "timeFrom" , dbs . QueryOrderDesc )
2022-09-24 18:55:33 +08:00
if len ( timeFrom ) > 0 {
query . Gte ( "timeFrom" , timeFrom )
}
if len ( timeTo ) > 0 {
query . Lte ( "timeTo" , timeTo )
}
_ , err = query .
2022-09-24 18:36:27 +08:00
Slice ( & result ) .
FindAll ( )
2022-10-14 10:03:29 +08:00
if err != nil {
return nil , err
}
2022-09-24 18:36:27 +08:00
return
}
2022-10-03 19:28:03 +08:00
// FindStatsBetweenDays 查找日期段内的5分钟统计
2022-10-14 10:03:29 +08:00
func ( this * ServerDailyStatDAO ) FindStatsBetweenDays ( tx * dbs . Tx , userId int64 , serverId int64 , regionId int64 , dayFrom string , dayTo string ) ( result [ ] * ServerDailyStat , err error ) {
if ! regexputils . YYYYMMDD . MatchString ( dayFrom ) || ! regexputils . YYYYMMDD . MatchString ( dayTo ) {
2022-10-03 19:28:03 +08:00
return
}
if userId <= 0 && serverId <= 0 {
return
}
if dayFrom > dayTo {
dayFrom , dayTo = dayTo , dayFrom
}
var query = this . Query ( tx )
if userId > 0 {
query . Attr ( "userId" , userId )
}
if serverId > 0 {
query . Attr ( "serverId" , serverId )
} else {
query . 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" , "MIN(day) AS day" , "MIN(timeFrom) AS timeFrom" , "MIN(timeTo) AS timeTo" )
2022-10-14 10:03:29 +08:00
query . Group ( "day" ) . Group ( "timeFrom" )
}
if regionId > 0 {
query . Attr ( "regionId" , regionId )
} else if regionId < 0 { // 表示未分配区域的流量
query . Attr ( "regionId" , 0 )
2022-10-03 19:28:03 +08:00
}
// 不需要排序
query . Between ( "day" , dayFrom , dayTo )
_ , err = query .
Slice ( & result ) .
FindAll ( )
if err != nil {
return
}
var m = map [ string ] * ServerDailyStat { } // day @ timeFrom => *ServerDailyStat
for _ , stat := range result {
2022-10-14 10:03:29 +08:00
var key = stat . Day + "@" + stat . TimeFrom
mStat , ok := m [ key ]
if ok {
mStat . Bytes += stat . Bytes
mStat . CachedBytes += stat . CachedBytes
mStat . AttackBytes += stat . AttackBytes
mStat . CountRequests += stat . CountRequests
mStat . CountAttackRequests += stat . CountAttackRequests
mStat . CountCachedRequests += stat . CountCachedRequests
} else {
m [ key ] = stat
}
2022-10-03 19:28:03 +08:00
}
// 填充空白
rangeDays , err := utils . RangeDays ( dayFrom , dayTo )
if err != nil {
return nil , err
}
dayTimes , err := utils . Range24HourTimes ( 5 )
if err != nil {
return nil , err
}
// 截止到当前时间
var currentTime = timeutil . Format ( "Ymd@Hi00" )
result = nil
for _ , day := range rangeDays {
for _ , timeAt /** HHII **/ := range dayTimes {
var key = day + "@" + timeAt + "00"
if key >= currentTime {
break
}
stat , ok := m [ key ]
if ok {
result = append ( result , stat )
} else {
var hour = types . Int ( timeAt [ : 2 ] )
var minute = types . Int ( timeAt [ 2 : ] )
minute += 4
result = append ( result , & ServerDailyStat {
Day : day ,
TimeFrom : timeAt + "00" ,
TimeTo : fmt . Sprintf ( "%02d%02d59" , hour , minute ) ,
} )
}
}
}
return
}
2021-11-11 08:30:53 +08:00
// FindMonthlyStatsWithPlan 查找某月有套餐的流量
// month YYYYMM
func ( this * ServerDailyStatDAO ) FindMonthlyStatsWithPlan ( tx * dbs . Tx , month string ) ( result [ ] * ServerDailyStat , err error ) {
_ , err = this . Query ( tx ) .
Between ( "day" , month + "01" , month + "32" ) .
Gt ( "planId" , 0 ) .
Slice ( & result ) .
FindAll ( )
return
}
2021-07-07 19:55:37 +08:00
// FindHourlyStats 按小时统计
2023-03-22 17:54:44 +08:00
func ( this * ServerDailyStatDAO ) compatFindHourlyStats ( tx * dbs . Tx , serverId int64 , hourFrom string , hourTo string ) ( result [ ] * ServerDailyStat , err error ) {
2021-07-07 19:55:37 +08:00
ones , err := this . Query ( tx ) .
2021-07-13 11:04:45 +08:00
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" , "hour" ) .
2021-07-07 19:55:37 +08:00
Attr ( "serverId" , serverId ) .
Between ( "hour" , hourFrom , hourTo ) .
Group ( "hour" ) .
FindAll ( )
if err != nil {
return nil , err
}
hourMap := map [ string ] * ServerDailyStat { } // hour => Stat
for _ , one := range ones {
stat := one . ( * ServerDailyStat )
hourMap [ stat . Hour ] = stat
}
hours , err := utils . RangeHours ( hourFrom , hourTo )
if err != nil {
return nil , err
}
for _ , hour := range hours {
stat , ok := hourMap [ hour ]
if ok {
result = append ( result , stat )
} else {
result = append ( result , & ServerDailyStat { Hour : hour } )
}
}
return
}
2021-07-11 18:05:57 +08:00
// FindTopUserStats 流量排行
func ( this * ServerDailyStatDAO ) FindTopUserStats ( tx * dbs . Tx , hourFrom string , hourTo string ) ( result [ ] * ServerDailyStat , err error ) {
_ , err = this . Query ( tx ) .
2021-07-13 11:04:45 +08:00
Result ( "userId" , "SUM(bytes) AS bytes" , "SUM(countRequests) AS countRequests, SUM(countAttackRequests) AS countAttackRequests, SUM(attackBytes) AS attackBytes" ) .
2021-07-11 18:05:57 +08:00
Between ( "hour" , hourFrom , hourTo ) .
Where ( "userId>0" ) .
Group ( "userId" ) .
Slice ( & result ) .
FindAll ( )
return
}
2022-01-23 19:16:52 +08:00
// FindDistinctServerIds 查找所有有流量的服务ID列表
// dayFrom YYYYMMDD
// dayTo YYYYMMDD
func ( this * ServerDailyStatDAO ) FindDistinctServerIds ( tx * dbs . Tx , dayFrom string , dayTo string ) ( serverIds [ ] int64 , err error ) {
dayFrom = strings . ReplaceAll ( dayFrom , "-" , "" )
dayTo = strings . ReplaceAll ( dayTo , "-" , "" )
ones , _ , err := this . Query ( tx ) .
Result ( "DISTINCT(serverId) AS serverId" ) .
Between ( "day" , dayFrom , dayTo ) .
FindOnes ( )
if err != nil {
return nil , err
}
for _ , one := range ones {
serverIds = append ( serverIds , one . GetInt64 ( "serverId" ) )
}
return serverIds , nil
}
2022-10-14 10:03:29 +08:00
// FindDistinctUserIds 查找所有有流量的用户ID
func ( this * ServerDailyStatDAO ) FindDistinctUserIds ( tx * dbs . Tx , dayFrom string , dayTo string ) ( userIds [ ] int64 , err error ) {
dayFrom = strings . ReplaceAll ( dayFrom , "-" , "" )
dayTo = strings . ReplaceAll ( dayTo , "-" , "" )
ones , _ , err := this . Query ( tx ) .
Result ( "DISTINCT(userId) AS userId" ) .
Between ( "day" , dayFrom , dayTo ) .
FindOnes ( )
if err != nil {
return nil , err
}
for _ , one := range ones {
2022-11-15 16:34:33 +08:00
var userId = one . GetInt64 ( "userId" )
if userId > 0 {
userIds = append ( userIds , userId )
}
2022-10-14 10:03:29 +08:00
}
return userIds , nil
}
2021-11-11 08:30:53 +08:00
// UpdateStatFee 设置费用
func ( this * ServerDailyStatDAO ) UpdateStatFee ( tx * dbs . Tx , statId int64 , fee float32 ) error {
return this . Query ( tx ) .
Pk ( statId ) .
Set ( "fee" , fee ) .
UpdateQuickly ( )
}
2021-07-05 11:37:22 +08:00
// Clean 清理历史数据
func ( this * ServerDailyStatDAO ) Clean ( tx * dbs . Tx , days int ) error {
var day = timeutil . Format ( "Ymd" , time . Now ( ) . AddDate ( 0 , 0 , - days ) )
_ , err := this . Query ( tx ) .
Lt ( "day" , day ) .
Delete ( )
return err
}