mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-21 06:36:54 +00:00
Short-lived clusters report once under a fresh raft topology id and never again, so CI runs and demo stacks each become their own cluster. Held forward for the whole active window they pile up, and the volume server line climbs every day while capacity stays flat. Sum the fleet series over confirmed clusters only, the same set the version and OS charts already use.
137 lines
4.6 KiB
Go
137 lines
4.6 KiB
Go
package storage
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/seaweedfs/seaweedfs/telemetry/proto"
|
|
)
|
|
|
|
// seedHistory gives a cluster one sample per listed day offset (0 is today).
|
|
func seedHistory(s *PrometheusStorage, id string, disk uint64, dayOffsets ...int) {
|
|
seedSamples(s, id, HistorySample{TotalDiskBytes: disk}, dayOffsets...)
|
|
}
|
|
|
|
// seedSamples is seedHistory for tests that care about more than disk usage.
|
|
// The sample's Ts is filled in per day offset.
|
|
func seedSamples(s *PrometheusStorage, id string, sample HistorySample, dayOffsets ...int) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
for _, offset := range dayOffsets {
|
|
sample.Ts = time.Now().AddDate(0, 0, offset).Unix()
|
|
s.histories[id] = append(s.histories[id], sample)
|
|
}
|
|
}
|
|
|
|
func TestClusterSizeSeries(t *testing.T) {
|
|
s := newPrometheusStorage(prometheus.NewRegistry())
|
|
|
|
// Reported every day of the window.
|
|
seedHistory(s, "daily", 300, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0)
|
|
// Reported two days ago and not since: still active, so its size is held
|
|
// to the right edge instead of dropping out of the stack.
|
|
seedHistory(s, "lagging", 200, -3, -2)
|
|
// Stopped reporting past the active window: its own days only.
|
|
seedHistory(s, "gone", 900, -9, -8)
|
|
// One day of history only: unconfirmed, so it stays out of the stack.
|
|
seedHistory(s, "oneshot", 400, -1)
|
|
|
|
series := s.GetClusterSizeSeries(10, 0)
|
|
if len(series.Dates) != 10 {
|
|
t.Fatalf("dates = %v, want 10 days", series.Dates)
|
|
}
|
|
if series.ClusterCount != 3 {
|
|
t.Fatalf("cluster_count = %d, want 3", series.ClusterCount)
|
|
}
|
|
|
|
byId := map[string][]uint64{}
|
|
for _, c := range series.Clusters {
|
|
byId[c.ClusterId] = c.Disk
|
|
}
|
|
if got := byId["daily"]; !equal(got, []uint64{300, 300, 300, 300, 300, 300, 300, 300, 300, 300}) {
|
|
t.Errorf("daily = %v, want 300 every day", got)
|
|
}
|
|
if got := byId["lagging"]; !equal(got, []uint64{0, 0, 0, 0, 0, 0, 200, 200, 200, 200}) {
|
|
t.Errorf("lagging = %v, want its size carried to the right edge", got)
|
|
}
|
|
if got := byId["gone"]; !equal(got, []uint64{900, 900, 0, 0, 0, 0, 0, 0, 0, 0}) {
|
|
t.Errorf("gone = %v, want no capacity after its last report", got)
|
|
}
|
|
if _, ok := byId["oneshot"]; ok {
|
|
t.Errorf("unconfirmed cluster in the stack: %v", byId["oneshot"])
|
|
}
|
|
|
|
// The total is the last day's stack height: daily + lagging, not gone.
|
|
if series.TotalDisk != 500 {
|
|
t.Errorf("total_disk = %d, want 500", series.TotalDisk)
|
|
}
|
|
// Largest on the last day comes first so the stack reads top-down.
|
|
if series.Clusters[0].ClusterId != "daily" {
|
|
t.Errorf("order = %s first, want daily", series.Clusters[0].ClusterId)
|
|
}
|
|
|
|
// Clusters past the limit are summed into "other", per day.
|
|
series = s.GetClusterSizeSeries(10, 1)
|
|
if len(series.Clusters) != 1 || series.Clusters[0].ClusterId != "daily" {
|
|
t.Fatalf("limited clusters = %+v, want just daily", series.Clusters)
|
|
}
|
|
if series.Other == nil || series.Other.Count != 2 {
|
|
t.Fatalf("other = %+v, want 2 clusters", series.Other)
|
|
}
|
|
if !equal(series.Other.Disk, []uint64{900, 900, 0, 0, 0, 0, 200, 200, 200, 200}) {
|
|
t.Errorf("other = %v, want lagging+gone summed per day", series.Other.Disk)
|
|
}
|
|
if series.ClusterCount != 3 || series.TotalDisk != 500 {
|
|
t.Errorf("limit changed totals: count=%d disk=%d, want 3/500", series.ClusterCount, series.TotalDisk)
|
|
}
|
|
}
|
|
|
|
// A report that lands after an earlier one on the same day replaces it, so the
|
|
// series shows one value per cluster per day.
|
|
func TestClusterSizeSeriesUsesLatestDailySample(t *testing.T) {
|
|
s := newPrometheusStorage(prometheus.NewRegistry())
|
|
|
|
data := &proto.TelemetryData{
|
|
TopologyId: "aaaaaaaa-0000-0000-0000-000000000001",
|
|
Version: "4.40",
|
|
Os: "linux/amd64",
|
|
TotalDiskBytes: 100,
|
|
}
|
|
if err := s.StoreTelemetry(data); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data.TotalDiskBytes = 700
|
|
if err := s.StoreTelemetry(data); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Nothing was reported before today, so the axis is today alone rather
|
|
// than the full 3 days padded out with zeros.
|
|
series := s.GetClusterSizeSeries(3, 0)
|
|
if len(series.Clusters) != 1 {
|
|
t.Fatalf("clusters = %+v, want 1", series.Clusters)
|
|
}
|
|
if today := time.Now().UTC().Format("2006-01-02"); len(series.Dates) != 1 || series.Dates[0] != today {
|
|
t.Errorf("dates = %v, want %s only", series.Dates, today)
|
|
}
|
|
if got := series.Clusters[0].Disk; !equal(got, []uint64{700}) {
|
|
t.Errorf("disk = %v, want today's latest sample only", got)
|
|
}
|
|
if series.TotalDisk != 700 {
|
|
t.Errorf("total_disk = %d, want 700", series.TotalDisk)
|
|
}
|
|
}
|
|
|
|
func equal(a, b []uint64) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
for i := range a {
|
|
if a[i] != b[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|