diff --git a/README.md b/README.md index 80ff3577..3f429235 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ net | [Win32_PerfRawData_Tcpip_NetworkInterface](https://technet.microsoft.com/e os | [Win32_OperatingSystem](https://msdn.microsoft.com/en-us/library/aa394239) metrics (memory, processes, users) | ✓ service | [Win32_Service](https://msdn.microsoft.com/en-us/library/aa394418(v=vs.85).aspx) metrics (service states) | ✓ system | Win32_PerfRawData_PerfOS_System metrics (system calls) | ✓ +vmware | Performance counters installed by the Vmware Guest agent | The HELP texts shows the WMI data source, please see MSDN documentation for details. diff --git a/collector/vmware.go b/collector/vmware.go new file mode 100644 index 00000000..4b5bc4de --- /dev/null +++ b/collector/vmware.go @@ -0,0 +1,335 @@ +// returns data points from Win32_PerfRawData_vmGuestLib_VMem and Win32_PerfRawData_vmGuestLib_VCPU +package collector + +import ( + "log" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" +) + +func init() { + Factories["vmware"] = NewVmwareCollector +} + +// A VmwareCollector is a Prometheus collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics +type VmwareCollector struct { + MemActive *prometheus.Desc + MemBallooned *prometheus.Desc + MemLimit *prometheus.Desc + MemMapped *prometheus.Desc + MemOverhead *prometheus.Desc + MemReservation *prometheus.Desc + MemShared *prometheus.Desc + MemSharedSaved *prometheus.Desc + MemShares *prometheus.Desc + MemSwapped *prometheus.Desc + MemTargetSize *prometheus.Desc + MemUsed *prometheus.Desc + + CpuLimitMHz *prometheus.Desc + CpuReservationMHz *prometheus.Desc + CpuShares *prometheus.Desc + CpuStolenTotal *prometheus.Desc + CpuTimeTotal *prometheus.Desc + EffectiveVMSpeedMHz *prometheus.Desc + HostProcessorSpeedMHz *prometheus.Desc +} + +func NewVmwareCollector() (Collector, error) { + const subsystem = "vmware" + return &VmwareCollector{ + MemActive: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_active_bytes"), + "(MemActiveMB)", + nil, + nil, + ), + MemBallooned: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_ballooned_bytes"), + "(MemBalloonedMB)", + nil, + nil, + ), + MemLimit: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_limit_bytes"), + "(MemLimitMB)", + nil, + nil, + ), + MemMapped: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_mapped_bytes"), + "(MemMappedMB)", + nil, + nil, + ), + MemOverhead: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_overhead_bytes"), + "(MemOverheadMB)", + nil, + nil, + ), + MemReservation: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_reservation_bytes"), + "(MemReservationMB)", + nil, + nil, + ), + MemShared: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_shared_bytes"), + "(MemSharedMB)", + nil, + nil, + ), + MemSharedSaved: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_shared_saved_bytes"), + "(MemSharedSavedMB)", + nil, + nil, + ), + MemShares: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_shares"), + "(MemShares)", + nil, + nil, + ), + MemSwapped: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_swapped_bytes"), + "(MemSwappedMB)", + nil, + nil, + ), + MemTargetSize: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_target_size_bytes"), + "(MemTargetSizeMB)", + nil, + nil, + ), + MemUsed: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_used_bytes"), + "(MemUsedMB)", + nil, + nil, + ), + + CpuLimitMHz: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_limit_mhz"), + "(CpuLimitMHz)", + nil, + nil, + ), + CpuReservationMHz: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_reservation_mhz"), + "(CpuReservationMHz)", + nil, + nil, + ), + CpuShares: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_shares"), + "(CpuShares)", + nil, + nil, + ), + CpuStolenTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_stolen_seconds_total"), + "(CpuStolenMs)", + nil, + nil, + ), + CpuTimeTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_time_seconds_total"), + "(CpuTimePercents)", + nil, + nil, + ), + EffectiveVMSpeedMHz: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "effective_vm_speed_mhz"), + "(EffectiveVMSpeedMHz)", + nil, + nil, + ), + HostProcessorSpeedMHz: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "host_processor_speed_mhz"), + "(HostProcessorSpeedMHz)", + nil, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *VmwareCollector) Collect(ch chan<- prometheus.Metric) error { + if desc, err := c.collectMem(ch); err != nil { + log.Println("[ERROR] failed collecting vmware memory metrics:", desc, err) + return err + } + if desc, err := c.collectCpu(ch); err != nil { + log.Println("[ERROR] failed collecting vmware cpu metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_vmGuestLib_VMem struct { + MemActiveMB uint64 + MemBalloonedMB uint64 + MemLimitMB uint64 + MemMappedMB uint64 + MemOverheadMB uint64 + MemReservationMB uint64 + MemSharedMB uint64 + MemSharedSavedMB uint64 + MemShares uint64 + MemSwappedMB uint64 + MemTargetSizeMB uint64 + MemUsedMB uint64 +} + +type Win32_PerfRawData_vmGuestLib_VCPU struct { + CpuLimitMHz uint64 + CpuReservationMHz uint64 + CpuShares uint64 + CpuStolenMs uint64 + CpuTimePercents uint64 + EffectiveVMSpeedMHz uint64 + HostProcessorSpeedMHz uint64 +} + +func (c *VmwareCollector) collectMem(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_vmGuestLib_VMem + q := wmi.CreateQuery(&dst, "") + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + ch <- prometheus.MustNewConstMetric( + c.MemActive, + prometheus.GaugeValue, + mbToBytes(dst[0].MemActiveMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemBallooned, + prometheus.GaugeValue, + mbToBytes(dst[0].MemBalloonedMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemLimit, + prometheus.GaugeValue, + mbToBytes(dst[0].MemLimitMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMapped, + prometheus.GaugeValue, + mbToBytes(dst[0].MemMappedMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemOverhead, + prometheus.GaugeValue, + mbToBytes(dst[0].MemOverheadMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemReservation, + prometheus.GaugeValue, + mbToBytes(dst[0].MemReservationMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemShared, + prometheus.GaugeValue, + mbToBytes(dst[0].MemSharedMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemSharedSaved, + prometheus.GaugeValue, + mbToBytes(dst[0].MemSharedSavedMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemShares, + prometheus.GaugeValue, + float64(dst[0].MemShares), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemSwapped, + prometheus.GaugeValue, + mbToBytes(dst[0].MemSwappedMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemTargetSize, + prometheus.GaugeValue, + mbToBytes(dst[0].MemTargetSizeMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemUsed, + prometheus.GaugeValue, + mbToBytes(dst[0].MemUsedMB), + ) + + return nil, nil +} + +func mbToBytes(mb uint64) float64 { + return float64(mb * 1024 * 1024) +} + +func (c *VmwareCollector) collectCpu(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_vmGuestLib_VCPU + q := wmi.CreateQuery(&dst, "") + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + ch <- prometheus.MustNewConstMetric( + c.CpuLimitMHz, + prometheus.GaugeValue, + float64(dst[0].CpuLimitMHz), + ) + + ch <- prometheus.MustNewConstMetric( + c.CpuReservationMHz, + prometheus.GaugeValue, + float64(dst[0].CpuReservationMHz), + ) + + ch <- prometheus.MustNewConstMetric( + c.CpuShares, + prometheus.GaugeValue, + float64(dst[0].CpuShares), + ) + + ch <- prometheus.MustNewConstMetric( + c.CpuStolenTotal, + prometheus.CounterValue, + float64(dst[0].CpuStolenMs)*ticksToSecondsScaleFactor, + ) + + ch <- prometheus.MustNewConstMetric( + c.CpuTimeTotal, + prometheus.CounterValue, + float64(dst[0].CpuTimePercents)*ticksToSecondsScaleFactor, + ) + + ch <- prometheus.MustNewConstMetric( + c.EffectiveVMSpeedMHz, + prometheus.GaugeValue, + float64(dst[0].EffectiveVMSpeedMHz), + ) + + ch <- prometheus.MustNewConstMetric( + c.HostProcessorSpeedMHz, + prometheus.GaugeValue, + float64(dst[0].HostProcessorSpeedMHz), + ) + + return nil, nil +}