2021-01-21 20:22:58 +08:00
package stats
2021-01-21 18:55:34 +08:00
import (
"github.com/TeaOSLab/EdgeAPI/internal/errors"
2021-12-14 10:49:29 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/goman"
2021-07-05 11:37:22 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
2021-01-21 18:55:34 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/utils"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
2021-07-19 21:01:26 +08:00
"github.com/iwind/TeaGo/rands"
2021-07-05 11:37:22 +08:00
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
2021-01-21 18:55:34 +08:00
)
type TrafficHourlyStatDAO 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 {
2021-12-05 19:53:37 +08:00
err := SharedTrafficHourlyStatDAO . Clean ( nil , 15 ) // 只保留N天
2021-07-05 11:37:22 +08:00
if err != nil {
remotelogs . Error ( "TrafficHourlyStatDAO" , "clean expired data failed: " + err . Error ( ) )
}
}
2021-12-14 10:49:29 +08:00
} )
2021-07-05 11:37:22 +08:00
} )
}
2021-01-21 18:55:34 +08:00
func NewTrafficHourlyStatDAO ( ) * TrafficHourlyStatDAO {
return dbs . NewDAO ( & TrafficHourlyStatDAO {
DAOObject : dbs . DAOObject {
DB : Tea . Env ,
Table : "edgeTrafficHourlyStats" ,
Model : new ( TrafficHourlyStat ) ,
PkName : "id" ,
} ,
} ) . ( * TrafficHourlyStatDAO )
}
var SharedTrafficHourlyStatDAO * TrafficHourlyStatDAO
func init ( ) {
dbs . OnReady ( func ( ) {
SharedTrafficHourlyStatDAO = NewTrafficHourlyStatDAO ( )
} )
}
2021-07-05 11:37:22 +08:00
// IncreaseHourlyStat 增加流量
2021-07-13 11:04:45 +08:00
func ( this * TrafficHourlyStatDAO ) IncreaseHourlyStat ( tx * dbs . Tx , hour string , bytes int64 , cachedBytes int64 , countRequests int64 , countCachedRequests int64 , countAttackRequests int64 , attackBytes int64 ) error {
2021-01-21 18:55:34 +08:00
if len ( hour ) != 10 {
return errors . New ( "invalid hour '" + hour + "'" )
}
err := this . Query ( tx ) .
Param ( "bytes" , bytes ) .
2021-07-05 11:37:22 +08:00
Param ( "cachedBytes" , cachedBytes ) .
Param ( "countRequests" , countRequests ) .
Param ( "countCachedRequests" , countCachedRequests ) .
2021-07-13 11:04:45 +08:00
Param ( "countAttackRequests" , countAttackRequests ) .
Param ( "attackBytes" , attackBytes ) .
2021-01-21 18:55:34 +08:00
InsertOrUpdateQuickly ( maps . Map {
2021-07-05 11:37:22 +08:00
"hour" : hour ,
"bytes" : bytes ,
"cachedBytes" : cachedBytes ,
"countRequests" : countRequests ,
"countCachedRequests" : countCachedRequests ,
2021-07-13 11:04:45 +08:00
"countAttackRequests" : countAttackRequests ,
"attackBytes" : attackBytes ,
2021-01-21 18:55:34 +08:00
} , maps . Map {
2021-07-05 11:37:22 +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-01-21 18:55:34 +08:00
} )
if err != nil {
return err
}
return nil
}
2021-07-05 11:37:22 +08:00
// FindHourlyStats 获取小时之间统计
2021-01-21 18:55:34 +08:00
func ( this * TrafficHourlyStatDAO ) FindHourlyStats ( tx * dbs . Tx , hourFrom string , hourTo string ) ( result [ ] * TrafficHourlyStat , err error ) {
ones , err := this . Query ( tx ) .
Between ( "hour" , hourFrom , hourTo ) .
FindAll ( )
2021-07-05 11:37:22 +08:00
if err != nil {
return nil , err
}
2021-01-21 18:55:34 +08:00
hourMap := map [ string ] * TrafficHourlyStat { } // hour => Stat
for _ , one := range ones {
stat := one . ( * TrafficHourlyStat )
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 , & TrafficHourlyStat { Hour : hour } )
}
}
return result , nil
}
2021-07-05 11:37:22 +08:00
2022-04-10 21:25:24 +08:00
// 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
}
2021-07-05 11:37:22 +08:00
// Clean 清理历史数据
func ( this * TrafficHourlyStatDAO ) Clean ( tx * dbs . Tx , days int ) error {
var hour = timeutil . Format ( "Ymd00" , time . Now ( ) . AddDate ( 0 , 0 , - days ) )
_ , err := this . Query ( tx ) .
Lt ( "hour" , hour ) .
Delete ( )
return err
}