fix for overview panel
This commit is contained in:
parent
21d8e91756
commit
d16f34070d
21 changed files with 920 additions and 40 deletions
79
internal/hoststats/cpu_unix.go
Normal file
79
internal/hoststats/cpu_unix.go
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
//go:build !windows
|
||||
|
||||
package hoststats
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// cpuSampler computes CPU busy% from successive cumulative /proc/stat
|
||||
// snapshots. The kernel's counters are monotonic totals since boot, so a
|
||||
// single read can't give a percentage -- only the delta between two reads
|
||||
// separated by real time can. sampleOnce (its only caller) already runs on
|
||||
// a fixed poll interval, so that interval doubles as the sampling window;
|
||||
// no internal sleep needed.
|
||||
type cpuSampler struct {
|
||||
prevTotal uint64
|
||||
prevIdle uint64
|
||||
have bool
|
||||
}
|
||||
|
||||
func (c *cpuSampler) sample() float64 {
|
||||
total, idle, err := readProcStatCPU()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
if !c.have {
|
||||
c.prevTotal, c.prevIdle = total, idle
|
||||
c.have = true
|
||||
return 0
|
||||
}
|
||||
deltaTotal := total - c.prevTotal
|
||||
deltaIdle := idle - c.prevIdle
|
||||
c.prevTotal, c.prevIdle = total, idle
|
||||
if deltaTotal == 0 {
|
||||
return 0
|
||||
}
|
||||
pct := (1 - float64(deltaIdle)/float64(deltaTotal)) * 100
|
||||
switch {
|
||||
case pct < 0:
|
||||
pct = 0
|
||||
case pct > 100:
|
||||
pct = 100
|
||||
}
|
||||
return pct
|
||||
}
|
||||
|
||||
// readProcStatCPU parses the aggregate "cpu " line: user nice system idle
|
||||
// iowait irq softirq steal guest guest_nice (guest/guest_nice already
|
||||
// double-counted inside user/nice on Linux, per `man proc`, so they're not
|
||||
// added again here). idle = idle + iowait, matching the convention `top`
|
||||
// and most load calculators use.
|
||||
func readProcStatCPU() (total, idle uint64, err error) {
|
||||
data, err := os.ReadFile("/proc/stat")
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
line, _, _ := strings.Cut(string(data), "\n")
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 5 || fields[0] != "cpu" {
|
||||
return 0, 0, fmt.Errorf("hoststats: unexpected /proc/stat format")
|
||||
}
|
||||
values := make([]uint64, 0, len(fields)-1)
|
||||
for _, f := range fields[1:] {
|
||||
v, err := strconv.ParseUint(f, 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
values = append(values, v)
|
||||
total += v
|
||||
}
|
||||
idle = values[3]
|
||||
if len(values) > 4 {
|
||||
idle += values[4] // iowait
|
||||
}
|
||||
return total, idle, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue