Sensors: one standard read interface — catalog, single value, history, shaped query
Every number the collector samples becomes a sensor with a stable dotted ID (cpu.core.3.usage, fan.nct6775.fan2, fs.root.used_pct). Clients discover them from the catalog and ask for exactly what they want, including as a shaped query: send the object you want, get it back with the values filled in. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
01aeb226ea
commit
43bf787696
@@ -0,0 +1,53 @@
|
||||
package sensors
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type fake []Sensor
|
||||
|
||||
func (f fake) Sensors() []Sensor { return f }
|
||||
|
||||
func TestSeg(t *testing.T) {
|
||||
for in, want := range map[string]string{"/": "root", "/mnt/tank": "mnt_tank", "Package id 0": "package_id_0", "enp3s0": "enp3s0", " ": "unnamed", "Tctl+": "tctl", "nvme0n1": "nvme0n1"} {
|
||||
if got := Seg(in); got != want {
|
||||
t.Errorf("Seg(%q) = %q, want %q", in, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistryDedupes(t *testing.T) {
|
||||
r := NewRegistry(fake{{ID: "temp.nvme.composite", Value: 40.0}}, fake{{ID: "temp.nvme.composite", Value: 50.0}})
|
||||
all := r.All()
|
||||
if len(all) != 2 || all[0].ID != "temp.nvme.composite" || all[1].ID != "temp.nvme.composite_2" {
|
||||
t.Fatalf("got %+v", all)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShape(t *testing.T) {
|
||||
all := []Sensor{{ID: "cpu.usage", Value: 12.5, Unit: "%"}, {ID: "fan.a.fan1", Value: 800.0}, {ID: "fan.a.fan2", Value: 900.0}, {ID: "net.eth0.up", Value: true}}
|
||||
got, err := Shape(all, json.RawMessage(`{"cpu":"cpu.usage","fans":"fan.*","box":{"link":"net.eth0.up","gone":"ups.battery"},"list":["cpu.usage"]}`), false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := map[string]any{
|
||||
"cpu": 12.5,
|
||||
"fans": map[string]any{"fan.a.fan1": 800.0, "fan.a.fan2": 900.0},
|
||||
"box": map[string]any{"link": true, "gone": nil},
|
||||
"list": []any{12.5},
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got %#v\nwant %#v", got, want)
|
||||
}
|
||||
full, _ := Shape(all, json.RawMessage(`"cpu.usage"`), true)
|
||||
if s, ok := full.(Sensor); !ok || s.Unit != "%" {
|
||||
t.Fatalf("full: got %#v", full)
|
||||
}
|
||||
for _, bad := range []string{`{"x": 5}`, `{"x": "fan.["}`, `not json`} {
|
||||
if _, err := Shape(all, json.RawMessage(bad), false); err == nil {
|
||||
t.Errorf("Shape(%s) should fail", bad)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user