Backend stability and security improvements: * internal/util/ — common RandomHex helper, removed 3 duplicates * ESL: deduplicated readMessage (locked/unlocked), net.JoinHostPort for IPv6 * AMI: synchronous reconnect() in readEventsLoop, net.JoinHostPort for IPv6 * Auth: /api/auth/refresh accepts Authorization header only (no ?token=) * decodeJSON: http.MaxBytesReader(1<<20) body limit * Trunks: gatewayParams() uses configured ESL.GatewayPrefix * Config: jwt_secret_env env-var fallback * FSCollector: time.After → time.NewTimer with defer Stop * Monitoring: Prometheus counters (route_requests, nodes_total/healthy, uptime) * go fmt pass across all internal/ packages
85 lines
1.8 KiB
Go
85 lines
1.8 KiB
Go
package agent
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// nowTS возвращает текущий unix timestamp.
|
|
func nowTS() int64 {
|
|
return time.Now().Unix()
|
|
}
|
|
|
|
// SystemStats содержит системные метрики (CPU, load).
|
|
type SystemStats struct {
|
|
Load1 float64 // load average 1m
|
|
Load5 float64 // load average 5m
|
|
Load15 float64 // load average 15m
|
|
IdleCPU float64 // процент простоя CPU
|
|
}
|
|
|
|
// CollectSystem собирает системные метрики из /proc.
|
|
func CollectSystem() *SystemStats {
|
|
load1, load5, load15 := loadAvg()
|
|
return &SystemStats{
|
|
Load1: load1,
|
|
Load5: load5,
|
|
Load15: load15,
|
|
IdleCPU: cpuIdle(),
|
|
}
|
|
}
|
|
|
|
// loadAvg читает /proc/loadavg.
|
|
func loadAvg() (float64, float64, float64) {
|
|
data, err := os.ReadFile("/proc/loadavg")
|
|
if err != nil {
|
|
return 0, 0, 0
|
|
}
|
|
parts := strings.Fields(string(data))
|
|
if len(parts) < 3 {
|
|
return 0, 0, 0
|
|
}
|
|
load1, _ := strconv.ParseFloat(parts[0], 64)
|
|
load5, _ := strconv.ParseFloat(parts[1], 64)
|
|
load15, _ := strconv.ParseFloat(parts[2], 64)
|
|
return load1, load5, load15
|
|
}
|
|
|
|
// cpuIdle вычисляет процент простоя CPU из /proc/stat.
|
|
func cpuIdle() float64 {
|
|
file, err := os.Open("/proc/stat")
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
defer file.Close()
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
if !strings.HasPrefix(line, "cpu ") {
|
|
continue
|
|
}
|
|
fields := strings.Fields(line)
|
|
if len(fields) < 8 {
|
|
return 0
|
|
}
|
|
// cpu user nice system idle iowait irq softirq steal ...
|
|
var total, idle float64
|
|
for i, f := range fields[1:] {
|
|
val, _ := strconv.ParseFloat(f, 64)
|
|
total += val
|
|
if i == 3 || i == 4 { // idle + iowait
|
|
idle += val
|
|
}
|
|
}
|
|
if total > 0 {
|
|
return (idle / total) * 100.0
|
|
}
|
|
return 0
|
|
}
|
|
return 0
|
|
}
|