mirror of
https://github.com/TeaOSLab/EdgeAPI.git
synced 2025-11-08 11:20:26 +08:00
实现节点看板(仅对企业版开放)
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/stats"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
@@ -116,7 +117,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeClusterBoard(ctx contex
|
||||
}
|
||||
|
||||
// 节点排行
|
||||
topNodeStats, err := stats.SharedNodeTrafficHourlyStatDAO.FindTopNodeStatsWithClusterId(tx, req.NodeClusterId, hourFrom, hourTo)
|
||||
topNodeStats, err := stats.SharedNodeTrafficHourlyStatDAO.FindTopNodeStatsWithClusterId(tx, "node", req.NodeClusterId, hourFrom, hourTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -151,7 +152,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeClusterBoard(ctx contex
|
||||
}
|
||||
|
||||
// CPU、内存、负载
|
||||
cpuValues, err := models.SharedNodeValueDAO.ListValuesWithClusterId(tx, req.NodeClusterId, "node", nodeconfigs.NodeValueItemCPU, "usage", nodeconfigs.NodeValueRangeMinute)
|
||||
cpuValues, err := models.SharedNodeValueDAO.ListValuesWithClusterId(tx, "node", req.NodeClusterId, nodeconfigs.NodeValueItemCPU, "usage", nodeconfigs.NodeValueRangeMinute)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -166,7 +167,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeClusterBoard(ctx contex
|
||||
})
|
||||
}
|
||||
|
||||
memoryValues, err := models.SharedNodeValueDAO.ListValuesWithClusterId(tx, req.NodeClusterId, "node", nodeconfigs.NodeValueItemMemory, "usage", nodeconfigs.NodeValueRangeMinute)
|
||||
memoryValues, err := models.SharedNodeValueDAO.ListValuesWithClusterId(tx, "node", req.NodeClusterId, nodeconfigs.NodeValueItemMemory, "usage", nodeconfigs.NodeValueRangeMinute)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -181,7 +182,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeClusterBoard(ctx contex
|
||||
})
|
||||
}
|
||||
|
||||
loadValues, err := models.SharedNodeValueDAO.ListValuesWithClusterId(tx, req.NodeClusterId, "node", nodeconfigs.NodeValueItemLoad, "load5m", nodeconfigs.NodeValueRangeMinute)
|
||||
loadValues, err := models.SharedNodeValueDAO.ListValuesWithClusterId(tx, "node", req.NodeClusterId, nodeconfigs.NodeValueItemLoad, "load5m", nodeconfigs.NodeValueRangeMinute)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -316,3 +317,334 @@ func (this *ServerStatBoardService) ComposeServerStatNodeClusterBoard(ctx contex
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ComposeServerStatNodeBoard 组合节点看板数据
|
||||
func (this *ServerStatBoardService) ComposeServerStatNodeBoard(ctx context.Context, req *pb.ComposeServerStatNodeBoardRequest) (*pb.ComposeServerStatNodeBoardResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result = &pb.ComposeServerStatNodeBoardResponse{}
|
||||
|
||||
// 在线状态
|
||||
var tx = this.NullTx()
|
||||
node, err := models.SharedNodeDAO.FindEnabledNode(tx, req.NodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if node == nil {
|
||||
return nil, errors.New("node not found")
|
||||
}
|
||||
|
||||
status, err := node.DecodeStatus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if status != nil && time.Now().Unix()-status.UpdatedAt < 60 {
|
||||
result.IsActive = true
|
||||
result.CacheDiskSize = status.CacheTotalDiskSize
|
||||
result.CacheMemorySize = status.CacheTotalMemorySize
|
||||
|
||||
}
|
||||
|
||||
// 流量
|
||||
{
|
||||
value, err := models.SharedNodeValueDAO.FindLatestNodeValue(tx, "node", int64(node.Id), nodeconfigs.NodeValueItemTrafficIn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if value != nil && time.Now().Unix()-int64(value.CreatedAt) < 120 {
|
||||
result.TrafficInBytes = value.DecodeMapValue().GetInt64("total")
|
||||
}
|
||||
}
|
||||
{
|
||||
value, err := models.SharedNodeValueDAO.FindLatestNodeValue(tx, "node", int64(node.Id), nodeconfigs.NodeValueItemTrafficOut)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if value != nil && time.Now().Unix()-int64(value.CreatedAt) < 120 {
|
||||
result.TrafficOutBytes = value.DecodeMapValue().GetInt64("total")
|
||||
}
|
||||
}
|
||||
|
||||
// 连接数
|
||||
{
|
||||
value, err := models.SharedNodeValueDAO.FindLatestNodeValue(tx, "node", int64(node.Id), nodeconfigs.NodeValueItemConnections)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if value != nil && time.Now().Unix()-int64(value.CreatedAt) < 120 {
|
||||
result.CountConnections = value.DecodeMapValue().GetInt64("total")
|
||||
}
|
||||
}
|
||||
|
||||
// 请求量
|
||||
{
|
||||
value, err := models.SharedNodeValueDAO.FindLatestNodeValue(tx, "node", int64(node.Id), nodeconfigs.NodeValueItemRequests)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if value != nil && time.Now().Unix()-int64(value.CreatedAt) < 120 {
|
||||
result.CountRequests = value.DecodeMapValue().GetInt64("total")
|
||||
}
|
||||
}
|
||||
{
|
||||
value, err := models.SharedNodeValueDAO.FindLatestNodeValue(tx, "node", int64(node.Id), nodeconfigs.NodeValueItemAttackRequests)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if value != nil && time.Now().Unix()-int64(value.CreatedAt) < 120 {
|
||||
result.CountAttackRequests = value.DecodeMapValue().GetInt64("total")
|
||||
}
|
||||
}
|
||||
|
||||
// CPU
|
||||
{
|
||||
value, err := models.SharedNodeValueDAO.FindLatestNodeValue(tx, "node", int64(node.Id), nodeconfigs.NodeValueItemCPU)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if value != nil && time.Now().Unix()-int64(value.CreatedAt) < 120 {
|
||||
result.CpuUsage = value.DecodeMapValue().GetFloat32("usage")
|
||||
}
|
||||
}
|
||||
|
||||
// 内存
|
||||
{
|
||||
value, err := models.SharedNodeValueDAO.FindLatestNodeValue(tx, "node", int64(node.Id), nodeconfigs.NodeValueItemMemory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if value != nil && time.Now().Unix()-int64(value.CreatedAt) < 120 {
|
||||
m := value.DecodeMapValue()
|
||||
result.MemoryUsage = m.GetFloat32("usage")
|
||||
result.MemoryTotalSize = m.GetInt64("total")
|
||||
}
|
||||
}
|
||||
|
||||
// 负载
|
||||
{
|
||||
value, err := models.SharedNodeValueDAO.FindLatestNodeValue(tx, "node", int64(node.Id), nodeconfigs.NodeValueItemLoad)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if value != nil && time.Now().Unix()-int64(value.CreatedAt) < 120 {
|
||||
result.Load = value.DecodeMapValue().GetFloat32("load1m")
|
||||
}
|
||||
}
|
||||
|
||||
// 按日流量统计
|
||||
dayFrom := timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
|
||||
dailyTrafficStats, err := stats.SharedNodeTrafficDailyStatDAO.FindDailyStats(tx, "node", req.NodeId, dayFrom, timeutil.Format("Ymd"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, stat := range dailyTrafficStats {
|
||||
result.DailyTrafficStats = append(result.DailyTrafficStats, &pb.ComposeServerStatNodeBoardResponse_DailyTrafficStat{
|
||||
Day: stat.Day,
|
||||
Bytes: int64(stat.Bytes),
|
||||
CachedBytes: int64(stat.CachedBytes),
|
||||
CountRequests: int64(stat.CountRequests),
|
||||
CountCachedRequests: int64(stat.CountCachedRequests),
|
||||
})
|
||||
}
|
||||
|
||||
// 小时流量统计
|
||||
hourFrom := timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
|
||||
hourTo := timeutil.Format("YmdH")
|
||||
hourlyTrafficStats, err := stats.SharedNodeTrafficHourlyStatDAO.FindHourlyStatsWithNodeId(tx, "node", req.NodeId, hourFrom, hourTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, stat := range hourlyTrafficStats {
|
||||
result.HourlyTrafficStats = append(result.HourlyTrafficStats, &pb.ComposeServerStatNodeBoardResponse_HourlyTrafficStat{
|
||||
Hour: stat.Hour,
|
||||
Bytes: int64(stat.Bytes),
|
||||
CachedBytes: int64(stat.CachedBytes),
|
||||
CountRequests: int64(stat.CountRequests),
|
||||
CountCachedRequests: int64(stat.CountCachedRequests),
|
||||
})
|
||||
}
|
||||
|
||||
// 域名排行
|
||||
topDomainStats, err := stats.SharedServerDomainHourlyStatDAO.FindTopDomainStatsWithNodeId(tx, req.NodeId, hourFrom, hourTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, stat := range topDomainStats {
|
||||
result.TopDomainStats = append(result.TopDomainStats, &pb.ComposeServerStatNodeBoardResponse_DomainStat{
|
||||
ServerId: int64(stat.ServerId),
|
||||
Domain: stat.Domain,
|
||||
CountRequests: int64(stat.CountRequests),
|
||||
Bytes: int64(stat.Bytes),
|
||||
})
|
||||
}
|
||||
|
||||
// CPU、内存、负载
|
||||
cpuValues, err := models.SharedNodeValueDAO.ListValues(tx, "node", req.NodeId, nodeconfigs.NodeValueItemCPU, nodeconfigs.NodeValueRangeMinute)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range cpuValues {
|
||||
valueJSON, err := json.Marshal(types.Float32(v.DecodeMapValue().GetFloat32("usage")))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CpuNodeValues = append(result.CpuNodeValues, &pb.NodeValue{
|
||||
ValueJSON: valueJSON,
|
||||
CreatedAt: int64(v.CreatedAt),
|
||||
})
|
||||
}
|
||||
|
||||
memoryValues, err := models.SharedNodeValueDAO.ListValues(tx, "node", req.NodeId, nodeconfigs.NodeValueItemMemory, nodeconfigs.NodeValueRangeMinute)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range memoryValues {
|
||||
valueJSON, err := json.Marshal(types.Float32(v.DecodeMapValue().GetFloat32("usage")))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.MemoryNodeValues = append(result.MemoryNodeValues, &pb.NodeValue{
|
||||
ValueJSON: valueJSON,
|
||||
CreatedAt: int64(v.CreatedAt),
|
||||
})
|
||||
}
|
||||
|
||||
loadValues, err := models.SharedNodeValueDAO.ListValues(tx, "node", req.NodeId, nodeconfigs.NodeValueItemLoad, nodeconfigs.NodeValueRangeMinute)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range loadValues {
|
||||
valueJSON, err := json.Marshal(types.Float32(v.DecodeMapValue().GetFloat32("load5m")))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.LoadNodeValues = append(result.LoadNodeValues, &pb.NodeValue{
|
||||
ValueJSON: valueJSON,
|
||||
CreatedAt: int64(v.CreatedAt),
|
||||
})
|
||||
}
|
||||
|
||||
// 指标
|
||||
var clusterId = int64(node.ClusterId)
|
||||
clusterMetricItems, err := models.SharedNodeClusterMetricItemDAO.FindAllClusterItems(tx, clusterId, serverconfigs.MetricItemCategoryHTTP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbMetricCharts = []*pb.ComposeServerStatNodeBoardResponse_MetricData{}
|
||||
for _, clusterMetricItem := range clusterMetricItems {
|
||||
if clusterMetricItem.IsOn != 1 {
|
||||
continue
|
||||
}
|
||||
var itemId = int64(clusterMetricItem.ItemId)
|
||||
charts, err := models.SharedMetricChartDAO.FindAllEnabledCharts(tx, itemId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
item, err := models.SharedMetricItemDAO.FindEnabledMetricItem(tx, itemId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if item == nil || item.IsOn == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, chart := range charts {
|
||||
if chart.IsOn == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var pbChart = &pb.MetricChart{
|
||||
Id: int64(chart.Id),
|
||||
Name: chart.Name,
|
||||
Type: chart.Type,
|
||||
WidthDiv: chart.WidthDiv,
|
||||
ParamsJSON: nil,
|
||||
IsOn: chart.IsOn == 1,
|
||||
MaxItems: types.Int32(chart.MaxItems),
|
||||
MetricItem: &pb.MetricItem{
|
||||
Id: itemId,
|
||||
PeriodUnit: item.PeriodUnit,
|
||||
Period: types.Int32(item.Period),
|
||||
Name: item.Name,
|
||||
Value: item.Value,
|
||||
Category: item.Category,
|
||||
Keys: item.DecodeKeys(),
|
||||
Code: item.Code,
|
||||
IsOn: item.IsOn == 1,
|
||||
},
|
||||
}
|
||||
var pbStats = []*pb.MetricStat{}
|
||||
switch chart.Type {
|
||||
case serverconfigs.MetricChartTypeTimeLine:
|
||||
itemStats, err := models.SharedMetricStatDAO.FindLatestItemStatsWithNodeId(tx, req.NodeId, itemId, types.Int32(item.Version), 10)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, stat := range itemStats {
|
||||
// 当前时间总和
|
||||
count, total, err := models.SharedMetricSumStatDAO.FindNodeSum(tx, req.NodeId, stat.Time, itemId, types.Int32(item.Version))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pbStats = append(pbStats, &pb.MetricStat{
|
||||
Id: int64(stat.Id),
|
||||
Hash: stat.Hash,
|
||||
ServerId: 0,
|
||||
ItemId: 0,
|
||||
Keys: stat.DecodeKeys(),
|
||||
Value: types.Float32(stat.Value),
|
||||
Time: stat.Time,
|
||||
Version: 0,
|
||||
NodeCluster: nil,
|
||||
Node: nil,
|
||||
Server: nil,
|
||||
SumCount: count,
|
||||
SumTotal: total,
|
||||
})
|
||||
}
|
||||
default:
|
||||
itemStats, err := models.SharedMetricStatDAO.FindItemStatsWithNodeIdAndLastTime(tx, req.NodeId, itemId, types.Int32(item.Version), 10)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, stat := range itemStats {
|
||||
// 当前时间总和
|
||||
// 当前时间总和
|
||||
count, total, err := models.SharedMetricSumStatDAO.FindNodeSum(tx, req.NodeId, stat.Time, itemId, types.Int32(item.Version))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pbStats = append(pbStats, &pb.MetricStat{
|
||||
Id: int64(stat.Id),
|
||||
Hash: stat.Hash,
|
||||
ServerId: 0,
|
||||
ItemId: 0,
|
||||
Keys: stat.DecodeKeys(),
|
||||
Value: types.Float32(stat.Value),
|
||||
Time: stat.Time,
|
||||
Version: 0,
|
||||
NodeCluster: nil,
|
||||
Node: nil,
|
||||
Server: nil,
|
||||
SumCount: count,
|
||||
SumTotal: total,
|
||||
})
|
||||
}
|
||||
}
|
||||
pbMetricCharts = append(pbMetricCharts, &pb.ComposeServerStatNodeBoardResponse_MetricData{
|
||||
MetricChart: pbChart,
|
||||
MetricStats: pbStats,
|
||||
})
|
||||
}
|
||||
}
|
||||
result.MetricCharts = pbMetricCharts
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user