//go:build linux package beach import ( "os" "runtime" "sync" "syscall" "time" ) var ( cpuMu sync.Mutex lastCPU cpuTimes lastAt time.Time lastPct float64 ) func readFile(p string) string { b, _ := os.ReadFile(p); return string(b) } // CollectHost reads /proc. CPU use is the change since the previous call; the // first call takes a short sample of its own. func CollectHost() Host { h := Host{Supported: true, CPUs: runtime.NumCPU(), Disks: []Filesystem{}} h.Hostname, _ = os.Hostname() h.Uptime = parseUptime(readFile("/proc/uptime")) h.Load = parseLoad(readFile("/proc/loadavg")) h.MemTotal, h.MemUsed, h.SwapTotal, h.SwapUsed = parseMeminfo(readFile("/proc/meminfo")) cpuMu.Lock() if now, err := parseCPU(readFile("/proc/stat")); err == nil { if lastAt.IsZero() { time.Sleep(250 * time.Millisecond) if n2, err := parseCPU(readFile("/proc/stat")); err == nil { lastPct, now = cpuPct(now, n2), n2 } lastCPU, lastAt = now, time.Now() } else if time.Since(lastAt) > 500*time.Millisecond { lastPct = cpuPct(lastCPU, now) lastCPU, lastAt = now, time.Now() } } h.CPUPct = lastPct cpuMu.Unlock() for _, m := range realMounts(readFile("/proc/mounts")) { var st syscall.Statfs_t if syscall.Statfs(m, &st) == nil && st.Blocks > 0 { bs := uint64(st.Bsize) h.Disks = append(h.Disks, Filesystem{Mount: m, Total: st.Blocks * bs, Used: (st.Blocks - st.Bfree) * bs}) } } return h }