mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-17 22:26:58 +00:00
183 lines
4.4 KiB
Go
183 lines
4.4 KiB
Go
package display
|
|
|
|
import (
|
|
"io"
|
|
"time"
|
|
|
|
"github.com/DeBrosOfficial/network/pkg/cli/monitor"
|
|
"github.com/DeBrosOfficial/network/pkg/cli/production/report"
|
|
)
|
|
|
|
type fullReport struct {
|
|
Meta struct {
|
|
Environment string `json:"environment"`
|
|
CollectedAt time.Time `json:"collected_at"`
|
|
DurationSec float64 `json:"duration_seconds"`
|
|
NodeCount int `json:"node_count"`
|
|
HealthyCount int `json:"healthy_count"`
|
|
FailedCount int `json:"failed_count"`
|
|
} `json:"meta"`
|
|
Summary struct {
|
|
RQLiteLeader string `json:"rqlite_leader"`
|
|
RQLiteQuorum string `json:"rqlite_quorum"`
|
|
WGMeshStatus string `json:"wg_mesh_status"`
|
|
ServiceHealth string `json:"service_health"`
|
|
CriticalAlerts int `json:"critical_alerts"`
|
|
WarningAlerts int `json:"warning_alerts"`
|
|
} `json:"summary"`
|
|
Alerts []monitor.Alert `json:"alerts"`
|
|
Nodes []nodeEntry `json:"nodes"`
|
|
}
|
|
|
|
type nodeEntry struct {
|
|
Host string `json:"host"`
|
|
Role string `json:"role"`
|
|
Status string `json:"status"` // "ok", "unreachable", "degraded"
|
|
Report *report.NodeReport `json:"report,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// FullReport outputs the LLM-optimized JSON report to w.
|
|
func FullReport(snap *monitor.ClusterSnapshot, w io.Writer) error {
|
|
fr := fullReport{}
|
|
|
|
// Meta
|
|
fr.Meta.Environment = snap.Environment
|
|
fr.Meta.CollectedAt = snap.CollectedAt
|
|
fr.Meta.DurationSec = snap.Duration.Seconds()
|
|
fr.Meta.NodeCount = snap.TotalCount()
|
|
fr.Meta.HealthyCount = snap.HealthyCount()
|
|
fr.Meta.FailedCount = len(snap.Failed())
|
|
|
|
// Summary
|
|
fr.Summary.RQLiteLeader = findRQLiteLeader(snap)
|
|
fr.Summary.RQLiteQuorum = computeQuorumStatus(snap)
|
|
fr.Summary.WGMeshStatus = computeWGMeshStatus(snap)
|
|
fr.Summary.ServiceHealth = computeServiceHealth(snap)
|
|
|
|
crit, warn := countAlerts(snap.Alerts)
|
|
fr.Summary.CriticalAlerts = crit
|
|
fr.Summary.WarningAlerts = warn
|
|
|
|
// Alerts
|
|
fr.Alerts = snap.Alerts
|
|
|
|
// Build set of hosts with critical alerts for "degraded" detection
|
|
criticalHosts := map[string]bool{}
|
|
for _, a := range snap.Alerts {
|
|
if a.Severity == monitor.AlertCritical && a.Node != "" && a.Node != "cluster" {
|
|
criticalHosts[a.Node] = true
|
|
}
|
|
}
|
|
|
|
// Nodes
|
|
for _, cs := range snap.Nodes {
|
|
ne := nodeEntry{
|
|
Host: cs.Node.Host,
|
|
Role: cs.Node.Role,
|
|
}
|
|
if cs.Error != nil {
|
|
ne.Status = "unreachable"
|
|
ne.Error = cs.Error.Error()
|
|
} else if cs.Report != nil {
|
|
if criticalHosts[cs.Node.Host] {
|
|
ne.Status = "degraded"
|
|
} else {
|
|
ne.Status = "ok"
|
|
}
|
|
ne.Report = cs.Report
|
|
} else {
|
|
ne.Status = "unreachable"
|
|
}
|
|
fr.Nodes = append(fr.Nodes, ne)
|
|
}
|
|
|
|
return writeJSON(w, fr)
|
|
}
|
|
|
|
// findRQLiteLeader returns the host of the RQLite leader, or "none".
|
|
func findRQLiteLeader(snap *monitor.ClusterSnapshot) string {
|
|
for _, cs := range snap.Nodes {
|
|
if cs.Report != nil && cs.Report.RQLite != nil && cs.Report.RQLite.RaftState == "Leader" {
|
|
return cs.Node.Host
|
|
}
|
|
}
|
|
return "none"
|
|
}
|
|
|
|
// computeQuorumStatus returns "ok", "degraded", or "lost".
|
|
func computeQuorumStatus(snap *monitor.ClusterSnapshot) string {
|
|
total := 0
|
|
responsive := 0
|
|
for _, cs := range snap.Nodes {
|
|
if cs.Report != nil && cs.Report.RQLite != nil {
|
|
total++
|
|
if cs.Report.RQLite.Responsive {
|
|
responsive++
|
|
}
|
|
}
|
|
}
|
|
if total == 0 {
|
|
return "unknown"
|
|
}
|
|
quorum := (total / 2) + 1
|
|
if responsive >= quorum {
|
|
return "ok"
|
|
}
|
|
if responsive > 0 {
|
|
return "degraded"
|
|
}
|
|
return "lost"
|
|
}
|
|
|
|
// computeWGMeshStatus returns "ok", "degraded", or "down".
|
|
func computeWGMeshStatus(snap *monitor.ClusterSnapshot) string {
|
|
totalWG := 0
|
|
upCount := 0
|
|
for _, cs := range snap.Nodes {
|
|
if cs.Report != nil && cs.Report.WireGuard != nil {
|
|
totalWG++
|
|
if cs.Report.WireGuard.InterfaceUp {
|
|
upCount++
|
|
}
|
|
}
|
|
}
|
|
if totalWG == 0 {
|
|
return "unknown"
|
|
}
|
|
if upCount == totalWG {
|
|
return "ok"
|
|
}
|
|
if upCount > 0 {
|
|
return "degraded"
|
|
}
|
|
return "down"
|
|
}
|
|
|
|
// computeServiceHealth returns "ok", "degraded", or "critical".
|
|
func computeServiceHealth(snap *monitor.ClusterSnapshot) string {
|
|
totalSvc := 0
|
|
failedSvc := 0
|
|
for _, cs := range snap.Nodes {
|
|
if cs.Report == nil || cs.Report.Services == nil {
|
|
continue
|
|
}
|
|
for _, svc := range cs.Report.Services.Services {
|
|
totalSvc++
|
|
if svc.ActiveState == "failed" {
|
|
failedSvc++
|
|
}
|
|
}
|
|
}
|
|
if totalSvc == 0 {
|
|
return "unknown"
|
|
}
|
|
if failedSvc == 0 {
|
|
return "ok"
|
|
}
|
|
if failedSvc < totalSvc/2 {
|
|
return "degraded"
|
|
}
|
|
return "critical"
|
|
}
|