Status page per machine: CPU load, RAM and disk of the client, sampled by the agent only while the page is open and visible (one reading serves every open tab), plus a button that has the agent measure its link to the host: ping, down and up. Online/offline now comes from the control polls the hub holds open, so a dropped agent shows offline at once instead of 45 s later, and the dashboard keeps the status column live. A forward rule can be created "without ufw": the panel opens nothing in ufw for it and so revokes nothing when it is deleted. The checkbox is shown only while the ufw integration is on. Dashboard row actions are icons; a status action is added.
46 lines
978 B
Go
46 lines
978 B
Go
package agent
|
|
|
|
import (
|
|
"runtime"
|
|
"sync"
|
|
"syscall"
|
|
|
|
"github.com/x-grk/longpolling-remote-access/internal/proto"
|
|
)
|
|
|
|
// statMu serializes samples: the CPU figure is a delta against the last one.
|
|
var statMu sync.Mutex
|
|
|
|
// sysStat samples the machine's load. It costs nothing while nobody asks: the
|
|
// panel requests it only for an open status page.
|
|
func sysStat() (proto.SysStatResult, error) {
|
|
statMu.Lock()
|
|
defer statMu.Unlock()
|
|
res := proto.SysStatResult{NCPU: runtime.NumCPU()}
|
|
cpu, err := cpuPercent()
|
|
if err != nil {
|
|
return res, err
|
|
}
|
|
res.CPU = cpu
|
|
if res.MemTotal, res.MemUsed, err = memUsage(); err != nil {
|
|
return res, err
|
|
}
|
|
var fs syscall.Statfs_t
|
|
if err := syscall.Statfs("/", &fs); err != nil {
|
|
return res, err
|
|
}
|
|
res.DiskTotal = uint64(fs.Blocks) * uint64(fs.Bsize)
|
|
res.DiskFree = uint64(fs.Bavail) * uint64(fs.Bsize)
|
|
return res, nil
|
|
}
|
|
|
|
func clampPercent(v float64) float64 {
|
|
if v < 0 {
|
|
return 0
|
|
}
|
|
if v > 100 {
|
|
return 100
|
|
}
|
|
return v
|
|
}
|