summaryrefslogtreecommitdiff
path: root/internal/collector/parse.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-13 22:52:46 +0200
committerPaul Buetow <paul@buetow.org>2026-02-13 22:52:46 +0200
commitcd5a3614baab756a41d764b79308afeea93f12dd (patch)
treeefc8c31e8b162ca2121ba92c841322119e6d3b04 /internal/collector/parse.go
parentbf7c6ade292a6444877797c8d699d147aceb57cc (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.go102
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
+}