chore: publish pxmon v0.2.0
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"pxmon/internal/history"
|
||||
)
|
||||
|
||||
type InterfaceP95Snapshot struct {
|
||||
ClusterName string `json:"cluster"`
|
||||
ClusterID string `json:"cluster_id"`
|
||||
Interface string `json:"interface"`
|
||||
Range history.RangeShortcut `json:"range"`
|
||||
Samples int `json:"samples"`
|
||||
P95Mbps float64 `json:"p95_mbps"`
|
||||
AvgMbps float64 `json:"avg_mbps"`
|
||||
MaxMbps float64 `json:"max_mbps"`
|
||||
Series []history.NodeSamplePoint `json:"series,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) CollectInterfaceP95(selector, iface string, rng history.RangeShortcut) (InterfaceP95Snapshot, error) {
|
||||
iface = strings.TrimSpace(iface)
|
||||
if iface == "" {
|
||||
return InterfaceP95Snapshot{}, errors.New("interface is required")
|
||||
}
|
||||
c, err := s.Get(selector)
|
||||
if err != nil {
|
||||
return InterfaceP95Snapshot{}, err
|
||||
}
|
||||
store := s.NetworkStore()
|
||||
if store == nil {
|
||||
return InterfaceP95Snapshot{}, errors.New("history store not configured")
|
||||
}
|
||||
snaps, err := store.Load(c.ID, rng.Since(s.now()))
|
||||
if err != nil {
|
||||
return InterfaceP95Snapshot{}, err
|
||||
}
|
||||
series := history.AggregateNodeSeries(snaps, iface)
|
||||
out := InterfaceP95Snapshot{
|
||||
ClusterName: c.Name,
|
||||
ClusterID: c.ID,
|
||||
Interface: iface,
|
||||
Range: rng,
|
||||
Samples: len(series),
|
||||
P95Mbps: history.PercentileMbps(series, 95),
|
||||
Series: series,
|
||||
}
|
||||
if len(series) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
var sum, maxV float64
|
||||
for _, p := range series {
|
||||
sum += p.TotalMbps
|
||||
if p.TotalMbps > maxV {
|
||||
maxV = p.TotalMbps
|
||||
}
|
||||
}
|
||||
out.AvgMbps = sum / float64(len(series))
|
||||
out.MaxMbps = maxV
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *Service) RenderInterfaceP95GraphPNG(snap InterfaceP95Snapshot) ([]byte, error) {
|
||||
if len(snap.Series) == 0 {
|
||||
return history.RenderNodeNetworkPNG([]history.NodeSamplePoint{}, history.ChartOptions{
|
||||
Title: fmt.Sprintf("%s: %s", snap.ClusterName, snap.Interface),
|
||||
Subtitle: "No samples",
|
||||
})
|
||||
}
|
||||
subtitle := fmt.Sprintf("P95 %.1f Mbps | max %.1f Mbps | avg %.1f Mbps", snap.P95Mbps, snap.MaxMbps, snap.AvgMbps)
|
||||
if math.IsNaN(snap.P95Mbps) {
|
||||
subtitle = "No samples"
|
||||
}
|
||||
return history.RenderNodeNetworkPNG(snap.Series, history.ChartOptions{
|
||||
Title: fmt.Sprintf("%s: %s", snap.ClusterName, snap.Interface),
|
||||
Subtitle: subtitle,
|
||||
Percentile: 95,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user