94 lines
3.5 KiB
Go
94 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
|
"git.novox.be/novox/mesh-sdk/go/health"
|
|
)
|
|
|
|
// ReadingTools are the tools over the state `readings`: every key, one key, how full the state is, and one item
|
|
// measured now (a module's tools are its command line).
|
|
func ReadingTools(k *Keeper) []stdio.Tool {
|
|
return []stdio.Tool{
|
|
{
|
|
Name: "disk_readings",
|
|
Description: "The data readings disk-load keeps for this machine's data items (ADR 0233, ADR 0571 clause 3): every key " +
|
|
"`<node>.<module>.<item>` with its size, newest write, measured-at, precision and seven-day peak, or one key with " +
|
|
"all it holds when `key` is given; and how full the state is: keys kept, their bytes, and the cap the bus puts on " +
|
|
"a state (none declared). Filter by `module`. (r)",
|
|
Input: map[string]any{
|
|
"key": map[string]any{"type": "string", "description": "one key, <node>.<module>.<item>, with everything it holds"},
|
|
"module": map[string]any{"type": "string", "description": "only this module's items"},
|
|
},
|
|
Run: func(args map[string]any) (any, error) {
|
|
if key := text(args, "key"); key != "" {
|
|
raw, err := k.Store.Get(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(raw) == 0 {
|
|
return nil, fmt.Errorf("no reading is kept at %q", key)
|
|
}
|
|
r, err := health.DecodeReading(raw)
|
|
return r, err
|
|
}
|
|
keys, err := k.Store.Keys()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sort.Strings(keys)
|
|
module := text(args, "module")
|
|
type line struct {
|
|
Key string `json:"key"`
|
|
SizeBytes *int64 `json:"size_bytes,omitempty"`
|
|
PeakBytes *int64 `json:"peak_bytes,omitempty"`
|
|
Precision string `json:"precision,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
Reading health.Reading `json:"-"`
|
|
}
|
|
var lines []line
|
|
total := 0
|
|
for _, key := range keys {
|
|
raw, err := k.Store.Get(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
total += len(raw)
|
|
r, err := health.DecodeReading(raw)
|
|
if err != nil || (module != "" && r.Module != module) {
|
|
continue
|
|
}
|
|
lines = append(lines, line{Key: key, SizeBytes: r.SizeBytes, PeakBytes: r.Peak, Precision: r.Precision, Error: r.Error})
|
|
}
|
|
return map[string]any{"readings": lines, "fill": map[string]any{"keys": len(keys), "bytes": total,
|
|
"cap": "none declared: the bus's own limit on a state applies"}}, nil
|
|
},
|
|
},
|
|
{
|
|
Name: "disk_measure",
|
|
Description: "Measure one data item of this machine now, whatever its method (a walk too), and write its reading when it " +
|
|
"changed. Reads the disks as root: a walk is bounded by time and files and says when it was partial.",
|
|
Input: map[string]any{
|
|
"module": map[string]any{"type": "string", "description": "the module that declares the item"},
|
|
"item": map[string]any{"type": "string", "description": "the item's id"},
|
|
},
|
|
Run: func(args map[string]any) (any, error) {
|
|
module, item := text(args, "module"), text(args, "item")
|
|
if module == "" || item == "" {
|
|
return nil, fmt.Errorf("module and item are required")
|
|
}
|
|
r, written, err := k.MeasureNow(context.Background(), module, item)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return map[string]any{"written": written, "reading": r, "key": health.ReadingKey(k.Node, module, item),
|
|
"note": strings.TrimSpace(map[bool]string{true: "the reading changed and was written", false: "the reading had not changed"}[written])}, nil
|
|
},
|
|
},
|
|
}
|
|
}
|