diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-13 22:52:46 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-13 22:52:46 +0200 |
| commit | cd5a3614baab756a41d764b79308afeea93f12dd (patch) | |
| tree | efc8c31e8b162ca2121ba92c841322119e6d3b04 /internal/collector/parse.go | |
| parent | bf7c6ade292a6444877797c8d699d147aceb57cc (diff) | |
Remove Perl version and build files; add .gitignore for .serena/
Amp-Thread-ID: https://ampcode.com/threads/T-019c58b3-06fb-733d-8fc1-f268fe7f70d5
Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'internal/collector/parse.go')
| -rw-r--r-- | internal/collector/parse.go | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/internal/collector/parse.go b/internal/collector/parse.go new file mode 100644 index 0000000..4f49456 --- /dev/null +++ b/internal/collector/parse.go @@ -0,0 +1,102 @@ +package collector + +import ( + "fmt" + "regexp" + "strconv" + "strings" +) + +// Mem key regex: "MemTotal: 12345 kB" -> MemTotal, 12345 +var memRegex = regexp.MustCompile(`^([A-Za-z0-9_]+):\s*(\d+)`) + +// ParseCPULine parses a /proc/stat line: "cpu 100 0 50 200 0 0 0 0 0 0" (name + 10 numbers). +// Older kernels may have fewer fields; missing ones are treated as 0. +func ParseCPULine(line string) (CPULine, error) { + fields := strings.Fields(line) + if len(fields) < 2 { + return CPULine{}, fmt.Errorf("cpu line too short: %q", line) + } + nums := make([]int64, 10) + for i := 1; i < len(fields) && i-1 < 10; i++ { + n, _ := strconv.ParseInt(fields[i], 10, 64) + nums[i-1] = n + } + return CPULine{ + Name: fields[0], + User: nums[0], + Nice: nums[1], + System: nums[2], + Idle: nums[3], + Iowait: nums[4], + IRQ: nums[5], + SoftIRQ: nums[6], + Steal: nums[7], + Guest: nums[8], + GuestNice: nums[9], + }, nil +} + +// ParseMemLine parses a /proc/meminfo line: "MemTotal: 123456 kB". +func ParseMemLine(line string) (MemLine, bool) { + m := memRegex.FindStringSubmatch(line) + if m == nil { + return MemLine{}, false + } + v, _ := strconv.ParseInt(m[2], 10, 64) + return MemLine{Key: m[1], Value: v}, true +} + +// ParseNetLine parses a protocol net line: "eth0:b=0;tb=0;p=0;tp=0 e=0;te=0;d=0;td=0". +// There may be a space between first block (b,tb,p,tp) and second (e,te,d,td). +func ParseNetLine(line string) (NetLine, error) { + parts := strings.SplitN(line, ":", 2) + if len(parts) != 2 { + return NetLine{}, fmt.Errorf("net line missing colon: %q", line) + } + net := NetLine{Iface: strings.TrimSpace(parts[0])} + rest := strings.ReplaceAll(parts[1], " ", ";") + for _, pair := range strings.Split(rest, ";") { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + continue + } + k := strings.TrimSpace(kv[0]) + v, _ := strconv.ParseInt(strings.TrimSpace(kv[1]), 10, 64) + switch k { + case "b": + net.B = v + case "tb": + net.Tb = v + case "p": + net.P = v + case "tp": + net.Tp = v + case "e": + net.E = v + case "te": + net.Te = v + case "d": + net.D = v + case "td": + net.Td = v + } + } + return net, nil +} + +// ParseLoadAvg parses "1.0;0.5;0.2" into Load1, Load5, Load15. +func ParseLoadAvg(line string) LoadAvg { + parts := strings.SplitN(line, ";", 3) + l := LoadAvg{} + if len(parts) > 0 { + l.Load1 = strings.TrimSpace(parts[0]) + } + if len(parts) > 1 { + l.Load5 = strings.TrimSpace(parts[1]) + } + if len(parts) > 2 { + l.Load15 = strings.TrimSpace(parts[2]) + } + return l +} |
