package metrics import ( "encoding/xml" "log" "strconv" "deevirt.fr/compute/pkg/config" "deevirt.fr/compute/pkg/schema" "github.com/prometheus/client_golang/prometheus" "libvirt.org/go/libvirt" ) var ( // Domain CPU libvirtDomainInfoMaxMemBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain", "memory_maximum_allocated_bytes"), "Maximum allowed memory of the domain, in bytes.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainInfoMemoryUsageBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain", "memory_allocated_bytes"), "Memory usage of the domain, in bytes.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainInfoNrVirtCPU = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain", "virtual_cpus"), "Number of virtual CPUs for the domain.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainInfoCPUTime = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain", "cpu_time_seconds_total"), "Amount of CPU time used by the domain, in seconds.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainInfoVirDomainState = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain", "state"), "Virtual domain state. 0: no state, 1: the domain is running, 2: the domain is blocked on resource,"+ " 3: the domain is paused by user, 4: the domain is being shut down, 5: the domain is shut off,"+ "6: the domain is crashed, 7: the domain is suspended by guest power management", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) // VCPU libvirtDomainVcpuState = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_vcpu", "state"), "VCPU state. 0: offline, 1: running, 2: blocked", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "vcpu"}, nil) libvirtDomainVcpuTime = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_vcpu", "time_seconds_total"), "Amount of CPU time used by the domain's VCPU, in seconds.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "vcpu"}, nil) libvirtDomainVcpuWait = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_vcpu", "wait_seconds_total"), "Vcpu's wait_sum metric. CONFIG_SCHEDSTATS has to be enabled", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "vcpu"}, nil) libvirtDomainVcpuDelay = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_vcpu", "delay_seconds_total"), "Amount of CPU time used by the domain's VCPU, in seconds. "+ "Vcpu's delay metric. Time the vcpu thread was enqueued by the "+ "host scheduler, but was waiting in the queue instead of running. "+ "Exposed to the VM as a steal time.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "vcpu"}, nil) // Domain Balloon libvirtDomainBalloonStatCurrentBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "current_bytes"), "The memory currently used (in bytes).", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainBalloonStatMaximumBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "maximum_bytes"), "The maximum memory (in bytes).", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainBalloonStatSwapInBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "swap_in_bytes"), "The amount of data read from swap space (in bytes).", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainBalloonStatSwapOutBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "swap_out_bytes"), "The amount of memory written out to swap space (in bytes).", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainBalloonStatMajorFaultTotal = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "major_fault_total"), "Page faults occur when a process makes a valid access to virtual memory that is not available. "+ "When servicing the page fault, if disk IO is required, it is considered a major fault.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainBalloonStatMinorFaultTotal = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "minor_fault_total"), "Page faults occur when a process makes a valid access to virtual memory that is not available. "+ "When servicing the page not fault, if disk IO is required, it is considered a minor fault.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainBalloonStatUnusedBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "unused_bytes"), "The amount of memory left completely unused by the system. Memory that is available but used for "+ "reclaimable caches should NOT be reported as free. This value is expressed in bytes.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainBalloonStatAvailableBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "available_bytes"), "The total amount of usable memory as seen by the domain. This value may be less than the amount of "+ "memory assigned to the domain if a balloon driver is in use or if the guest OS does not initialize all "+ "assigned pages. This value is expressed in bytes.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainBalloonStatRssBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "rss_bytes"), "Resident Set Size of the process running the domain. This value is in bytes", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainBalloonStatUsableBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "usable_bytes"), "How much the balloon can be inflated without pushing the guest system to swap, corresponds "+ "to 'Available' in /proc/meminfo", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) libvirtDomainBalloonStatDiskCachesBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_balloon", "disk_cache_bytes"), "The amount of memory, that can be quickly reclaimed without additional I/O (in bytes)."+ "Typically these pages are used for caching files from disk.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id"}, nil) // Domain Block libvirtDomainBlockRdBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "read_bytes_total"), "Number of bytes read from a block device, in bytes.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainBlockRdReq = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "read_requests_total"), "Number of read requests from a block device.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainBlockRdTotalTimeSeconds = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "read_time_seconds_total"), "Total time spent on reads from a block device, in seconds.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainBlockWrBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "write_bytes_total"), "Number of bytes written to a block device, in bytes.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainBlockWrReq = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "write_requests_total"), "Number of write requests to a block device.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainBlockWrTotalTimes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "write_time_seconds_total"), "Total time spent on writes on a block device, in seconds", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainBlockFlushReq = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "flush_requests_total"), "Total flush requests from a block device.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainBlockFlushTotalTimeSeconds = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "flush_time_seconds_total"), "Total time in seconds spent on cache flushing to a block device", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainBlockAllocation = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "allocation"), "Offset of the highest written sector on a block device.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainBlockCapacityBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "capacity_bytes"), "Logical size in bytes of the block device backing image.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainBlockPhysicalSizeBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_block", "physicalsize_bytes"), "Physical size in bytes of the container of the backing image.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) // Domain Net libvirtDomainInterfaceRxBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_interface", "receive_bytes_total"), "Number of bytes received on a network interface, in bytes.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainInterfaceRxPackets = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_interface", "receive_packets_total"), "Number of packets received on a network interface.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainInterfaceRxErrs = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_interface", "receive_errors_total"), "Number of packet receive errors on a network interface.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainInterfaceRxDrop = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_interface", "receive_drops_total"), "Number of packet receive drops on a network interface.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainInterfaceTxBytes = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_interface", "transmit_bytes_total"), "Number of bytes transmitted on a network interface, in bytes.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainInterfaceTxPackets = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_interface", "transmit_packets_total"), "Number of packets transmitted on a network interface.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainInterfaceTxErrs = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_interface", "transmit_errors_total"), "Number of packet transmit errors on a network interface.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) libvirtDomainInterfaceTxDrop = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "domain_interface", "transmit_drops_total"), "Number of packet transmit drops on a network interface.", []string{"cluster_id", "company_id", "datacenter_id", "domain_id", "target_device"}, nil) ) func CollectDomain(ch chan<- prometheus.Metric, stat libvirt.DomainStats, hostname string) error { config, err := config.NewConfig() if err != nil { log.Fatalln(err) } domainUUID, err := stat.Domain.GetUUIDString() if err != nil { return err } // Decode XML description of domain to get block device names, etc. xmlDesc, err := stat.Domain.GetXMLDesc(0) if err != nil { return err } var desc schema.Domain err = xml.Unmarshal([]byte(xmlDesc), &desc) if err != nil { return err } // Report domain info. info, err := stat.Domain.GetInfo() if err != nil { return err } ch <- prometheus.MustNewConstMetric( libvirtDomainInfoMaxMemBytes, prometheus.GaugeValue, float64(info.MaxMem)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainInfoMemoryUsageBytes, prometheus.GaugeValue, float64(info.Memory)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainInfoNrVirtCPU, prometheus.GaugeValue, float64(info.NrVirtCpu), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainInfoCPUTime, prometheus.CounterValue, float64(info.CpuTime)/1e9, // From nsec to sec config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainInfoVirDomainState, prometheus.GaugeValue, float64(info.State), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) // Block Stats CollectDomainVCPU(ch, stat.Vcpu, hostname, domainUUID, config, desc) CollectDomainBlock(ch, stat.Block, hostname, domainUUID, config, desc) CollectDomainNet(ch, stat.Net, hostname, domainUUID, config, desc) CollectDomainBalloon(ch, stat.Balloon, hostname, domainUUID, config, desc) return nil } func CollectDomainVCPU(ch chan<- prometheus.Metric, stat []libvirt.DomainStatsVcpu, hostname string, domainUUID string, config *config.Config, desc schema.Domain) { for idx, vcpu := range stat { ch <- prometheus.MustNewConstMetric( libvirtDomainVcpuState, prometheus.GaugeValue, float64(vcpu.State), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, strconv.FormatInt(int64(idx), 10)) ch <- prometheus.MustNewConstMetric( libvirtDomainVcpuTime, prometheus.CounterValue, float64(vcpu.Time)/1000/1000/1000, // From nsec to sec config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, strconv.FormatInt(int64(idx), 10)) ch <- prometheus.MustNewConstMetric( libvirtDomainVcpuWait, prometheus.CounterValue, float64(vcpu.Wait)/1e9, // From nsec to sec config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, strconv.FormatInt(int64(idx), 10)) ch <- prometheus.MustNewConstMetric( libvirtDomainVcpuDelay, prometheus.CounterValue, float64(vcpu.Delay)/1e9, // From nsec to sec config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, strconv.FormatInt(int64(idx), 10)) } } func CollectDomainBalloon(ch chan<- prometheus.Metric, stat *libvirt.DomainStatsBalloon, hostname string, domainUUID string, config *config.Config, desc schema.Domain) { ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatCurrentBytes, prometheus.GaugeValue, float64(stat.Current)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatMaximumBytes, prometheus.GaugeValue, float64(stat.Maximum)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatSwapInBytes, prometheus.GaugeValue, float64(stat.SwapIn)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatSwapOutBytes, prometheus.GaugeValue, float64(stat.SwapOut)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatMajorFaultTotal, prometheus.CounterValue, float64(stat.MajorFault), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatMinorFaultTotal, prometheus.CounterValue, float64(stat.MinorFault), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatUnusedBytes, prometheus.GaugeValue, float64(stat.Unused)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatAvailableBytes, prometheus.GaugeValue, float64(stat.Available)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatRssBytes, prometheus.GaugeValue, float64(stat.Rss)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatUsableBytes, prometheus.GaugeValue, float64(stat.Usable)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) ch <- prometheus.MustNewConstMetric( libvirtDomainBalloonStatDiskCachesBytes, prometheus.GaugeValue, float64(stat.DiskCaches)*1024, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID) } func CollectDomainBlock(ch chan<- prometheus.Metric, stat []libvirt.DomainStatsBlock, hostname string, domainUUID string, config *config.Config, desc schema.Domain) { for _, block := range stat { if block.RdBytesSet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockRdBytes, prometheus.CounterValue, float64(block.RdBytes), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } if block.RdReqsSet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockRdReq, prometheus.CounterValue, float64(block.RdReqs), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } if block.RdTimesSet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockRdTotalTimeSeconds, prometheus.CounterValue, float64(block.RdTimes)/1e9, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } if block.WrBytesSet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockWrBytes, prometheus.CounterValue, float64(block.WrBytes), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } if block.WrReqsSet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockWrReq, prometheus.CounterValue, float64(block.WrReqs), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } if block.WrTimesSet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockWrTotalTimes, prometheus.CounterValue, float64(block.WrTimes)/1e9, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } if block.FlReqsSet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockFlushReq, prometheus.CounterValue, float64(block.FlReqs), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } if block.FlTimesSet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockFlushTotalTimeSeconds, prometheus.CounterValue, float64(block.FlTimes)/1e9, config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } if block.AllocationSet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockAllocation, prometheus.GaugeValue, float64(block.Allocation), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } if block.CapacitySet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockCapacityBytes, prometheus.GaugeValue, float64(block.Capacity), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } if block.PhysicalSet { ch <- prometheus.MustNewConstMetric( libvirtDomainBlockPhysicalSizeBytes, prometheus.GaugeValue, float64(block.Physical), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, block.Name) } } } func CollectDomainNet(ch chan<- prometheus.Metric, stat []libvirt.DomainStatsNet, hostname string, domainUUID string, config *config.Config, desc schema.Domain) { for _, iface := range stat { if iface.RxBytesSet { ch <- prometheus.MustNewConstMetric( libvirtDomainInterfaceRxBytes, prometheus.CounterValue, float64(iface.RxBytes), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, iface.Name) } if iface.RxPktsSet { ch <- prometheus.MustNewConstMetric( libvirtDomainInterfaceRxPackets, prometheus.CounterValue, float64(iface.RxPkts), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, iface.Name) } if iface.RxErrsSet { ch <- prometheus.MustNewConstMetric( libvirtDomainInterfaceRxErrs, prometheus.CounterValue, float64(iface.RxErrs), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, iface.Name) } if iface.RxDropSet { ch <- prometheus.MustNewConstMetric( libvirtDomainInterfaceRxDrop, prometheus.CounterValue, float64(iface.RxDrop), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, iface.Name) } if iface.TxBytesSet { ch <- prometheus.MustNewConstMetric( libvirtDomainInterfaceTxBytes, prometheus.CounterValue, float64(iface.TxBytes), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, iface.Name) } if iface.TxPktsSet { ch <- prometheus.MustNewConstMetric( libvirtDomainInterfaceTxPackets, prometheus.CounterValue, float64(iface.TxPkts), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, iface.Name) } if iface.TxErrsSet { ch <- prometheus.MustNewConstMetric( libvirtDomainInterfaceTxErrs, prometheus.CounterValue, float64(iface.TxErrs), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, iface.Name) } if iface.TxDropSet { ch <- prometheus.MustNewConstMetric( libvirtDomainInterfaceTxDrop, prometheus.CounterValue, float64(iface.TxDrop), config.ClusterID, desc.Metadata.DeevirtInstance.DeevirtCompanyID, desc.Metadata.DeevirtInstance.DeevirtDatacenterID, domainUUID, iface.Name) } } } func CollectDomains(conn *libvirt.Connect, ch chan<- prometheus.Metric, hostname string) error { stats, err := conn.GetAllDomainStats([]*libvirt.Domain{}, libvirt.DOMAIN_STATS_STATE|libvirt.DOMAIN_STATS_CPU_TOTAL|libvirt.DOMAIN_STATS_BALLOON| libvirt.DOMAIN_STATS_VCPU|libvirt.DOMAIN_STATS_BLOCK|libvirt.DOMAIN_STATS_INTERFACE, libvirt.CONNECT_GET_ALL_DOMAINS_STATS_RUNNING|libvirt.CONNECT_GET_ALL_DOMAINS_STATS_SHUTOFF) defer func(stats []libvirt.DomainStats) { for _, stat := range stats { stat.Domain.Free() } }(stats) if err != nil { return err } for _, stat := range stats { err = CollectDomain(ch, stat, hostname) if err != nil { log.Printf("Failed to scrape metrics: %s", err) } } return nil } func (e *LibvirtExporter) DescribeDomains(ch chan<- *prometheus.Desc) { // Domain info ch <- libvirtDomainInfoMaxMemBytes ch <- libvirtDomainInfoMemoryUsageBytes ch <- libvirtDomainInfoNrVirtCPU ch <- libvirtDomainInfoCPUTime ch <- libvirtDomainInfoVirDomainState // VCPU info ch <- libvirtDomainVcpuState ch <- libvirtDomainVcpuTime ch <- libvirtDomainVcpuWait ch <- libvirtDomainVcpuDelay // Domain Balloon Memory ch <- libvirtDomainBalloonStatCurrentBytes ch <- libvirtDomainBalloonStatMaximumBytes ch <- libvirtDomainBalloonStatSwapInBytes ch <- libvirtDomainBalloonStatSwapOutBytes ch <- libvirtDomainBalloonStatMajorFaultTotal ch <- libvirtDomainBalloonStatMinorFaultTotal ch <- libvirtDomainBalloonStatUnusedBytes ch <- libvirtDomainBalloonStatAvailableBytes ch <- libvirtDomainBalloonStatRssBytes ch <- libvirtDomainBalloonStatUsableBytes ch <- libvirtDomainBalloonStatDiskCachesBytes // Domain block stats ch <- libvirtDomainBlockRdBytes ch <- libvirtDomainBlockRdReq ch <- libvirtDomainBlockRdTotalTimeSeconds ch <- libvirtDomainBlockWrBytes ch <- libvirtDomainBlockWrReq ch <- libvirtDomainBlockWrTotalTimes ch <- libvirtDomainBlockFlushReq ch <- libvirtDomainBlockFlushTotalTimeSeconds ch <- libvirtDomainBlockAllocation ch <- libvirtDomainBlockCapacityBytes ch <- libvirtDomainBlockPhysicalSizeBytes // Domain net interfaces stats ch <- libvirtDomainInterfaceRxBytes ch <- libvirtDomainInterfaceRxPackets ch <- libvirtDomainInterfaceRxErrs ch <- libvirtDomainInterfaceRxDrop ch <- libvirtDomainInterfaceTxBytes ch <- libvirtDomainInterfaceTxPackets ch <- libvirtDomainInterfaceTxErrs ch <- libvirtDomainInterfaceTxDrop }