mirror of
https://github.com/TeaOSLab/EdgeAPI.git
synced 2025-11-03 15:00:27 +08:00
国家/地区统计时上传流量、攻击量等信息/多个统计增加自动清理程序
This commit is contained in:
@@ -16,7 +16,8 @@ const (
|
||||
RegionCountryStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
var regionCountryNameAndIdCacheMap = map[string]int64{} // country name => int
|
||||
var regionCountryNameAndIdCacheMap = map[string]int64{} // country name => id
|
||||
var regionCountryIdAndNameCacheMap = map[int64]string{} // country id => name
|
||||
|
||||
type RegionCountryDAO dbs.DAO
|
||||
|
||||
@@ -39,7 +40,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableRegionCountry 启用条目
|
||||
func (this *RegionCountryDAO) EnableRegionCountry(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -48,7 +49,7 @@ func (this *RegionCountryDAO) EnableRegionCountry(tx *dbs.Tx, id uint32) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableRegionCountry 禁用条目
|
||||
func (this *RegionCountryDAO) DisableRegionCountry(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -57,7 +58,7 @@ func (this *RegionCountryDAO) DisableRegionCountry(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledRegionCountry 查找启用中的条目
|
||||
func (this *RegionCountryDAO) FindEnabledRegionCountry(tx *dbs.Tx, id int64) (*RegionCountry, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -69,15 +70,29 @@ func (this *RegionCountryDAO) FindEnabledRegionCountry(tx *dbs.Tx, id int64) (*R
|
||||
return result.(*RegionCountry), err
|
||||
}
|
||||
|
||||
// 根据主键查找名称
|
||||
// FindRegionCountryName 根据主键查找名称
|
||||
func (this *RegionCountryDAO) FindRegionCountryName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
SharedCacheLocker.Lock()
|
||||
defer SharedCacheLocker.Unlock()
|
||||
|
||||
name, ok := regionCountryIdAndNameCacheMap[id]
|
||||
if ok {
|
||||
return name, nil
|
||||
}
|
||||
|
||||
name, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
regionCountryIdAndNameCacheMap[id] = name
|
||||
return name, nil
|
||||
}
|
||||
|
||||
// 根据数据ID查找国家
|
||||
// FindCountryIdWithDataId 根据数据ID查找国家
|
||||
func (this *RegionCountryDAO) FindCountryIdWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("dataId", dataId).
|
||||
@@ -85,7 +100,7 @@ func (this *RegionCountryDAO) FindCountryIdWithDataId(tx *dbs.Tx, dataId string)
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// 根据国家名查找国家ID
|
||||
// FindCountryIdWithName 根据国家名查找国家ID
|
||||
func (this *RegionCountryDAO) FindCountryIdWithName(tx *dbs.Tx, countryName string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Where("JSON_CONTAINS(codes, :countryName)").
|
||||
@@ -94,7 +109,7 @@ func (this *RegionCountryDAO) FindCountryIdWithName(tx *dbs.Tx, countryName stri
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// 根据国家名查找国家ID,并可使用缓存
|
||||
// FindCountryIdWithNameCacheable 根据国家名查找国家ID,并可使用缓存
|
||||
func (this *RegionCountryDAO) FindCountryIdWithNameCacheable(tx *dbs.Tx, countryName string) (int64, error) {
|
||||
SharedCacheLocker.RLock()
|
||||
provinceId, ok := regionCountryNameAndIdCacheMap[countryName]
|
||||
@@ -116,7 +131,7 @@ func (this *RegionCountryDAO) FindCountryIdWithNameCacheable(tx *dbs.Tx, country
|
||||
return countryId, nil
|
||||
}
|
||||
|
||||
// 根据数据ID创建国家
|
||||
// CreateCountry 根据数据ID创建国家
|
||||
func (this *RegionCountryDAO) CreateCountry(tx *dbs.Tx, name string, dataId string) (int64, error) {
|
||||
op := NewRegionCountryOperator()
|
||||
op.Name = name
|
||||
@@ -145,7 +160,7 @@ func (this *RegionCountryDAO) CreateCountry(tx *dbs.Tx, name string, dataId stri
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// 查找所有可用的国家
|
||||
// FindAllEnabledCountriesOrderByPinyin 查找所有可用的国家
|
||||
func (this *RegionCountryDAO) FindAllEnabledCountriesOrderByPinyin(tx *dbs.Tx) (result []*RegionCountry, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(RegionCountryStateEnabled).
|
||||
|
||||
@@ -2,12 +2,31 @@ package stats
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
go func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerClientBrowserMonthlyStatDAO.Clean(nil)
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerClientBrowserMonthlyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
type ServerClientBrowserMonthlyStatDAO dbs.DAO
|
||||
|
||||
func NewServerClientBrowserMonthlyStatDAO() *ServerClientBrowserMonthlyStatDAO {
|
||||
@@ -29,7 +48,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 增加数量
|
||||
// IncreaseMonthlyCount 增加数量
|
||||
func (this *ServerClientBrowserMonthlyStatDAO) IncreaseMonthlyCount(tx *dbs.Tx, serverId int64, browserId int64, version string, month string, count int64) error {
|
||||
if len(month) != 6 {
|
||||
return errors.New("invalid month '" + month + "'")
|
||||
@@ -51,7 +70,7 @@ func (this *ServerClientBrowserMonthlyStatDAO) IncreaseMonthlyCount(tx *dbs.Tx,
|
||||
return nil
|
||||
}
|
||||
|
||||
// 查找单页数据
|
||||
// ListStats 查找单页数据
|
||||
func (this *ServerClientBrowserMonthlyStatDAO) ListStats(tx *dbs.Tx, serverId int64, month string, offset int64, size int64) (result []*ServerClientBrowserMonthlyStat, err error) {
|
||||
query := this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
@@ -63,3 +82,13 @@ func (this *ServerClientBrowserMonthlyStatDAO) ListStats(tx *dbs.Tx, serverId in
|
||||
_, err = query.FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// Clean 清理统计数据
|
||||
func (this *ServerClientBrowserMonthlyStatDAO) Clean(tx *dbs.Tx) error {
|
||||
// 只保留两个月的
|
||||
var month = timeutil.Format("Ym", time.Now().AddDate(0, -2, 0))
|
||||
_, err := this.Query(tx).
|
||||
Lte("month", month).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -17,3 +17,12 @@ func TestServerClientBrowserMonthlyStatDAO_IncreaseMonthlyCount(t *testing.T) {
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestServerClientBrowserMonthlyStatDAO_Clean(t *testing.T) {
|
||||
var dao = NewServerClientBrowserMonthlyStatDAO()
|
||||
err := dao.Clean(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -2,12 +2,31 @@ package stats
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
go func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerClientSystemMonthlyStatDAO.Clean(nil)
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerClientSystemMonthlyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
type ServerClientSystemMonthlyStatDAO dbs.DAO
|
||||
|
||||
func NewServerClientSystemMonthlyStatDAO() *ServerClientSystemMonthlyStatDAO {
|
||||
@@ -29,7 +48,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 增加数量
|
||||
// IncreaseMonthlyCount 增加数量
|
||||
func (this *ServerClientSystemMonthlyStatDAO) IncreaseMonthlyCount(tx *dbs.Tx, serverId int64, systemId int64, version string, month string, count int64) error {
|
||||
if len(month) != 6 {
|
||||
return errors.New("invalid month '" + month + "'")
|
||||
@@ -51,7 +70,7 @@ func (this *ServerClientSystemMonthlyStatDAO) IncreaseMonthlyCount(tx *dbs.Tx, s
|
||||
return nil
|
||||
}
|
||||
|
||||
// 查找单页数据
|
||||
// ListStats 查找单页数据
|
||||
func (this *ServerClientSystemMonthlyStatDAO) ListStats(tx *dbs.Tx, serverId int64, month string, offset int64, size int64) (result []*ServerClientSystemMonthlyStat, err error) {
|
||||
query := this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
@@ -63,3 +82,13 @@ func (this *ServerClientSystemMonthlyStatDAO) ListStats(tx *dbs.Tx, serverId int
|
||||
_, err = query.FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// Clean 清理统计数据
|
||||
func (this *ServerClientSystemMonthlyStatDAO) Clean(tx *dbs.Tx) error {
|
||||
// 只保留两个月的
|
||||
var month = timeutil.Format("Ym", time.Now().AddDate(0, -2, 0))
|
||||
_, err := this.Query(tx).
|
||||
Lte("month", month).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,4 +2,14 @@ package stats
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestServerClientSystemMonthlyStatDAO_Clean(t *testing.T) {
|
||||
var dao = NewServerClientSystemMonthlyStatDAO()
|
||||
err := dao.Clean(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
go func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerHTTPFirewallDailyStatDAO.Clean(nil, 60) // 只保留60天
|
||||
err := SharedServerHTTPFirewallDailyStatDAO.Clean(nil, 30) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerHTTPFirewallDailyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -133,4 +133,3 @@ func (this *ServerHTTPFirewallDailyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
145
internal/db/models/stats/server_region_country_daily_stat_dao.go
Normal file
145
internal/db/models/stats/server_region_country_daily_stat_dao.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
go func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerRegionCountryDailyStatDAO.Clean(nil)
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerRegionCountryDailyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
type ServerRegionCountryDailyStatDAO dbs.DAO
|
||||
|
||||
func NewServerRegionCountryDailyStatDAO() *ServerRegionCountryDailyStatDAO {
|
||||
return dbs.NewDAO(&ServerRegionCountryDailyStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeServerRegionCountryDailyStats",
|
||||
Model: new(ServerRegionCountryDailyStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*ServerRegionCountryDailyStatDAO)
|
||||
}
|
||||
|
||||
var SharedServerRegionCountryDailyStatDAO *ServerRegionCountryDailyStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedServerRegionCountryDailyStatDAO = NewServerRegionCountryDailyStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// IncreaseDailyStat 增加统计
|
||||
func (this *ServerRegionCountryDailyStatDAO) IncreaseDailyStat(tx *dbs.Tx, serverId int64, countryId int64, day string, bytes int64, countRequests int64, attackBytes int64, countAttackRequests int64) error {
|
||||
if len(day) != 8 {
|
||||
return errors.New("invalid day '" + day + "'")
|
||||
}
|
||||
err := this.Query(tx).
|
||||
Param("bytes", bytes).
|
||||
Param("countRequests", countRequests).
|
||||
Param("attackBytes", attackBytes).
|
||||
Param("countAttackRequests", countAttackRequests).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"serverId": serverId,
|
||||
"countryId": countryId,
|
||||
"day": day,
|
||||
"bytes": bytes,
|
||||
"attackBytes": attackBytes,
|
||||
"countRequests": countRequests,
|
||||
"countAttackRequests": countAttackRequests,
|
||||
}, maps.Map{
|
||||
"bytes": dbs.SQL("bytes+:bytes"),
|
||||
"countRequests": dbs.SQL("countRequests+:countRequests"),
|
||||
"attackBytes": dbs.SQL("attackBytes+:attackBytes"),
|
||||
"countAttackRequests": dbs.SQL("countAttackRequests+:countAttackRequests"),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListServerStats 查找单页数据
|
||||
func (this *ServerRegionCountryDailyStatDAO) ListServerStats(tx *dbs.Tx, serverId int64, day string, orderField string, offset int64, size int64) (result []*ServerRegionCountryDailyStat, err error) {
|
||||
query := this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
Attr("day", day).
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result)
|
||||
|
||||
switch orderField {
|
||||
case "bytes":
|
||||
query.Desc("bytes")
|
||||
case "countRequests":
|
||||
query.Desc("countRequests")
|
||||
case "attackBytes":
|
||||
query.Desc("attackBytes")
|
||||
case "countAttackRequests":
|
||||
query.Desc("countAttackRequests")
|
||||
}
|
||||
|
||||
_, err = query.FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// ListSumStats 查找总体数据
|
||||
func (this *ServerRegionCountryDailyStatDAO) ListSumStats(tx *dbs.Tx, day string, orderField string, offset int64, size int64) (result []*ServerRegionCountryDailyStat, err error) {
|
||||
query := this.Query(tx).
|
||||
Attr("day", day).
|
||||
Result("countryId", "SUM(bytes) AS bytes", "SUM(countRequests) AS countRequests", "SUM(attackBytes) AS attackBytes", "SUM(countAttackRequests) AS countAttackRequests").
|
||||
Group("countryId").
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result)
|
||||
|
||||
switch orderField {
|
||||
case "bytes":
|
||||
query.Desc("bytes")
|
||||
case "countRequests":
|
||||
query.Desc("countRequests")
|
||||
case "attackBytes":
|
||||
query.Desc("attackBytes")
|
||||
case "countAttackRequests":
|
||||
query.Desc("countAttackRequests")
|
||||
}
|
||||
|
||||
_, err = query.FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// SumDailyBytes 计算总流量
|
||||
func (this *ServerRegionCountryDailyStatDAO) SumDailyTotalBytes(tx *dbs.Tx, day string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("day", day).
|
||||
SumInt64("bytes", 0)
|
||||
}
|
||||
|
||||
// Clean 清理统计数据
|
||||
func (this *ServerRegionCountryDailyStatDAO) Clean(tx *dbs.Tx) error {
|
||||
// 只保留7天的
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -7))
|
||||
_, err := this.Query(tx).
|
||||
Lte("day", day).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestServerRegionCountryDailyStatDAO_IncreaseDailyStat(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
err := NewServerRegionCountryDailyStatDAO().IncreaseDailyStat(tx, 1, 3, timeutil.Format("Ymd"), 2, 2, 1, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestServerRegionCountryDailyStatDAO_ListSumStats(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
stats, err := NewServerRegionCountryDailyStatDAO().ListSumStats(tx, timeutil.Format("Ymd"), "countAttackRequests", 0, 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, stat := range stats {
|
||||
statJSON, err := json.Marshal(stat)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(string(statJSON))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package stats
|
||||
|
||||
// ServerRegionCountryDailyStat 服务用户区域分布统计(按天)
|
||||
type ServerRegionCountryDailyStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
CountryId uint32 `field:"countryId"` // 国家/区域ID
|
||||
Day string `field:"day"` // 日期YYYYMMDD
|
||||
CountRequests uint64 `field:"countRequests"` // 请求数量
|
||||
CountAttackRequests uint64 `field:"countAttackRequests"` // 攻击数量
|
||||
AttackBytes uint64 `field:"attackBytes"` // 攻击流量
|
||||
Bytes uint64 `field:"bytes"` // 总流量
|
||||
}
|
||||
|
||||
type ServerRegionCountryDailyStatOperator struct {
|
||||
Id interface{} // ID
|
||||
ServerId interface{} // 服务ID
|
||||
CountryId interface{} // 国家/区域ID
|
||||
Day interface{} // 日期YYYYMMDD
|
||||
CountRequests interface{} // 请求数量
|
||||
CountAttackRequests interface{} // 攻击数量
|
||||
AttackBytes interface{} // 攻击流量
|
||||
Bytes interface{} // 总流量
|
||||
}
|
||||
|
||||
func NewServerRegionCountryDailyStatOperator() *ServerRegionCountryDailyStatOperator {
|
||||
return &ServerRegionCountryDailyStatOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package stats
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/authority"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/regions"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/stats"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
@@ -735,6 +736,34 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
}
|
||||
}
|
||||
|
||||
// 流量排行
|
||||
if isPlus {
|
||||
totalBytes, err := stats.SharedServerRegionCountryDailyStatDAO.SumDailyTotalBytes(tx, timeutil.Format("Ymd"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if totalBytes > 0 {
|
||||
topCountryStats, err := stats.SharedServerRegionCountryDailyStatDAO.ListSumStats(tx, timeutil.Format("Ymd"), "bytes", 0, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, stat := range topCountryStats {
|
||||
countryName, err := regions.SharedRegionCountryDAO.FindRegionCountryName(tx, int64(stat.CountryId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.TopCountryStats = append(result.TopCountryStats, &pb.ComposeAdminDashboardResponse_CountryStat{
|
||||
CountryName: countryName,
|
||||
Bytes: int64(stat.Bytes),
|
||||
CountRequests: int64(stat.CountRequests),
|
||||
Percent: float32(stat.Bytes*100) / float32(totalBytes),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 指标数据
|
||||
pbCharts, err := this.findMetricDataCharts(tx)
|
||||
if err != nil {
|
||||
|
||||
@@ -1358,9 +1358,17 @@ func (this *ServerService) UploadServerHTTPRequestStat(ctx context.Context, req
|
||||
return err
|
||||
}
|
||||
if countryId > 0 {
|
||||
key := fmt.Sprintf("%d@%d@%s", result.ServerId, countryId, month)
|
||||
countryKey := fmt.Sprintf("%d@%d@%s", result.ServerId, countryId, day)
|
||||
serverStatLocker.Lock()
|
||||
serverHTTPCountryStatMap[key] += result.Count
|
||||
stat, ok := serverHTTPCountryStatMap[countryKey]
|
||||
if !ok {
|
||||
stat = &TrafficStat{}
|
||||
serverHTTPCountryStatMap[countryKey] = stat
|
||||
}
|
||||
stat.CountRequests += result.CountRequests
|
||||
stat.Bytes += result.Bytes
|
||||
stat.CountAttackRequests += result.CountAttackRequests
|
||||
stat.AttackBytes += result.AttackBytes
|
||||
serverStatLocker.Unlock()
|
||||
|
||||
// 省份
|
||||
@@ -1372,7 +1380,7 @@ func (this *ServerService) UploadServerHTTPRequestStat(ctx context.Context, req
|
||||
if provinceId > 0 {
|
||||
key := fmt.Sprintf("%d@%d@%s", result.ServerId, provinceId, month)
|
||||
serverStatLocker.Lock()
|
||||
serverHTTPProvinceStatMap[key] += result.Count
|
||||
serverHTTPProvinceStatMap[key] += result.CountRequests
|
||||
serverStatLocker.Unlock()
|
||||
|
||||
// 城市
|
||||
@@ -1384,7 +1392,7 @@ func (this *ServerService) UploadServerHTTPRequestStat(ctx context.Context, req
|
||||
if cityId > 0 {
|
||||
key := fmt.Sprintf("%d@%d@%s", result.ServerId, cityId, month)
|
||||
serverStatLocker.Lock()
|
||||
serverHTTPCityStatMap[key] += result.Count
|
||||
serverHTTPCityStatMap[key] += result.CountRequests
|
||||
serverStatLocker.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package services
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/stats"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -12,8 +13,19 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type TrafficStat struct {
|
||||
Bytes int64
|
||||
CachedBytes int64
|
||||
CountRequests int64
|
||||
CountCachedRequests int64
|
||||
CountAttackRequests int64
|
||||
AttackBytes int64
|
||||
PlanId int64
|
||||
CheckingTrafficLimit bool
|
||||
}
|
||||
|
||||
// HTTP请求统计缓存队列
|
||||
var serverHTTPCountryStatMap = map[string]int64{} // serverId@countryId@month => count
|
||||
var serverHTTPCountryStatMap = map[string]*TrafficStat{} // serverId@countryId@day => *TrafficStat
|
||||
var serverHTTPProvinceStatMap = map[string]int64{} // serverId@provinceId@month => count
|
||||
var serverHTTPCityStatMap = map[string]int64{} // serverId@cityId@month => count
|
||||
var serverHTTPProviderStatMap = map[string]int64{} // serverId@providerId@month => count
|
||||
@@ -49,14 +61,26 @@ func (this *ServerService) dumpServerHTTPStats() error {
|
||||
{
|
||||
serverStatLocker.Lock()
|
||||
m := serverHTTPCountryStatMap
|
||||
serverHTTPCountryStatMap = map[string]int64{}
|
||||
serverHTTPCountryStatMap = map[string]*TrafficStat{}
|
||||
serverStatLocker.Unlock()
|
||||
for k, count := range m {
|
||||
for k, stat := range m {
|
||||
pieces := strings.Split(k, "@")
|
||||
if len(pieces) != 3 {
|
||||
continue
|
||||
}
|
||||
err := stats.SharedServerRegionCountryMonthlyStatDAO.IncreaseMonthlyCount(nil, types.Int64(pieces[0]), types.Int64(pieces[1]), pieces[2], count)
|
||||
|
||||
// Monthly
|
||||
var day = pieces[2]
|
||||
if len(day) != 8 {
|
||||
return errors.New("invalid day '" + day + "'")
|
||||
}
|
||||
err := stats.SharedServerRegionCountryMonthlyStatDAO.IncreaseMonthlyCount(nil, types.Int64(pieces[0]), types.Int64(pieces[1]), day[:6], stat.CountRequests)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Daily
|
||||
err = stats.SharedServerRegionCountryDailyStatDAO.IncreaseDailyStat(nil, types.Int64(pieces[0]), types.Int64(pieces[1]), day, stat.Bytes, stat.CountRequests, stat.AttackBytes, stat.CountAttackRequests)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -87,12 +111,12 @@ func (this *ServerService) dumpServerHTTPStats() error {
|
||||
m := serverHTTPCityStatMap
|
||||
serverHTTPCityStatMap = map[string]int64{}
|
||||
serverStatLocker.Unlock()
|
||||
for k, count := range m {
|
||||
for k, countRequests := range m {
|
||||
pieces := strings.Split(k, "@")
|
||||
if len(pieces) != 3 {
|
||||
continue
|
||||
}
|
||||
err := stats.SharedServerRegionCityMonthlyStatDAO.IncreaseMonthlyCount(nil, types.Int64(pieces[0]), types.Int64(pieces[1]), pieces[2], count)
|
||||
err := stats.SharedServerRegionCityMonthlyStatDAO.IncreaseMonthlyCount(nil, types.Int64(pieces[0]), types.Int64(pieces[1]), pieces[2], countRequests)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -172,13 +196,12 @@ func (this *ServerService) dumpServerHTTPStats() error {
|
||||
}
|
||||
|
||||
// 按小时统计
|
||||
err = stats.SharedServerHTTPFirewallHourlyStatDAO.IncreaseHourlyCount(nil, types.Int64(pieces[0]), types.Int64(pieces[1]), pieces[2], pieces[3] + timeutil.Format("H"), count)
|
||||
err = stats.SharedServerHTTPFirewallHourlyStatDAO.IncreaseHourlyCount(nil, types.Int64(pieces[0]), types.Int64(pieces[1]), pieces[2], pieces[3]+timeutil.Format("H"), count)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user