Refactor dashboard overview: remove active alerts and lagging nodes from summary, update tests and components accordingly

- Removed active alerts and lagging nodes from DashboardSummary and related types.
- Updated DashboardOverview component to reflect changes in data structure.
- Adjusted tests to align with the new dashboard overview structure, ensuring no active alerts are displayed.
- Simplified the dashboard metrics and risk signals, focusing on essential health and capacity metrics.
- Enhanced the WorldStage component to present updated traffic and capacity information.
- Removed unused alert-related functions and components to streamline the codebase.
This commit is contained in:
ryan
2026-03-14 16:00:41 +08:00
parent f33e9514dc
commit fe3c6312f9
8 changed files with 118 additions and 900 deletions
-192
View File
@@ -2,11 +2,8 @@ package service
import (
"atsflare/model"
"errors"
"sort"
"time"
"gorm.io/gorm"
)
type DashboardOverviewView struct {
@@ -14,13 +11,9 @@ type DashboardOverviewView struct {
Summary DashboardSummary `json:"summary"`
Traffic DashboardTraffic `json:"traffic"`
Capacity DashboardCapacity `json:"capacity"`
Config DashboardConfig `json:"config"`
Risk DashboardRiskSummary `json:"risk"`
Peaks DashboardPeakSummary `json:"peaks"`
Distributions TrafficDistributions `json:"distributions"`
Trends DashboardTrends `json:"trends"`
Nodes []DashboardNodeHealth `json:"nodes"`
ActiveAlerts []DashboardAlert `json:"active_alerts"`
}
type DashboardSummary struct {
@@ -29,8 +22,6 @@ type DashboardSummary struct {
OfflineNodes int `json:"offline_nodes"`
PendingNodes int `json:"pending_nodes"`
UnhealthyNodes int `json:"unhealthy_nodes"`
ActiveAlerts int `json:"active_alerts"`
LaggingNodes int `json:"lagging_nodes"`
}
type DashboardTraffic struct {
@@ -49,48 +40,6 @@ type DashboardCapacity struct {
HighStorageNodes int `json:"high_storage_nodes"`
}
type DashboardConfig struct {
ActiveVersion string `json:"active_version"`
LaggingNodes int `json:"lagging_nodes"`
PendingNodes int `json:"pending_nodes"`
}
type DashboardRiskSummary struct {
CriticalAlerts int `json:"critical_alerts"`
WarningAlerts int `json:"warning_alerts"`
InfoAlerts int `json:"info_alerts"`
OfflineNodes int `json:"offline_nodes"`
UnhealthyNodes int `json:"unhealthy_nodes"`
LaggingNodes int `json:"lagging_nodes"`
HighCPUNodes int `json:"high_cpu_nodes"`
HighMemoryNodes int `json:"high_memory_nodes"`
HighStorageNodes int `json:"high_storage_nodes"`
}
type DashboardPeakSummary struct {
PeakRequestHour DashboardPeakHour `json:"peak_request_hour"`
PeakErrorHour DashboardPeakHour `json:"peak_error_hour"`
BusiestNode *DashboardPeakNode `json:"busiest_node"`
RiskiestNode *DashboardPeakNode `json:"riskiest_node"`
}
type DashboardPeakHour struct {
BucketStartedAt time.Time `json:"bucket_started_at"`
RequestCount int64 `json:"request_count"`
ErrorCount int64 `json:"error_count"`
}
type DashboardPeakNode struct {
NodeID string `json:"node_id"`
NodeName string `json:"node_name"`
RequestCount int64 `json:"request_count"`
ErrorCount int64 `json:"error_count"`
CPUUsagePercent float64 `json:"cpu_usage_percent"`
ActiveEventCount int `json:"active_event_count"`
OpenrestyStatus string `json:"openresty_status"`
StorageUsagePercent float64 `json:"storage_usage_percent"`
}
type DashboardTrends struct {
Traffic24h []TrafficTrendPoint `json:"traffic_24h"`
Capacity24h []CapacityTrendPoint `json:"capacity_24h"`
@@ -118,16 +67,6 @@ type DashboardNodeHealth struct {
UniqueVisitorCount int64 `json:"unique_visitor_count"`
}
type DashboardAlert struct {
NodeID string `json:"node_id"`
NodeName string `json:"node_name"`
EventType string `json:"event_type"`
Severity string `json:"severity"`
Message string `json:"message"`
LastTriggeredAt time.Time `json:"last_triggered_at"`
Status string `json:"status"`
}
func GetDashboardOverview() (*DashboardOverviewView, error) {
now := time.Now()
since := now.Add(-24 * time.Hour)
@@ -137,13 +76,6 @@ func GetDashboardOverview() (*DashboardOverviewView, error) {
return nil, err
}
activeVersion := ""
if version, versionErr := model.GetActiveConfigVersion(); versionErr == nil {
activeVersion = version.Version
} else if !errors.Is(versionErr, gorm.ErrRecordNotFound) {
return nil, versionErr
}
snapshots, err := model.ListMetricSnapshotsSince(since)
if err != nil {
return nil, err
@@ -160,7 +92,6 @@ func GetDashboardOverview() (*DashboardOverviewView, error) {
view := &DashboardOverviewView{
GeneratedAt: now,
Nodes: make([]DashboardNodeHealth, 0, len(nodes)),
ActiveAlerts: make([]DashboardAlert, 0),
Distributions: buildTrafficDistributions(reports, 8),
Trends: DashboardTrends{
Traffic24h: buildTrafficTrendPoints(now, reports),
@@ -183,21 +114,11 @@ func GetDashboardOverview() (*DashboardOverviewView, error) {
view.Summary.OnlineNodes++
case NodeStatusOffline:
view.Summary.OfflineNodes++
view.Risk.OfflineNodes++
case NodeStatusPending:
view.Summary.PendingNodes++
}
if node.OpenrestyStatus == OpenrestyStatusUnhealthy {
view.Summary.UnhealthyNodes++
view.Risk.UnhealthyNodes++
}
if activeVersion != "" && node.CurrentVersion != "" && node.CurrentVersion != activeVersion {
view.Summary.LaggingNodes++
view.Risk.LaggingNodes++
}
if activeVersion != "" && node.CurrentVersion == "" && computedStatus != NodeStatusPending {
view.Summary.LaggingNodes++
view.Risk.LaggingNodes++
}
latestSnapshot := latestSnapshots[node.NodeID]
@@ -218,26 +139,6 @@ func GetDashboardOverview() (*DashboardOverviewView, error) {
ActiveEventCount: len(nodeActiveEvents),
}
for _, event := range nodeActiveEvents {
view.ActiveAlerts = append(view.ActiveAlerts, DashboardAlert{
NodeID: node.NodeID,
NodeName: node.Name,
EventType: event.EventType,
Severity: event.Severity,
Message: event.Message,
LastTriggeredAt: event.LastTriggeredAt,
Status: event.Status,
})
switch event.Severity {
case NodeHealthSeverityCritical:
view.Risk.CriticalAlerts++
case NodeHealthSeverityWarning:
view.Risk.WarningAlerts++
default:
view.Risk.InfoAlerts++
}
}
if latestSnapshot != nil {
nodeHealth.CPUUsagePercent = latestSnapshot.CPUUsagePercent
nodeHealth.MemoryUsagePercent = percentage(latestSnapshot.MemoryUsedBytes, latestSnapshot.MemoryTotalBytes)
@@ -252,15 +153,12 @@ func GetDashboardOverview() (*DashboardOverviewView, error) {
}
if latestSnapshot.CPUUsagePercent >= 80 {
view.Capacity.HighCPUNodes++
view.Risk.HighCPUNodes++
}
if nodeHealth.MemoryUsagePercent >= 85 {
view.Capacity.HighMemoryNodes++
view.Risk.HighMemoryNodes++
}
if nodeHealth.StorageUsagePercent >= 85 {
view.Capacity.HighStorageNodes++
view.Risk.HighStorageNodes++
}
}
@@ -277,14 +175,10 @@ func GetDashboardOverview() (*DashboardOverviewView, error) {
view.Traffic.ReportedNodes++
}
view.Summary.ActiveAlerts += len(nodeActiveEvents)
view.Nodes = append(view.Nodes, nodeHealth)
}
view.Summary.TotalNodes = len(nodes)
view.Config.ActiveVersion = activeVersion
view.Config.LaggingNodes = view.Summary.LaggingNodes
view.Config.PendingNodes = view.Summary.PendingNodes
if cpuNodeCount > 0 {
view.Capacity.AverageCPUUsagePercent /= float64(cpuNodeCount)
@@ -293,13 +187,6 @@ func GetDashboardOverview() (*DashboardOverviewView, error) {
view.Capacity.AverageMemoryUsagePercent /= float64(memoryNodeCount)
}
sort.Slice(view.ActiveAlerts, func(i int, j int) bool {
if severityWeight(view.ActiveAlerts[i].Severity) == severityWeight(view.ActiveAlerts[j].Severity) {
return view.ActiveAlerts[i].LastTriggeredAt.After(view.ActiveAlerts[j].LastTriggeredAt)
}
return severityWeight(view.ActiveAlerts[i].Severity) > severityWeight(view.ActiveAlerts[j].Severity)
})
sort.Slice(view.Nodes, func(i int, j int) bool {
if view.Nodes[i].ActiveEventCount == view.Nodes[j].ActiveEventCount {
return view.Nodes[i].CPUUsagePercent > view.Nodes[j].CPUUsagePercent
@@ -307,19 +194,6 @@ func GetDashboardOverview() (*DashboardOverviewView, error) {
return view.Nodes[i].ActiveEventCount > view.Nodes[j].ActiveEventCount
})
if len(view.ActiveAlerts) > 8 {
view.ActiveAlerts = view.ActiveAlerts[:8]
}
view.Peaks.PeakRequestHour = peakTrafficHour(view.Trends.Traffic24h, func(point TrafficTrendPoint) int64 {
return point.RequestCount
})
view.Peaks.PeakErrorHour = peakTrafficHour(view.Trends.Traffic24h, func(point TrafficTrendPoint) int64 {
return point.ErrorCount
})
view.Peaks.BusiestNode = busiestDashboardNode(view.Nodes)
view.Peaks.RiskiestNode = riskiestDashboardNode(view.Nodes)
return view, nil
}
@@ -368,69 +242,3 @@ func activeHealthEventsByNode(events []*model.NodeHealthEvent) map[string][]*mod
}
return result
}
func severityWeight(severity string) int {
switch severity {
case NodeHealthSeverityCritical:
return 3
case NodeHealthSeverityWarning:
return 2
default:
return 1
}
}
func peakTrafficHour(points []TrafficTrendPoint, selector func(point TrafficTrendPoint) int64) DashboardPeakHour {
var result DashboardPeakHour
var maxValue int64 = -1
for _, point := range points {
value := selector(point)
if value <= maxValue {
continue
}
maxValue = value
result = DashboardPeakHour{
BucketStartedAt: point.BucketStartedAt,
RequestCount: point.RequestCount,
ErrorCount: point.ErrorCount,
}
}
return result
}
func busiestDashboardNode(nodes []DashboardNodeHealth) *DashboardPeakNode {
var selected *DashboardPeakNode
for _, node := range nodes {
candidate := &DashboardPeakNode{
NodeID: node.NodeID,
NodeName: node.Name,
RequestCount: node.RequestCount,
ErrorCount: node.ErrorCount,
CPUUsagePercent: node.CPUUsagePercent,
ActiveEventCount: node.ActiveEventCount,
OpenrestyStatus: node.OpenrestyStatus,
StorageUsagePercent: node.StorageUsagePercent,
}
if selected == nil || candidate.RequestCount > selected.RequestCount || (candidate.RequestCount == selected.RequestCount && candidate.ErrorCount > selected.ErrorCount) {
selected = candidate
}
}
return selected
}
func riskiestDashboardNode(nodes []DashboardNodeHealth) *DashboardPeakNode {
if len(nodes) == 0 {
return nil
}
node := nodes[0]
return &DashboardPeakNode{
NodeID: node.NodeID,
NodeName: node.Name,
RequestCount: node.RequestCount,
ErrorCount: node.ErrorCount,
CPUUsagePercent: node.CPUUsagePercent,
ActiveEventCount: node.ActiveEventCount,
OpenrestyStatus: node.OpenrestyStatus,
StorageUsagePercent: node.StorageUsagePercent,
}
}