Improve service checks and system health details

This commit is contained in:
Maxim
2026-08-01 12:21:26 +03:00
parent 980f69cf8f
commit d3fbbf2a6b
6 changed files with 184 additions and 67 deletions

View File

@@ -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++