diff --git a/bin/status-go b/bin/status-go index 34c1573..c1199b3 100755 Binary files a/bin/status-go and b/bin/status-go differ diff --git a/cmd/status/metrics.go b/cmd/status/metrics.go index c00c24f..50449ca 100644 --- a/cmd/status/metrics.go +++ b/cmd/status/metrics.go @@ -1,6 +1,7 @@ package main import ( + "bufio" "context" "encoding/json" "errors" @@ -365,18 +366,37 @@ func formatUptime(secs uint64) string { } func collectCPU() (CPUStatus, error) { + counts, countsErr := cpu.Counts(false) + if countsErr != nil || counts == 0 { + counts = runtime.NumCPU() + } + + logical, logicalErr := cpu.Counts(true) + if logicalErr != nil || logical == 0 { + logical = runtime.NumCPU() + } + if logical <= 0 { + logical = 1 + } + percents, err := cpu.Percent(cpuSampleInterval, true) - if err != nil { - return CPUStatus{}, err + var totalPercent float64 + if err != nil || len(percents) == 0 { + fallbackUsage, fallbackPerCore, fallbackErr := fallbackCPUUtilization(logical) + if fallbackErr != nil { + if err != nil { + return CPUStatus{}, err + } + return CPUStatus{}, fallbackErr + } + totalPercent = fallbackUsage + percents = fallbackPerCore + } else { + for _, v := range percents { + totalPercent += v + } + totalPercent /= float64(len(percents)) } - if len(percents) == 0 { - return CPUStatus{}, errors.New("cannot read CPU utilization") - } - totalPercent := 0.0 - for _, v := range percents { - totalPercent += v - } - totalPercent /= float64(len(percents)) loadStats, loadErr := load.Avg() var loadAvg load.AvgStat @@ -389,16 +409,6 @@ func collectCPU() (CPUStatus, error) { } } - counts, countsErr := cpu.Counts(false) - if countsErr != nil || counts == 0 { - counts = runtime.NumCPU() - } - - logical, logicalErr := cpu.Counts(true) - if logicalErr != nil || logical == 0 { - logical = runtime.NumCPU() - } - return CPUStatus{ Usage: totalPercent, PerCore: percents, @@ -466,6 +476,60 @@ func fallbackLoadAvgFromUptime() (load.AvgStat, error) { }, nil } +func fallbackCPUUtilization(logical int) (float64, []float64, error) { + if logical <= 0 { + logical = runtime.NumCPU() + } + if logical <= 0 { + logical = 1 + } + + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + + out, err := runCmd(ctx, "ps", "-Aceo", "pcpu") + if err != nil { + return 0, nil, err + } + + scanner := bufio.NewScanner(strings.NewReader(out)) + total := 0.0 + lineIndex := 0 + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line == "" { + continue + } + lineIndex++ + if lineIndex == 1 && (strings.Contains(strings.ToLower(line), "cpu") || strings.Contains(line, "%")) { + continue + } + + val, parseErr := strconv.ParseFloat(line, 64) + if parseErr != nil { + continue + } + total += val + } + if scanErr := scanner.Err(); scanErr != nil { + return 0, nil, scanErr + } + + maxTotal := float64(logical * 100) + if total < 0 { + total = 0 + } else if total > maxTotal { + total = maxTotal + } + + perCore := make([]float64, logical) + avg := total / float64(logical) + for i := range perCore { + perCore[i] = avg + } + return total, perCore, nil +} + func collectMemory() (MemoryStatus, error) { vm, err := mem.VirtualMemory() if err != nil { diff --git a/mole b/mole index 74e29dd..5f0084c 100755 --- a/mole +++ b/mole @@ -22,7 +22,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/lib/common.sh" # Version info -VERSION="1.10.7" +VERSION="1.10.8" MOLE_TAGLINE="can dig deep to clean your Mac." # Check if Touch ID is already configured