The full switch: Monitors and Disks read only the sensor API; /api/metrics retired
- stock Monitors modules fed by one sensor stream, the catalog and one batch of histories (GET /api/sensors/history?ids=…), through sampleAdapter.ts - the stream closes while the page is hidden and refills its curves on return - Disks tab live rates from the stream - new sensors: hamlab.sample_interval, ups.last_event - stream: asking for about the sampling rate means every sample - NUT runtime rounded at the source Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
f01175ceca
commit
4ddf10be51
@@ -136,16 +136,6 @@ type Sample struct {
|
||||
fsT, upsT int64 // when the slow sections were really read; sensors report these, not T
|
||||
}
|
||||
|
||||
// Series is the compact history the UI seeds its sparklines from.
|
||||
type Series struct {
|
||||
T []int64 `json:"t"`
|
||||
CPU []float64 `json:"cpu"`
|
||||
Mem []uint64 `json:"mem"`
|
||||
Net map[string]map[string][]float64 `json:"net"` // iface -> {rx,tx}
|
||||
Disk map[string]map[string][]float64 `json:"disk"` // name -> {r,w,u}
|
||||
Temp map[string][]float64 `json:"temp"` // "chip/label" -> °C
|
||||
}
|
||||
|
||||
type Collector struct {
|
||||
mu sync.RWMutex
|
||||
ring []Sample
|
||||
@@ -236,44 +226,6 @@ func (c *Collector) Latest() (Sample, bool) {
|
||||
return c.ring[len(c.ring)-1], true
|
||||
}
|
||||
|
||||
func (c *Collector) History() Series {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
n := len(c.ring)
|
||||
s := Series{T: make([]int64, n), CPU: make([]float64, n), Mem: make([]uint64, n),
|
||||
Net: map[string]map[string][]float64{}, Disk: map[string]map[string][]float64{}, Temp: map[string][]float64{}}
|
||||
series := func(m map[string]map[string][]float64, key string, keys ...string) map[string][]float64 {
|
||||
v, ok := m[key]
|
||||
if !ok {
|
||||
v = map[string][]float64{}
|
||||
for _, k := range keys {
|
||||
v[k] = make([]float64, n)
|
||||
}
|
||||
m[key] = v
|
||||
}
|
||||
return v
|
||||
}
|
||||
for i, smp := range c.ring {
|
||||
s.T[i], s.CPU[i], s.Mem[i] = smp.T, smp.CPU, smp.Mem.Used
|
||||
for _, x := range smp.Net {
|
||||
v := series(s.Net, x.Iface, "rx", "tx")
|
||||
v["rx"][i], v["tx"][i] = x.RxBps, x.TxBps
|
||||
}
|
||||
for _, d := range smp.Disks {
|
||||
v := series(s.Disk, d.Name, "r", "w", "u")
|
||||
v["r"][i], v["w"][i], v["u"][i] = d.ReadBps, d.WriteBps, d.UtilPct
|
||||
}
|
||||
for _, t := range smp.Temps {
|
||||
k := t.Chip + "/" + t.Label
|
||||
if s.Temp[k] == nil {
|
||||
s.Temp[k] = make([]float64, n)
|
||||
}
|
||||
s.Temp[k][i] = t.C
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// ---- sampling ----
|
||||
|
||||
func (c *Collector) sample() {
|
||||
@@ -853,7 +805,7 @@ func upsNUT() *UPS {
|
||||
u.InV = leadingNum(kv["input.voltage"])
|
||||
u.OutV = leadingNum(kv["output.voltage"])
|
||||
u.BatteryPct = leadingNum(kv["battery.charge"])
|
||||
u.RuntimeMin = leadingNum(kv["battery.runtime"]) / 60
|
||||
u.RuntimeMin = round1(leadingNum(kv["battery.runtime"]) / 60)
|
||||
u.LoadPct = leadingNum(kv["ups.load"])
|
||||
u.LoadW = leadingNum(kv["ups.realpower"])
|
||||
if u.LoadW == 0 {
|
||||
|
||||
Reference in New Issue
Block a user