Improve service checks and system health details
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -13,14 +14,23 @@ type SystemIssue struct {
|
||||
Unit string `json:"unit"`
|
||||
Priority string `json:"priority"`
|
||||
Message string `json:"message"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
type SystemHealthMetrics struct {
|
||||
Available bool `json:"available"`
|
||||
FailedUnits int `json:"failedUnits"`
|
||||
KernelErrors int `json:"kernelErrors"`
|
||||
SystemErrors int `json:"systemErrors"`
|
||||
Issues []SystemIssue `json:"issues"`
|
||||
CheckedAt int64 `json:"checkedAt"`
|
||||
Available bool `json:"available"`
|
||||
FailedUnits int `json:"failedUnits"`
|
||||
KernelErrors int `json:"kernelErrors"`
|
||||
SystemErrors int `json:"systemErrors"`
|
||||
Issues []SystemIssue `json:"issues"`
|
||||
FailedServices []FailedService `json:"failedServices"`
|
||||
CheckedAt int64 `json:"checkedAt"`
|
||||
}
|
||||
type FailedService struct {
|
||||
Unit string `json:"unit"`
|
||||
Load string `json:"load"`
|
||||
Active string `json:"active"`
|
||||
State string `json:"state"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
type systemHealthCollector struct {
|
||||
mu sync.RWMutex
|
||||
@@ -56,12 +66,27 @@ func (c *systemHealthCollector) refresh() {
|
||||
m.Available = true
|
||||
if out, err := exec.Command("systemctl", "--failed", "--no-legend", "--plain").Output(); err == nil {
|
||||
for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
|
||||
if strings.TrimSpace(line) != "" {
|
||||
m.FailedUnits++
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 4 {
|
||||
continue
|
||||
}
|
||||
unit := strings.TrimPrefix(fields[0], "●")
|
||||
offset := 1
|
||||
if unit == "" && len(fields) > 4 {
|
||||
unit = fields[1]
|
||||
offset = 2
|
||||
}
|
||||
description := ""
|
||||
if len(fields) > offset+3 {
|
||||
description = strings.Join(fields[offset+3:], " ")
|
||||
}
|
||||
m.FailedServices = append(m.FailedServices, FailedService{Unit: unit, Load: fields[offset], Active: fields[offset+1], State: fields[offset+2], Description: description})
|
||||
m.FailedUnits++
|
||||
}
|
||||
}
|
||||
out, _ := exec.Command("journalctl", "--since", "24 hours ago", "-p", "0..3", "--no-pager", "-o", "short-unix", "-n", "100").Output()
|
||||
pidPattern := regexp.MustCompile(`\[[0-9]+\]`)
|
||||
grouped := map[string]int{}
|
||||
for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
|
||||
f := strings.Fields(line)
|
||||
if len(f) < 2 {
|
||||
@@ -71,8 +96,15 @@ func (c *systemHealthCollector) refresh() {
|
||||
sec, _ := strconv.ParseFloat(raw, 64)
|
||||
unit := strings.TrimSuffix(f[1], ":")
|
||||
message := strings.Join(f[2:], " ")
|
||||
issue := SystemIssue{Time: int64(sec), Unit: unit, Priority: "error", Message: message}
|
||||
m.Issues = append(m.Issues, issue)
|
||||
normalized := pidPattern.ReplaceAllString(message, "[*]")
|
||||
key := unit + "\x00" + normalized
|
||||
if index, ok := grouped[key]; ok {
|
||||
m.Issues[index].Count++
|
||||
m.Issues[index].Time = int64(sec)
|
||||
} else {
|
||||
grouped[key] = len(m.Issues)
|
||||
m.Issues = append(m.Issues, SystemIssue{Time: int64(sec), Unit: unit, Priority: "error", Message: normalized, Count: 1})
|
||||
}
|
||||
m.SystemErrors++
|
||||
if strings.Contains(strings.ToLower(unit), "kernel") {
|
||||
m.KernelErrors++
|
||||
|
||||
Reference in New Issue
Block a user