package main import ( "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) } } record() ticker := time.NewTicker(time.Minute) defer ticker.Stop() for range ticker.C { record() } } 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 }