mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-17 04:36:50 +00:00
* telemetry: stack volume servers per cluster over time The fleet-wide server count says how many volume servers reported, but not who they belong to. Carry per-cluster counts in /api/cluster-sizes and draw them the same way as cluster sizes, sharing one cluster ranking so a cluster keeps its colour across both stacks. * telemetry: drop the total disk usage chart from the dashboard The stacked cluster sizes chart right below it has the same fleet total as its stack height, plus the per-cluster breakdown. /api/metrics still serves the aggregate for anyone graphing it elsewhere.
91 lines
3.0 KiB
Go
91 lines
3.0 KiB
Go
package storage
|
|
|
|
import (
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
// ClusterSeries is one cluster's daily disk usage and volume server count,
|
|
// aligned to the shared date axis of the enclosing ClusterSizeSeries.
|
|
type ClusterSeries struct {
|
|
ClusterId string `json:"cluster_id"`
|
|
Disk []uint64 `json:"disk"`
|
|
Servers []uint64 `json:"servers"`
|
|
}
|
|
|
|
// OtherSeries is the clusters beyond the caller's limit, summed per day so a
|
|
// stacked chart still adds up to the fleet total.
|
|
type OtherSeries struct {
|
|
Count int `json:"count"`
|
|
Disk []uint64 `json:"disk"`
|
|
Servers []uint64 `json:"servers"`
|
|
}
|
|
|
|
// ClusterSizeSeries is per-cluster disk usage and volume server count over
|
|
// time: one value per cluster per day, largest cluster first, ranked by disk on
|
|
// their most recent day. Both metrics share one ranking so a cluster keeps its
|
|
// place, and its colour, across the charts drawn from this.
|
|
type ClusterSizeSeries struct {
|
|
Dates []string `json:"dates"`
|
|
Clusters []ClusterSeries `json:"clusters"`
|
|
Other *OtherSeries `json:"other,omitempty"`
|
|
ClusterCount int `json:"cluster_count"`
|
|
TotalDisk uint64 `json:"total_disk"` // across all clusters on the last day
|
|
TotalServers uint64 `json:"total_servers"` // across all clusters on the last day
|
|
}
|
|
|
|
// GetClusterSizeSeries returns the last `days` days of per-cluster disk usage
|
|
// and volume server counts across confirmed clusters. Clusters beyond `limit`
|
|
// are folded into Other.
|
|
func (s *PrometheusStorage) GetClusterSizeSeries(days, limit int) ClusterSizeSeries {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
|
|
histories := s.seriesHistories()
|
|
axis := newDailySeries(days, histories)
|
|
activeSince := time.Now().UTC().AddDate(0, 0, -activeDays).Unix()
|
|
last := len(axis.dates) - 1
|
|
series := ClusterSizeSeries{Dates: axis.dates}
|
|
|
|
for id, history := range histories {
|
|
disk, ok := axis.align(history, activeSince, diskBytes)
|
|
if !ok {
|
|
continue
|
|
}
|
|
servers, _ := axis.align(history, activeSince, serverCount)
|
|
series.Clusters = append(series.Clusters, ClusterSeries{ClusterId: id, Disk: disk, Servers: servers})
|
|
series.TotalDisk += disk[last]
|
|
series.TotalServers += servers[last]
|
|
}
|
|
series.ClusterCount = len(series.Clusters)
|
|
|
|
// Rank by the latest day so the stack reads largest-first at its right
|
|
// edge, tie-breaking on id to keep the order stable across refreshes.
|
|
sort.Slice(series.Clusters, func(i, j int) bool {
|
|
a, b := series.Clusters[i], series.Clusters[j]
|
|
if a.Disk[last] != b.Disk[last] {
|
|
return a.Disk[last] > b.Disk[last]
|
|
}
|
|
return a.ClusterId < b.ClusterId
|
|
})
|
|
|
|
if limit > 0 && len(series.Clusters) > limit {
|
|
other := OtherSeries{
|
|
Count: len(series.Clusters) - limit,
|
|
Disk: make([]uint64, len(axis.dates)),
|
|
Servers: make([]uint64, len(axis.dates)),
|
|
}
|
|
for _, c := range series.Clusters[limit:] {
|
|
for i, v := range c.Disk {
|
|
other.Disk[i] += v
|
|
}
|
|
for i, v := range c.Servers {
|
|
other.Servers[i] += v
|
|
}
|
|
}
|
|
series.Clusters = series.Clusters[:limit]
|
|
series.Other = &other
|
|
}
|
|
return series
|
|
}
|