Files
ProxmoxDash/history.go

135 lines
4.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"fmt"
"log"
"time"
)
func runHistoryCollector(collect func() (dashboardMetrics, error), store *Store) {
record := func() {
metrics, err := collect()
if err != nil {
log.Printf("Не удалось собрать исторические метрики: %v", err)
return
}
if err := store.AddHistory(historyPointFromMetrics(metrics)); err != nil {
log.Printf("Не удалось сохранить исторические метрики: %v", err)
}
store.AddEntityMetrics(metrics)
}
record()
ticker := time.NewTicker(time.Minute)
defer ticker.Stop()
for range ticker.C {
record()
}
}
func (s *Store) AddEntityMetrics(metrics dashboardMetrics) {
ts := time.Now().Unix()
for _, p := range metrics.ZFS.Pools {
v := p.CapacityPercent
s.AddEntityHistory("zfs", p.Name, ts, &v, nil)
}
for _, g := range metrics.Guests.Guests {
if g.Template != 0 {
continue
}
cpu := g.CPU * 100
var mem float64
if g.MaxMemory > 0 {
mem = float64(g.MemoryBytes) / float64(g.MaxMemory) * 100
}
s.AddEntityHistory("guest", fmt.Sprintf("%d · %s", g.VMID, g.Name), ts, &cpu, &mem)
}
for _, d := range metrics.Disks {
iops := d.ReadIOPS + d.WriteIOPS
util := d.Utilization
s.AddEntityHistory("disk-io", d.Name+" · "+d.Model, ts, &iops, &util)
latency := d.LatencyMs
s.AddEntityHistory("disk-latency", d.Name+" · "+d.Model, ts, &latency, nil)
if d.Temperature == nil {
continue
}
var wear *float64
if d.WearUsedPercent != nil {
wear = d.WearUsedPercent
}
s.AddEntityHistory("disk", d.Name+" · "+d.Model, ts, d.Temperature, wear)
}
for _, task := range metrics.Activity.Tasks {
if task.Type == "vzdump" && task.Duration > 0 && task.EndTime >= time.Now().Add(-15*time.Minute).Unix() {
duration := float64(task.Duration)
s.AddEntityHistory("backup-duration", "VMID "+task.ID, ts, &duration, nil)
}
}
for _, agent := range metrics.Agents {
if !agent.Online {
continue
}
name := agent.ID + " · " + agent.Name
cpu := agent.Report.CPUPercent
memory := float64(0)
if agent.Report.MemoryTotal > 0 {
memory = float64(agent.Report.MemoryUsed) / float64(agent.Report.MemoryTotal) * 100
}
swap := float64(0)
if agent.Report.SwapTotal > 0 {
swap = float64(agent.Report.SwapUsed) / float64(agent.Report.SwapTotal) * 100
}
s.AddEntityHistory("agent-resource", name, ts, &cpu, &memory)
s.AddEntityHistory("agent-swap", name, ts, &swap, nil)
pressure := agent.Report.Pressure.IO.Avg10
s.AddEntityHistory("agent-pressure", name, ts, &pressure, nil)
for _, filesystem := range agent.Report.Filesystems {
used := filesystem.UsedPercent
inodes := filesystem.InodesPercent
s.AddEntityHistory("agent-filesystem", name+" · "+filesystem.Mountpoint, ts, &used, &inodes)
}
}
s.PruneEntityHistory()
}
func historyPointFromMetrics(metrics dashboardMetrics) HistoryPoint {
point := HistoryPoint{
Timestamp: time.Now().Unix(), CPUUsage: metrics.CPU.UsagePercent,
MemoryUsage: metrics.Memory.UsagePercent, SwapUsage: metrics.Memory.SwapPercent,
RootUsage: metrics.Storage.UsagePercent, NetworkReceive: metrics.Network.ReceivePerSec,
NetworkTransmit: metrics.Network.TransmitPerSec, UPSCharge: metrics.UPS.ChargePercent,
UPSLoad: metrics.UPS.LoadPercent,
}
if len(metrics.CPU.Temperatures) > 0 {
for _, temperature := range metrics.CPU.Temperatures {
point.CPUTemperature += temperature.Celsius
}
point.CPUTemperature /= float64(len(metrics.CPU.Temperatures))
}
var zfsSize, zfsUsed uint64
for _, pool := range metrics.ZFS.Pools {
zfsSize += pool.SizeBytes
zfsUsed += pool.AllocatedBytes
}
if zfsSize > 0 {
point.ZFSUsage = float64(zfsUsed) / float64(zfsSize) * 100
}
var guestCores, guestUsedCPU float64
var guestMemory, guestMaxMemory uint64
for _, guest := range metrics.Guests.Guests {
if guest.Template != 0 || guest.Status != "running" {
continue
}
guestCores += guest.MaxCPU
guestUsedCPU += guest.CPU * guest.MaxCPU
guestMemory += guest.MemoryBytes
guestMaxMemory += guest.MaxMemory
}
if guestCores > 0 {
point.GuestsCPU = guestUsedCPU / guestCores * 100
}
if guestMaxMemory > 0 {
point.GuestsMemory = float64(guestMemory) / float64(guestMaxMemory) * 100
}
return point
}