Keep when each data item was first seen and when and why it was retired in its reading, so the self-check's D13 judges a new or retired item from disk-load's state (issue 1955, ADR 0571 clause 3)
This commit is contained in:
@@ -89,6 +89,22 @@ func TestTheHealthLayoutsHoldTheKeepersRules(t *testing.T) {
|
||||
}
|
||||
prev = &r
|
||||
}
|
||||
// The first reading sets FirstSeen and every one after keeps it, as it keeps a retirement; an older reading reads as before.
|
||||
if first := time.Date(2026, 10, 20, 1, 0, 0, 0, time.UTC); !prev.FirstSeen.Equal(first) {
|
||||
t.Fatalf("first seen %s, not %s", prev.FirstSeen, first)
|
||||
}
|
||||
retired := *prev
|
||||
retired.RetiredAt, retired.RetiredWhy = at, "its module left ace"
|
||||
if r, _ := NextReading(&retired, "ace", retired.PlacedDataItem, retired.Measured, at.Add(time.Hour)); !r.RetiredAt.Equal(at) ||
|
||||
r.RetiredWhy != "its module left ace" || !r.FirstSeen.Equal(prev.FirstSeen) {
|
||||
t.Fatalf("a retired reading moved on as %+v", r)
|
||||
}
|
||||
if old, err := DecodeReading([]byte(`{"v":1,"node":"ace","module":"pg","item":"data"}`)); err != nil || !old.FirstSeen.IsZero() {
|
||||
t.Fatalf("a reading of before read as %+v: %v", old, err)
|
||||
}
|
||||
if raw, _ := json.Marshal(Reading{V: ReadingVersion}); strings.Contains(string(raw), "first_seen") || strings.Contains(string(raw), "retired") {
|
||||
t.Fatalf("zero fields were written: %s", raw)
|
||||
}
|
||||
if ReadingKey("ace", "pg", "data") != "ace.pg.data" || ReadingsBucket != "disk-load_readings" {
|
||||
t.Fatal("the readings' key or bucket moved")
|
||||
}
|
||||
|
||||
+11
-1
@@ -67,6 +67,12 @@ type Reading struct {
|
||||
Peak *int64 `json:"peak_bytes,omitempty"`
|
||||
PeakAt string `json:"peak_day,omitempty"`
|
||||
Days []DaySize `json:"days,omitempty"`
|
||||
// FirstSeen is when the item was first measured on this node, kept by every reading after; RetiredAt and RetiredWhy
|
||||
// say its module left the node, written by whoever retires it and carried on unchanged. Each is left out while zero,
|
||||
// so a reading written before reads as it did.
|
||||
FirstSeen time.Time `json:"first_seen,omitzero"`
|
||||
RetiredAt time.Time `json:"retired_at,omitzero"`
|
||||
RetiredWhy string `json:"retired_why,omitempty"`
|
||||
}
|
||||
|
||||
// ReadingKey is the key of an item on a node: `<node>.<module>.<item>`.
|
||||
@@ -88,10 +94,14 @@ func DecodeReading(raw []byte) (Reading, error) {
|
||||
// was taken: a reading that did not change is not written. A measurement with no size (an error, a shallow item) carries
|
||||
// the last size's days on, so the peak outlives one failed measurement.
|
||||
func NextReading(prev *Reading, node string, it catalogue.PlacedDataItem, m Measured, now time.Time) (Reading, bool) {
|
||||
r := Reading{V: ReadingVersion, Node: node, PlacedDataItem: it, Measured: m}
|
||||
r := Reading{V: ReadingVersion, Node: node, PlacedDataItem: it, Measured: m, FirstSeen: now.UTC()}
|
||||
var days []DaySize
|
||||
if prev != nil {
|
||||
days = prev.Days
|
||||
r.RetiredAt, r.RetiredWhy = prev.RetiredAt, prev.RetiredWhy
|
||||
if !prev.FirstSeen.IsZero() {
|
||||
r.FirstSeen = prev.FirstSeen
|
||||
}
|
||||
}
|
||||
today := now.UTC().Format("2006-01-02")
|
||||
cut := now.UTC().Add(-PeakWindow).Format("2006-01-02")
|
||||
|
||||
Reference in New Issue
Block a user