This commit is contained in:
robin
2026-03-13 14:25:13 +08:00
parent a25a474d6a
commit afbaaa869c
95 changed files with 4591 additions and 2578 deletions

View File

@@ -0,0 +1,324 @@
package httpdns
import (
"context"
"time"
"github.com/TeaOSLab/EdgeAPI/internal/clickhouse"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/dbs"
timeutil "github.com/iwind/TeaGo/utils/time"
)
// HTTPDNSBoardService HTTPDNS 仪表盘服务
type HTTPDNSBoardService struct {
services.BaseService
}
// ComposeHTTPDNSBoard 组合看板数据
func (this *HTTPDNSBoardService) ComposeHTTPDNSBoard(ctx context.Context, req *pb.ComposeHTTPDNSBoardRequest) (*pb.ComposeHTTPDNSBoardResponse, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
tx := this.NullTx()
result := &pb.ComposeHTTPDNSBoardResponse{}
countApps, err := models.SharedHTTPDNSAppDAO.CountEnabledApps(tx, "")
if err != nil {
return nil, err
}
result.CountApps = countApps
countDomains, err := models.SharedHTTPDNSDomainDAO.CountEnabledDomains(tx, 0)
if err != nil {
return nil, err
}
result.CountDomains = countDomains
countClusters, err := models.SharedHTTPDNSClusterDAO.CountEnabledClusters(tx, "")
if err != nil {
return nil, err
}
result.CountClusters = countClusters
allNodes, err := models.SharedHTTPDNSNodeDAO.ListEnabledNodes(tx, 0)
if err != nil {
return nil, err
}
result.CountNodes = int64(len(allNodes))
var countOffline int64
for _, node := range allNodes {
if !node.IsActive {
countOffline++
}
}
result.CountOfflineNodes = countOffline
hourFrom := timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
hourTo := timeutil.Format("YmdH")
dayFrom := timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
dayTo := timeutil.Format("Ymd")
todayFrom := timeutil.Format("Ymd", time.Now().Add(-24*time.Hour))
store := clickhouse.NewHTTPDNSAccessLogsStore()
if store.Client().IsConfigured() {
err = this.composeTrafficAndRanksFromClickHouse(ctx, tx, store, result, hourFrom, hourTo, dayFrom, dayTo, todayFrom)
}
if err != nil || !store.Client().IsConfigured() {
err = this.composeTrafficAndRanksFromMySQL(tx, result, hourFrom, hourTo, dayFrom, dayTo, todayFrom)
if err != nil {
return nil, err
}
}
err = this.fillNodeValues(tx, result)
if err != nil {
return nil, err
}
return result, nil
}
func (this *HTTPDNSBoardService) composeTrafficAndRanksFromClickHouse(ctx context.Context, tx *dbs.Tx, store *clickhouse.HTTPDNSAccessLogsStore, result *pb.ComposeHTTPDNSBoardResponse, hourFrom string, hourTo string, dayFrom string, dayTo string, todayFrom string) error {
hourlyStats, err := store.FindHourlyStats(ctx, hourFrom, hourTo)
if err != nil {
return err
}
hourlyMap := map[string]*clickhouse.HTTPDNSAccessLogHourlyStat{}
for _, stat := range hourlyStats {
hourlyMap[stat.Hour] = stat
}
hours, err := utils.RangeHours(hourFrom, hourTo)
if err != nil {
return err
}
for _, hour := range hours {
stat, ok := hourlyMap[hour]
if ok {
result.HourlyTrafficStats = append(result.HourlyTrafficStats, &pb.ComposeHTTPDNSBoardResponse_HourlyTrafficStat{
Hour: hour,
CountRequests: stat.CountRequests,
})
} else {
result.HourlyTrafficStats = append(result.HourlyTrafficStats, &pb.ComposeHTTPDNSBoardResponse_HourlyTrafficStat{Hour: hour})
}
}
dailyStats, err := store.FindDailyStats(ctx, dayFrom, dayTo)
if err != nil {
return err
}
dailyMap := map[string]*clickhouse.HTTPDNSAccessLogDailyStat{}
for _, stat := range dailyStats {
dailyMap[stat.Day] = stat
}
days, err := utils.RangeDays(dayFrom, dayTo)
if err != nil {
return err
}
for _, day := range days {
stat, ok := dailyMap[day]
if ok {
result.DailyTrafficStats = append(result.DailyTrafficStats, &pb.ComposeHTTPDNSBoardResponse_DailyTrafficStat{
Day: day,
CountRequests: stat.CountRequests,
})
} else {
result.DailyTrafficStats = append(result.DailyTrafficStats, &pb.ComposeHTTPDNSBoardResponse_DailyTrafficStat{Day: day})
}
}
topAppStats, err := store.ListTopApps(ctx, todayFrom, dayTo, 10)
if err != nil {
return err
}
for _, stat := range topAppStats {
appName := stat.AppName
if len(appName) == 0 {
appName = stat.AppId
}
result.TopAppStats = append(result.TopAppStats, &pb.ComposeHTTPDNSBoardResponse_TopAppStat{
AppId: 0,
AppName: appName,
CountRequests: stat.CountRequests,
})
}
topDomainStats, err := store.ListTopDomains(ctx, todayFrom, dayTo, 10)
if err != nil {
return err
}
for _, stat := range topDomainStats {
result.TopDomainStats = append(result.TopDomainStats, &pb.ComposeHTTPDNSBoardResponse_TopDomainStat{
DomainName: stat.Domain,
CountRequests: stat.CountRequests,
})
}
topNodeStats, err := store.ListTopNodes(ctx, todayFrom, dayTo, 10)
if err != nil {
return err
}
for _, stat := range topNodeStats {
nodeName := ""
node, nodeErr := models.SharedHTTPDNSNodeDAO.FindEnabledNode(tx, int64(stat.NodeId))
if nodeErr == nil && node != nil {
nodeName = node.Name
}
if len(nodeName) == 0 {
continue
}
result.TopNodeStats = append(result.TopNodeStats, &pb.ComposeHTTPDNSBoardResponse_TopNodeStat{
ClusterId: int64(stat.ClusterId),
NodeId: int64(stat.NodeId),
NodeName: nodeName,
CountRequests: stat.CountRequests,
})
}
return nil
}
func (this *HTTPDNSBoardService) composeTrafficAndRanksFromMySQL(tx *dbs.Tx, result *pb.ComposeHTTPDNSBoardResponse, hourFrom string, hourTo string, dayFrom string, dayTo string, todayFrom string) error {
hourlyStats, err := models.SharedHTTPDNSAccessLogDAO.FindHourlyStats(tx, hourFrom, hourTo)
if err != nil {
return err
}
hourlyMap := map[string]*models.HTTPDNSAccessLogHourlyStat{}
for _, stat := range hourlyStats {
hourlyMap[stat.Hour] = stat
}
hours, err := utils.RangeHours(hourFrom, hourTo)
if err != nil {
return err
}
for _, hour := range hours {
stat, ok := hourlyMap[hour]
if ok {
result.HourlyTrafficStats = append(result.HourlyTrafficStats, &pb.ComposeHTTPDNSBoardResponse_HourlyTrafficStat{
Hour: hour,
CountRequests: stat.CountRequests,
})
} else {
result.HourlyTrafficStats = append(result.HourlyTrafficStats, &pb.ComposeHTTPDNSBoardResponse_HourlyTrafficStat{Hour: hour})
}
}
dailyStats, err := models.SharedHTTPDNSAccessLogDAO.FindDailyStats(tx, dayFrom, dayTo)
if err != nil {
return err
}
dailyMap := map[string]*models.HTTPDNSAccessLogDailyStat{}
for _, stat := range dailyStats {
dailyMap[stat.Day] = stat
}
days, err := utils.RangeDays(dayFrom, dayTo)
if err != nil {
return err
}
for _, day := range days {
stat, ok := dailyMap[day]
if ok {
result.DailyTrafficStats = append(result.DailyTrafficStats, &pb.ComposeHTTPDNSBoardResponse_DailyTrafficStat{
Day: day,
CountRequests: stat.CountRequests,
})
} else {
result.DailyTrafficStats = append(result.DailyTrafficStats, &pb.ComposeHTTPDNSBoardResponse_DailyTrafficStat{Day: day})
}
}
topAppStats, err := models.SharedHTTPDNSAccessLogDAO.ListTopApps(tx, todayFrom, dayTo, 10)
if err != nil {
return err
}
for _, stat := range topAppStats {
appName := stat.AppName
if len(appName) == 0 {
appName = stat.AppId
}
result.TopAppStats = append(result.TopAppStats, &pb.ComposeHTTPDNSBoardResponse_TopAppStat{
AppId: 0,
AppName: appName,
CountRequests: stat.CountRequests,
})
}
topDomainStats, err := models.SharedHTTPDNSAccessLogDAO.ListTopDomains(tx, todayFrom, dayTo, 10)
if err != nil {
return err
}
for _, stat := range topDomainStats {
result.TopDomainStats = append(result.TopDomainStats, &pb.ComposeHTTPDNSBoardResponse_TopDomainStat{
DomainName: stat.Domain,
CountRequests: stat.CountRequests,
})
}
topNodeStats, err := models.SharedHTTPDNSAccessLogDAO.ListTopNodes(tx, todayFrom, dayTo, 10)
if err != nil {
return err
}
for _, stat := range topNodeStats {
nodeName := ""
node, nodeErr := models.SharedHTTPDNSNodeDAO.FindEnabledNode(tx, int64(stat.NodeId))
if nodeErr == nil && node != nil {
nodeName = node.Name
}
if len(nodeName) == 0 {
continue
}
result.TopNodeStats = append(result.TopNodeStats, &pb.ComposeHTTPDNSBoardResponse_TopNodeStat{
ClusterId: int64(stat.ClusterId),
NodeId: int64(stat.NodeId),
NodeName: nodeName,
CountRequests: stat.CountRequests,
})
}
return nil
}
func (this *HTTPDNSBoardService) fillNodeValues(tx *dbs.Tx, result *pb.ComposeHTTPDNSBoardResponse) error {
cpuValues, err := models.SharedNodeValueDAO.ListValuesForHTTPDNSNodes(tx, nodeconfigs.NodeValueItemCPU, "usage", nodeconfigs.NodeValueRangeMinute)
if err != nil {
return err
}
for _, v := range cpuValues {
result.CpuNodeValues = append(result.CpuNodeValues, &pb.NodeValue{
ValueJSON: v.Value,
CreatedAt: int64(v.CreatedAt),
})
}
memoryValues, err := models.SharedNodeValueDAO.ListValuesForHTTPDNSNodes(tx, nodeconfigs.NodeValueItemMemory, "usage", nodeconfigs.NodeValueRangeMinute)
if err != nil {
return err
}
for _, v := range memoryValues {
result.MemoryNodeValues = append(result.MemoryNodeValues, &pb.NodeValue{
ValueJSON: v.Value,
CreatedAt: int64(v.CreatedAt),
})
}
loadValues, err := models.SharedNodeValueDAO.ListValuesForHTTPDNSNodes(tx, nodeconfigs.NodeValueItemLoad, "load1m", nodeconfigs.NodeValueRangeMinute)
if err != nil {
return err
}
for _, v := range loadValues {
result.LoadNodeValues = append(result.LoadNodeValues, &pb.NodeValue{
ValueJSON: v.Value,
CreatedAt: int64(v.CreatedAt),
})
}
return nil
}

View File

@@ -17,7 +17,7 @@ type NodeValueService struct {
// CreateNodeValue 记录数据
func (this *NodeValueService) CreateNodeValue(ctx context.Context, req *pb.CreateNodeValueRequest) (*pb.RPCSuccess, error) {
role, nodeId, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeNode, rpcutils.UserTypeDNS, rpcutils.UserTypeUser)
role, nodeId, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeNode, rpcutils.UserTypeDNS, rpcutils.UserTypeUser, rpcutils.UserTypeHTTPDNS)
if err != nil {
return nil, err
}
@@ -30,6 +30,8 @@ func (this *NodeValueService) CreateNodeValue(ctx context.Context, req *pb.Creat
clusterId, err = models.SharedNodeDAO.FindNodeClusterId(tx, nodeId)
case rpcutils.UserTypeDNS:
clusterId, err = models.SharedNSNodeDAO.FindNodeClusterId(tx, nodeId)
case rpcutils.UserTypeHTTPDNS:
clusterId, err = models.SharedHTTPDNSNodeDAO.FindNodeClusterId(tx, nodeId)
case rpcutils.UserTypeUser:
}
if err != nil {