@@ -2,6 +2,7 @@ package exporter
2
2
3
3
import (
4
4
"encoding/xml"
5
+ "regexp"
5
6
"time"
6
7
7
8
"github.com/digitalocean/go-libvirt"
@@ -160,6 +161,38 @@ var (
160
161
[]string {"domain" , "target_device" },
161
162
nil )
162
163
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
+
163
196
// info metrics
164
197
libvirtDomainInfoDesc = prometheus .NewDesc (
165
198
prometheus .BuildFQName (namespace , "domain" , "info" ),
@@ -370,7 +403,7 @@ func CollectDomain(ch chan<- prometheus.Metric, l *libvirt.Libvirt, domain domai
370
403
return nil
371
404
}
372
405
373
- for _ , collectFunc := range []collectFunc {CollectDomainBlockDeviceInfo , CollectDomainNetworkInfo , CollectDomainDomainStatInfo } {
406
+ for _ , collectFunc := range []collectFunc {CollectDomainBlockDeviceInfo , CollectDomainNetworkInfo , CollectDomainMemoryStatInfo , CollectDomainVCPUInfo } {
374
407
if err = collectFunc (ch , l , domain , promLabels , logger ); err != nil {
375
408
_ = level .Warn (logger ).Log ("warn" , "failed to collect some domain info" , "domain" , domain .libvirtDomain .Name , "msg" , err )
376
409
}
@@ -498,7 +531,7 @@ func CollectDomainNetworkInfo(ch chan<- prometheus.Metric, l *libvirt.Libvirt, d
498
531
return
499
532
}
500
533
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 ) {
502
535
//collect stat info
503
536
var rStats []libvirt.DomainMemoryStat
504
537
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
548
581
return
549
582
}
550
583
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
+
551
655
// Describe returns metadata for all Prometheus metrics that may be exported.
552
656
func (e * LibvirtExporter ) Describe (ch chan <- * prometheus.Desc ) {
553
657
ch <- libvirtUpDesc
@@ -588,4 +692,12 @@ func (e *LibvirtExporter) Describe(ch chan<- *prometheus.Desc) {
588
692
ch <- libvirtDomainMemoryStatsAvailableInBytesDesc
589
693
ch <- libvirtDomainMemoryStatsUsableBytesDesc
590
694
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
591
703
}
0 commit comments