Go service (nasmon/) plus nfpm packaging (packaging/), carried over from the home_nas monorepo. Adds rpm packaging alongside the existing deb build (Fedora/RHEL/Rocky dependency names via nfpm overrides, per-format systemd unit path, dpkg+rpm-compatible maintainer scripts) and a Gitea Actions workflow that builds both formats on every push. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
76 lines
1.6 KiB
Go
76 lines
1.6 KiB
Go
// Package collect reads system state from /proc, /sys and CLI tools.
|
|
package collect
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type CPU struct {
|
|
UsagePct float64 `json:"usage_pct"`
|
|
Cores int `json:"cores"`
|
|
Load [3]float64 `json:"load"`
|
|
}
|
|
|
|
type cpuTimes struct{ idle, total uint64 }
|
|
|
|
// CPUSampler keeps the previous /proc/stat reading to compute usage deltas.
|
|
type CPUSampler struct {
|
|
prev cpuTimes
|
|
init bool
|
|
}
|
|
|
|
func (s *CPUSampler) Sample() (CPU, error) {
|
|
b, err := os.ReadFile("/proc/stat")
|
|
if err != nil {
|
|
return CPU{}, err
|
|
}
|
|
cur, err := parseProcStat(b)
|
|
if err != nil {
|
|
return CPU{}, err
|
|
}
|
|
c := CPU{Cores: runtime.NumCPU()}
|
|
if s.init && cur.total > s.prev.total {
|
|
dt := float64(cur.total - s.prev.total)
|
|
di := float64(cur.idle - s.prev.idle)
|
|
c.UsagePct = 100 * (1 - di/dt)
|
|
}
|
|
s.prev, s.init = cur, true
|
|
if lb, err := os.ReadFile("/proc/loadavg"); err == nil {
|
|
f := strings.Fields(string(lb))
|
|
for i := 0; i < 3 && i < len(f); i++ {
|
|
c.Load[i], _ = strconv.ParseFloat(f[i], 64)
|
|
}
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
// parseProcStat returns idle and total jiffies from the aggregate "cpu" line.
|
|
func parseProcStat(b []byte) (cpuTimes, error) {
|
|
sc := bufio.NewScanner(bytes.NewReader(b))
|
|
for sc.Scan() {
|
|
f := strings.Fields(sc.Text())
|
|
if len(f) < 5 || f[0] != "cpu" {
|
|
continue
|
|
}
|
|
var t cpuTimes
|
|
for i, v := range f[1:] {
|
|
n, err := strconv.ParseUint(v, 10, 64)
|
|
if err != nil {
|
|
return t, err
|
|
}
|
|
t.total += n
|
|
if i == 3 || i == 4 { // idle + iowait
|
|
t.idle += n
|
|
}
|
|
}
|
|
return t, nil
|
|
}
|
|
return cpuTimes{}, fmt.Errorf("no cpu line in /proc/stat")
|
|
}
|