Skip to content

Commit 4cb1bf3

Browse files
sihenselfrittentheke
authored andcommitted
Expose vCPU metrics
* Rename func CollectDomainDomainStatInfo -> CollectDomainMemoryStatInfo
1 parent 71ace1d commit 4cb1bf3

File tree

2 files changed

+126
-3
lines changed

2 files changed

+126
-3
lines changed

README.md

+12-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ libvirt_domain_interface_stats_transmit_bytes_total | "domain", "target_device"
6161
libvirt_domain_interface_stats_transmit_packets_total | "domain", "target_device" | Number of packets transmitted on a network interface
6262
libvirt_domain_interface_stats_transmit_errors_total | "domain", "target_device" | Number of packet transmit errors on a network interface
6363
libvirt_domain_interface_stats_transmit_drops_total | "domain", "target_device" | Number of packet transmit drops on a network interface
64+
libvirt_domain_vcpu_current | "domain" | Number of current online vCPUs
65+
libvirt_domain_vcpu_delay_seconds_total | "domain", "vcpu" | Time the vCPU spent waiting in the queue instead of running. Exposed to the VM as steal time
66+
libvirt_domain_vcpu_maximum | "domain" | Number of maximum online vCPUs
67+
libvirt_domain_vcpu_state | "domain", "vcpu" | State of the vCPU
68+
libvirt_domain_vcpu_time_seconds_total | "domain", "vcpu" | Time spent by the virtual CPU
69+
libvirt_domain_vcpu_wait_seconds_total | "domain", "vcpu" | Time the vCPU wants to run, but the host scheduler has something else running ahead of it
6470

6571

