//go:build darwin package stats import ( "os/exec" "strconv" "strings" ) func (r *Reporter) SystemCPUPercent() float64 { idle, total, ok := readDarwinCPUSample() 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 readDarwinCPUSample() (idle, total uint64, ok bool) { out, err := exec.Command("sysctl", "-n", "kern.cp_time").Output() if err != nil { return 0, 0, false } return parseDarwinCPTimes(string(out)) } func parseDarwinCPTimes(raw string) (idle, total uint64, ok bool) { parts := strings.Fields(strings.TrimSpace(raw)) if len(parts) < 4 { return 0, 0, false } var values []uint64 for _, p := range parts { v, err := strconv.ParseUint(p, 10, 64) if err != nil { return 0, 0, false } values = append(values, v) } for _, v := range values { total += v } // user, nice, sys, idle[, intr] idle = values[3] return idle, total, true }