package metrics import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "lostak.dev/pve-exporter/proxmox" ) // PVE container collector. type PveContainerCollector struct { apiClient *proxmox.PveApiClient // PVE API client instance. state *prometheus.GaugeVec // Container state prometheus gauge. uptime *prometheus.GaugeVec // Container uptime prometheus gauge. cpu *prometheus.GaugeVec // Container count of CPUs prometheus gauge. cpuUsage *prometheus.GaugeVec // Container CPU usage % prometheus gauge. memBytes *prometheus.GaugeVec // Container memory in bytes prometheus gauge. memBytesUsed *prometheus.GaugeVec // Container memory usage in bytes prometheus gauge. netReceive *prometheus.GaugeVec // Container network RX in bytes prometheus gauge. netTransmit *prometheus.GaugeVec // Container network TX in bytes prometheus gauge. diskWrite *prometheus.GaugeVec // Container disk written in bytes prometheus gauge. diskRead *prometheus.GaugeVec // Container disk read in bytes prometheus gauge. disk *prometheus.GaugeVec // Container disk space usage in bytes prometheus gauge. diskMax *prometheus.GaugeVec // Container disk size in bytes prometheus gauge. swap *prometheus.GaugeVec // Container swap usage in bytes prometheus gauge. } // Create new instance of PVE container collector. func NewPveContainerCollector(apiClient *proxmox.PveApiClient) *PveContainerCollector { c := PveContainerCollector{apiClient: apiClient} // Container state. c.state = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_state", Help: "Container state.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container uptime. c.uptime = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_uptime", Help: "Container uptime.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container CPU count. c.cpu = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_cpu_count", Help: "Container CPU count.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container CPU usage. c.cpuUsage = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_cpu_usage", Help: "Container CPU usage.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container memory total. c.memBytes = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_mem_total_bytes", Help: "Container total memory in bytes.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container memory usage. c.memBytesUsed = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_mem_used_bytes", Help: "Container used memory in bytes.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container network RX. c.netReceive = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_network_receive_bytes", Help: "Container network RX bytes.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container network TX. c.netTransmit = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_network_transmit_bytes", Help: "Container network TX bytes.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container disk written. c.diskWrite = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_disk_written_bytes", Help: "Container disk written bytes.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container disk read. c.diskRead = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_disk_read_bytes", Help: "Container disk read bytes.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container disk size. c.disk = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_disk_usage_bytes", Help: "Container disk read bytes.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container disk size. c.diskMax = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_disk_size_bytes", Help: "Container disk size bytes.", }, []string{"cluster", "node", "vmid", "name"}, ) // Container swap usage. c.swap = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "pve_ct_swap_used_bytes", Help: "Container swap usage bytes.", }, []string{"cluster", "node", "vmid", "name"}, ) return &c } // PveMetricsCollector interface implementation. func (c *PveContainerCollector) CollectMetrics() error { cluster, err := c.apiClient.GetClusterStatus() if err != nil { return err } for _, node := range cluster.NodeStatuses { containers, err := c.apiClient.GetNodeContainerList(node.Name) if err != nil { return err } for _, container := range *containers { // Skip templates because they are always offline. if container.Template == 1 { continue } labels := prometheus.Labels{ "cluster": cluster.GetClusterName(), "node": node.Name, "vmid": container.VMID, "name": container.Name, } c.state.With(labels).Set(container.GetStatusNumeric()) c.cpu.With(labels).Set(float64(container.CPUs)) c.memBytes.With(labels).Set(float64(container.MaxMem)) c.diskMax.With(labels).Set(float64(container.MaxDisk)) // Metrics only on running container. if container.IsRunning() { c.uptime.With(labels).Set(float64(container.Uptime)) c.cpuUsage.With(labels).Set(float64(container.CPU)) c.memBytesUsed.With(labels).Set(float64(container.Mem)) c.netReceive.With(labels).Set(float64(container.NetIn)) c.netTransmit.With(labels).Set(float64(container.NetOut)) c.diskRead.With(labels).Set(float64(container.DiskRead)) c.diskWrite.With(labels).Set(float64(container.DiskWrite)) c.disk.With(labels).Set(float64(container.Disk)) c.swap.With(labels).Set(float64(container.Swap)) } } } return nil } // PveMetricsCollector interface implementation. func (c *PveContainerCollector) GetName() string { return "Container" }