//go:build linux package stats import ( "bufio" "os" "strconv" "strings" ) func (r *Reporter) SystemCPUPercent() float64 { idle, total, ok := readProcStatCPUSample() if !ok { return 0 } r.mu.Lock() defer r.mu.Unlock() if !r.hasSample { r.lastIdle = idle r.lastTotal = total r.hasSample = true return 0 } idleDelta := float64(idle - r.lastIdle) totalDelta := float64(total - r.lastTotal) r.lastIdle = idle r.lastTotal = total return cpuBusyPercentFromDeltas(idleDelta, totalDelta) } func readProcStatCPUSample() (idle, total uint64, ok bool) { f, err := os.Open("/proc/stat") if err != nil { return 0, 0, false } defer f.Close() sc := bufio.NewScanner(f) if !sc.Scan() { return 0, 0, false } return parseProcStatCPU(sc.Text()) } func parseProcStatCPU(line string) (idle, total uint64, ok bool) { fields := strings.Fields(line) if len(fields) < 5 || fields[0] != "cpu" { return 0, 0, false } var values []uint64 for _, f := range fields[1:] { v, err := strconv.ParseUint(f, 10, 64) if err != nil { return 0, 0, false } values = append(values, v) } for _, v := range values { total += v } // idle + iowait (index 3 and 4 when present) idle = values[3] if len(values) > 4 { idle += values[4] } return idle, total, true }