compute/cmd/qemu/metrics/domains.go

740 lines
28 KiB
Go

package metrics
import (
"encoding/xml"
"log"
"strconv"
"deevirt.fr/compute/cmd/qemu/metrics/schema"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/ini.v1"
"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()
if err != nil {
log.Fatalf("Fail to read file: %v", 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.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainInfoMemoryUsageBytes,
prometheus.GaugeValue,
float64(info.Memory)*1024,
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainInfoNrVirtCPU,
prometheus.GaugeValue,
float64(info.NrVirtCpu),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainInfoCPUTime,
prometheus.CounterValue,
float64(info.CpuTime)/1e9, // From nsec to sec
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainInfoVirDomainState,
prometheus.GaugeValue,
float64(info.State),
config.Section("").Key("id").String(),
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 *ini.File, desc schema.Domain) {
for idx, vcpu := range stat {
ch <- prometheus.MustNewConstMetric(
libvirtDomainVcpuState,
prometheus.GaugeValue,
float64(vcpu.State),
config.Section("").Key("id").String(),
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.Section("").Key("id").String(),
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.Section("").Key("id").String(),
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.Section("").Key("id").String(),
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 *ini.File, desc schema.Domain) {
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatCurrentBytes,
prometheus.GaugeValue,
float64(stat.Current)*1024,
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatMaximumBytes,
prometheus.GaugeValue,
float64(stat.Maximum)*1024,
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatSwapInBytes,
prometheus.GaugeValue,
float64(stat.SwapIn)*1024,
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatSwapOutBytes,
prometheus.GaugeValue,
float64(stat.SwapOut)*1024,
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatMajorFaultTotal,
prometheus.CounterValue,
float64(stat.MajorFault),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatMinorFaultTotal,
prometheus.CounterValue,
float64(stat.MinorFault),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatUnusedBytes,
prometheus.GaugeValue,
float64(stat.Unused)*1024,
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatAvailableBytes,
prometheus.GaugeValue,
float64(stat.Available)*1024,
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatRssBytes,
prometheus.GaugeValue,
float64(stat.Rss)*1024,
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatUsableBytes,
prometheus.GaugeValue,
float64(stat.Usable)*1024,
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
ch <- prometheus.MustNewConstMetric(
libvirtDomainBalloonStatDiskCachesBytes,
prometheus.GaugeValue,
float64(stat.DiskCaches)*1024,
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID)
}
func CollectDomainBlock(ch chan<- prometheus.Metric, stat []libvirt.DomainStatsBlock, hostname string, domainUUID string, config *ini.File, desc schema.Domain) {
for _, block := range stat {
if block.RdBytesSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainBlockRdBytes,
prometheus.CounterValue,
float64(block.RdBytes),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
block.Name)
}
if block.RdReqsSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainBlockRdReq,
prometheus.CounterValue,
float64(block.RdReqs),
config.Section("").Key("id").String(),
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.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
block.Name)
}
if block.WrBytesSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainBlockWrBytes,
prometheus.CounterValue,
float64(block.WrBytes),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
block.Name)
}
if block.WrReqsSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainBlockWrReq,
prometheus.CounterValue,
float64(block.WrReqs),
config.Section("").Key("id").String(),
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.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
block.Name)
}
if block.FlReqsSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainBlockFlushReq,
prometheus.CounterValue,
float64(block.FlReqs),
config.Section("").Key("id").String(),
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.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
block.Name)
}
if block.AllocationSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainBlockAllocation,
prometheus.GaugeValue,
float64(block.Allocation),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
block.Name)
}
if block.CapacitySet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainBlockCapacityBytes,
prometheus.GaugeValue,
float64(block.Capacity),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
block.Name)
}
if block.PhysicalSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainBlockPhysicalSizeBytes,
prometheus.GaugeValue,
float64(block.Physical),
config.Section("").Key("id").String(),
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 *ini.File, desc schema.Domain) {
for _, iface := range stat {
if iface.RxBytesSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainInterfaceRxBytes,
prometheus.CounterValue,
float64(iface.RxBytes),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
iface.Name)
}
if iface.RxPktsSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainInterfaceRxPackets,
prometheus.CounterValue,
float64(iface.RxPkts),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
iface.Name)
}
if iface.RxErrsSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainInterfaceRxErrs,
prometheus.CounterValue,
float64(iface.RxErrs),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
iface.Name)
}
if iface.RxDropSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainInterfaceRxDrop,
prometheus.CounterValue,
float64(iface.RxDrop),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
iface.Name)
}
if iface.TxBytesSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainInterfaceTxBytes,
prometheus.CounterValue,
float64(iface.TxBytes),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
iface.Name)
}
if iface.TxPktsSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainInterfaceTxPackets,
prometheus.CounterValue,
float64(iface.TxPkts),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
iface.Name)
}
if iface.TxErrsSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainInterfaceTxErrs,
prometheus.CounterValue,
float64(iface.TxErrs),
config.Section("").Key("id").String(),
desc.Metadata.DeevirtInstance.DeevirtCompanyID,
desc.Metadata.DeevirtInstance.DeevirtDatacenterID,
domainUUID,
iface.Name)
}
if iface.TxDropSet {
ch <- prometheus.MustNewConstMetric(
libvirtDomainInterfaceTxDrop,
prometheus.CounterValue,
float64(iface.TxDrop),
config.Section("").Key("id").String(),
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
}