It watches its node's keys of mesh-host_data instead of composing every module's items from about 370 resolved keys per round, so a round no longer takes 30 to 45 minutes across the tunnel and a manifest its mesh-sdk cannot judge no longer silences it. A changed key measures its module at once; each round writes how far it got to the per-node state rounds, said by disk_round. Pins mesh-sdk feat/data-items. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
61 lines
2.5 KiB
Go
61 lines
2.5 KiB
Go
// The disk-load module's Go bundle (novox/hq ADR 0188, ADR 0193, issue 312): a process the node's
|
|
// runtime launches and speaks MCP over stdio to. It reads the machine's storage load from /proc and
|
|
// /sys — iowait, pressure stall, each disk's busy share, throughput, IOPS, wait and queue depth, the
|
|
// filesystems' space and the processes doing the I/O — and changes nothing of the machine.
|
|
//
|
|
// It also measures the data items the modules of its node declare (ADR 0233) and keeps each reading and the item's
|
|
// seven-day peak as its own state `readings` (ADR 0571 clause 3). It learns the items from the node-engine's state data,
|
|
// watching its own node's keys, and composes nothing (ADR 0577 clause 2); each round says how far it got in its state
|
|
// `rounds` (clause 3).
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
|
"git.novox.be/novox/mesh-sdk/go/announce"
|
|
)
|
|
|
|
func logf(format string, args ...any) { fmt.Fprintf(os.Stderr, "[disk-load] "+format+"\n", args...) }
|
|
|
|
// Kept is every state disk-load keeps, as it announces them: the readings, readable by restic, nfs-server, mounts and
|
|
// the self-check (their manifests' `reads`; checks/readable holds it), and the rounds, its own tools' alone.
|
|
var Kept = []announce.State{{Name: StateReadings, Readable: true}, {Name: StateRounds}}
|
|
|
|
func main() {
|
|
if err := stdio.Keeps(Kept...); err != nil {
|
|
logf("%v", err)
|
|
os.Exit(1)
|
|
}
|
|
node := os.Getenv("MESH_NODE")
|
|
watched := &Watched{Node: node}
|
|
k := &Keeper{Node: node, Store: busStore{StateReadings}, Rounds: busStore{StateRounds}, Say: logf,
|
|
Measurer: Measurer{Run: RootRunner, Now: time.Now}, Items: watched.All}
|
|
if node != "" {
|
|
every := time.Hour
|
|
if d, err := time.ParseDuration(os.Getenv("MESH_DISK_MEASURE_EVERY")); err == nil && d >= time.Minute {
|
|
every = d
|
|
}
|
|
ctx := context.Background()
|
|
go k.Work(ctx)
|
|
go func() {
|
|
<-stdio.Served() // the runtime's channel first: a watch is asked through it
|
|
if err := watched.Follow(k); err != nil {
|
|
logf("this machine's keys of the node-engine's data items cannot be watched, and nothing is measured: %v", err)
|
|
return
|
|
}
|
|
logf("watching this machine's keys of the node-engine's data items")
|
|
}()
|
|
go k.Loop(ctx, every, 3*time.Minute)
|
|
}
|
|
tools := append(Tools(Here()), ReadingTools(k)...)
|
|
// An empty name serves as the module the runtime names (MESH_SERVED_MODULE): disk-load.
|
|
if err := stdio.Serve("", tools); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|