Files
mesh-catalog/modules/disk-load/cmd/disk-load/readings_tools.go
T

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
},
},
}
}