6672
## Example
@@ -93,5 +99,10 @@ libvirt_domain_memory_stats_swap_out_bytes{domain="instance-0001e06e"} 0
9399
libvirt_domain_memory_stats_unused_bytes{domain="instance-0001e06e"} 1.3844406272e+10
94100
libvirt_domain_memory_stats_usable_bytes{domain="instance-0001e06e"} 1.4880370688e+10
95101
libvirt_domain_openstack_info{domain="instance-0001e06e",flavor_name="z1.4xlarge",instance_id="a12423b02-4a36-4530-bf25-acb8ba80b1b1",instance_name="openstackInstanceName",project_id="hghngfhbf45435352353623gvfegt352",project_name="openstackProjectName",user_id="",user_name="openstackUserName"} 1
96-
102+
libvirt_domain_vcpu_current{domain="instance-00000131"} 2
103+
libvirt_domain_vcpu_delay_seconds_total{domain="instance-00000131",vcpu="0"} 6309719178
104+
libvirt_domain_vcpu_maximum{domain="instance-00000131"} 2
105+
libvirt_domain_vcpu_state{domain="instance-00000131",vcpu="0"} 1
106+
libvirt_domain_vcpu_time_seconds_total{domain="instance-00000131",vcpu="0"} 2111850000000
107+
libvirt_domain_vcpu_wait_seconds_total{domain="instance-00000131",vcpu="0"} 4103560000000
97108
```

pkg/exporter/prometheus-libvirt-exporter.go

+114-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package exporter
22

33
import (
44
"encoding/xml"
5+
"regexp"
56
"time"
67

78
"github.com/digitalocean/go-libvirt"
@@ -160,6 +161,38 @@ var (
160161
[]string{"domain", "target_device"},
161162
nil)
162163

164+
// domain vcpu stats
165+
libvirtDomainVCPUStatsCurrent = prometheus.NewDesc(
166+
prometheus.BuildFQName(namespace, "domain_vcpu", "current"),
167+
"Number of current online vCPUs.",
168+
[]string{"domain"},
169+
nil)
170+
libvirtDomainVCPUStatsMaximum = prometheus.NewDesc(
171+
prometheus.BuildFQName(namespace, "domain_vcpu", "maximum"),
172+
"Number of maximum online vCPUs.",
173+
[]string{"domain"},
174+
nil)
175+
libvirtDomainVCPUStatsState = prometheus.NewDesc(
176+
prometheus.BuildFQName(namespace, "domain_vcpu", "state"),
177+
"State of the vCPU.",
178+
[]string{"domain", "vcpu"},
179+
nil)
180+
libvirtDomainVCPUStatsTime = prometheus.NewDesc(
181+
prometheus.BuildFQName(namespace, "domain_vcpu", "time_seconds_total"),
182+
"Time spent by the virtual CPU.",
183+
[]string{"domain", "vcpu"},
184+
nil)
185+
libvirtDomainVCPUStatsWait = prometheus.NewDesc(
186+
prometheus.BuildFQName(namespace, "domain_vcpu", "wait_seconds_total"),
187+
"Time the vCPU wants to run, but the host scheduler has something else running ahead of it.",
188+
[]string{"domain", "vcpu"},
189+
nil)
190+
libvirtDomainVCPUStatsDelay = prometheus.NewDesc(
191+
prometheus.BuildFQName(namespace, "domain_vcpu", "delay_seconds_total"),
192+
"Time the vCPU spent waiting in the queue instead of running. Exposed to the VM as steal time.",
193+
[]string{"domain", "vcpu"},
194+
nil)
195+
163196
// info metrics
164197
libvirtDomainInfoDesc = prometheus.NewDesc(
165198
prometheus.BuildFQName(namespace, "domain", "info"),
@@ -370,7 +403,7 @@ func CollectDomain(ch chan<- prometheus.Metric, l *libvirt.Libvirt, domain domai
370403
return nil
371404
}
372405

373-
for _, collectFunc := range []collectFunc{CollectDomainBlockDeviceInfo, CollectDomainNetworkInfo, CollectDomainDomainStatInfo} {
406+
for _, collectFunc := range []collectFunc{CollectDomainBlockDeviceInfo, CollectDomainNetworkInfo, CollectDomainMemoryStatInfo, CollectDomainVCPUInfo} {
374407
if err = collectFunc(ch, l, domain, promLabels, logger); err != nil {
375408
_ = level.Warn(logger).Log("warn", "failed to collect some domain info", "domain", domain.libvirtDomain.Name, "msg", err)
376409
}
@@ -498,7 +531,7 @@ func CollectDomainNetworkInfo(ch chan<- prometheus.Metric, l *libvirt.Libvirt, d
498531
return
499532
}
500533

501-
func CollectDomainDomainStatInfo(ch chan<- prometheus.Metric, l *libvirt.Libvirt, domain domainMeta, promLabels []string, logger log.Logger) (err error) {
534+
func CollectDomainMemoryStatInfo(ch chan<- prometheus.Metric, l *libvirt.Libvirt, domain domainMeta, promLabels []string, logger log.Logger) (err error) {
502535
//collect stat info
503536
var rStats []libvirt.DomainMemoryStat
504537
if rStats, err = l.DomainMemoryStats(domain.libvirtDomain, uint32(libvirt.DomainMemoryStatNr), 0); err != nil {
@@ -548,6 +581,77 @@ func CollectDomainDomainStatInfo(ch chan<- prometheus.Metric, l *libvirt.Libvirt
548581
return
549582
}
550583

584+
func CollectDomainVCPUInfo(ch chan<- prometheus.Metric, l *libvirt.Libvirt, domain domainMeta, promLabels []string, logger log.Logger) (err error) {
585+
//collect domain vCPU stats
586+
var stats []libvirt.DomainStatsRecord
587+
// ConnectGetAllDomainStats expects a list of domains
588+
var d []libvirt.Domain
589+
d = append(d, domain.libvirtDomain)
590+
591+
if stats, err = l.ConnectGetAllDomainStats(d, uint32(libvirt.DomainStatsVCPU), 0); err != nil {
592+
_ = level.Warn(logger).Log("warn", "failed to get vcpu stats", "domain", domain.libvirtDomain.Name, "msg", err)
593+
return err
594+
}
595+
current := regexp.MustCompile("vcpu.current")
596+
maximum := regexp.MustCompile("vcpu.maximum")
597+
vcpu_metrics := regexp.MustCompile(`vcpu\.\d+\.\w+`)
598+
for _, stat := range stats {
599+
for _, param := range stat.Params {
600+
switch true {
601+
case current.MatchString(param.Field):
602+
metric_value := param.Value.I.(uint32)
603+
ch <- prometheus.MustNewConstMetric(
604+
libvirtDomainVCPUStatsCurrent,
605+
prometheus.GaugeValue,
606+
float64(metric_value),
607+
promLabels...)
608+
case maximum.MatchString(param.Field):
609+
metric_value := param.Value.I.(uint32)
610+
ch <- prometheus.MustNewConstMetric(
611+
libvirtDomainVCPUStatsMaximum,
612+
prometheus.GaugeValue,
613+
float64(metric_value),
614+
promLabels...)
615+
case vcpu_metrics.MatchString(param.Field):
616+
r := regexp.MustCompile(`vcpu\.(\d+)\.(\w+)`)
617+
match := r.FindStringSubmatch(param.Field)
618+
promVCPULabels := append(promLabels, match[1])
619+
switch match[2] {
620+
case "state":
621+
metric_value := param.Value.I.(int32)
622+
ch <- prometheus.MustNewConstMetric(
623+
libvirtDomainVCPUStatsState,
624+
prometheus.GaugeValue,
625+
float64(metric_value),
626+
promVCPULabels...)
627+
case "time":
628+
metric_value := param.Value.I.(uint64)
629+
ch <- prometheus.MustNewConstMetric(
630+
libvirtDomainVCPUStatsTime,
631+
prometheus.CounterValue,
632+
float64(metric_value),
633+
promVCPULabels...)
634+
case "wait":
635+
metric_value := param.Value.I.(uint64)
636+
ch <- prometheus.MustNewConstMetric(
637+
libvirtDomainVCPUStatsWait,
638+
prometheus.CounterValue,
639+
float64(metric_value),
640+
promVCPULabels...)
641+
case "delay":
642+
metric_value := param.Value.I.(uint64)
643+
ch <- prometheus.MustNewConstMetric(
644+
libvirtDomainVCPUStatsDelay,
645+
prometheus.CounterValue,
646+
float64(metric_value),
647+
promVCPULabels...)
648+
}
649+
}
650+
}
651+
}
652+
return
653+
}
654+
551655
// Describe returns metadata for all Prometheus metrics that may be exported.
552656
func (e *LibvirtExporter) Describe(ch chan<- *prometheus.Desc) {
553657
ch <- libvirtUpDesc
@@ -588,4 +692,12 @@ func (e *LibvirtExporter) Describe(ch chan<- *prometheus.Desc) {
588692
ch <- libvirtDomainMemoryStatsAvailableInBytesDesc
589693
ch <- libvirtDomainMemoryStatsUsableBytesDesc
590694
ch <- libvirtDomainMemoryStatsRssBytesDesc
695+
696+
//domain vcpu stats
697+
ch <- libvirtDomainVCPUStatsCurrent
698+
ch <- libvirtDomainVCPUStatsMaximum
699+
ch <- libvirtDomainVCPUStatsState
700+
ch <- libvirtDomainVCPUStatsTime
701+
ch <- libvirtDomainVCPUStatsWait
702+
ch <- libvirtDomainVCPUStatsDelay
591703
}

0 commit comments

Comments
 (0)