Files
nasmon/internal/history/ring.go
T
a.gritsenkoandClaude Sonnet 5 09159a5f31 Initial import: nasmon health monitor, split out of home_nas
Go service (nasmon/) plus nfpm packaging (packaging/), carried over from
the home_nas monorepo. Adds rpm packaging alongside the existing deb
build (Fedora/RHEL/Rocky dependency names via nfpm overrides, per-format
systemd unit path, dpkg+rpm-compatible maintainer scripts) and a Gitea
Actions workflow that builds both formats on every push.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 10:24:34 +03:00

60 lines
1.2 KiB
Go

// Package history keeps a fixed-size in-memory ring of metric samples.
package history
import (
"sync"
"time"
)
type Sample struct {
T int64 `json:"t"` // unix seconds
CPU float64 `json:"cpu"`
MemUsed uint64 `json:"mem_used"`
ARC uint64 `json:"arc"`
CPUTemp float64 `json:"cpu_temp"`
}
type Ring struct {
mu sync.RWMutex
buf []Sample
head int
n int
}
func New(size int) *Ring { return &Ring{buf: make([]Sample, size)} }
func (r *Ring) Add(s Sample) {
r.mu.Lock()
defer r.mu.Unlock()
r.buf[r.head] = s
r.head = (r.head + 1) % len(r.buf)
if r.n < len(r.buf) {
r.n++
}
}
// Since returns samples newer than t in chronological order, thinned to at
// most maxPoints entries.
func (r *Ring) Since(t time.Time, maxPoints int) []Sample {
r.mu.RLock()
defer r.mu.RUnlock()
ts := t.Unix()
out := make([]Sample, 0, r.n)
start := (r.head - r.n + len(r.buf)) % len(r.buf)
for i := 0; i < r.n; i++ {
s := r.buf[(start+i)%len(r.buf)]
if s.T >= ts {
out = append(out, s)
}
}
if maxPoints > 0 && len(out) > maxPoints {
step := (len(out) + maxPoints - 1) / maxPoints
thin := out[:0:0]
for i := 0; i < len(out); i += step {
thin = append(thin, out[i])
}
out = thin
}
return out
}