mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-08 05:56:37 +00:00
411 lines
9.6 KiB
Go
411 lines
9.6 KiB
Go
//go:build windows
|
|
|
|
package vmware
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"github.com/alecthomas/kingpin/v2"
|
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
)
|
|
|
|
const Name = "vmware"
|
|
|
|
type Config struct{}
|
|
|
|
var ConfigDefaults = Config{}
|
|
|
|
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics.
|
|
type Collector struct {
|
|
config Config
|
|
miSession *mi.Session
|
|
miQueryCPU mi.Query
|
|
miQueryMem mi.Query
|
|
|
|
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 New(config *Config) *Collector {
|
|
if config == nil {
|
|
config = &ConfigDefaults
|
|
}
|
|
|
|
c := &Collector{
|
|
config: *config,
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
func NewWithFlags(_ *kingpin.Application) *Collector {
|
|
return &Collector{}
|
|
}
|
|
|
|
func (c *Collector) GetName() string {
|
|
return Name
|
|
}
|
|
|
|
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
|
|
return []string{}, nil
|
|
}
|
|
|
|
func (c *Collector) Close(_ *slog.Logger) error {
|
|
return nil
|
|
}
|
|
|
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
|
if miSession == nil {
|
|
return errors.New("miSession is nil")
|
|
}
|
|
|
|
miQuery, err := mi.NewQuery("SELECT * FROM Win32_PerfRawData_vmGuestLib_VCPU")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
|
}
|
|
|
|
c.miQueryCPU = miQuery
|
|
|
|
miQuery, err = mi.NewQuery("SELECT * FROM Win32_PerfRawData_vmGuestLib_VMem")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
|
}
|
|
|
|
c.miQueryMem = miQuery
|
|
c.miSession = miSession
|
|
|
|
c.memActive = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_active_bytes"),
|
|
"(MemActiveMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memBallooned = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_ballooned_bytes"),
|
|
"(MemBalloonedMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memLimit = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_limit_bytes"),
|
|
"(MemLimitMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memMapped = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_mapped_bytes"),
|
|
"(MemMappedMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memOverhead = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_overhead_bytes"),
|
|
"(MemOverheadMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memReservation = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_reservation_bytes"),
|
|
"(MemReservationMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memShared = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_shared_bytes"),
|
|
"(MemSharedMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memSharedSaved = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_shared_saved_bytes"),
|
|
"(MemSharedSavedMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memShares = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_shares"),
|
|
"(MemShares)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memSwapped = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_swapped_bytes"),
|
|
"(MemSwappedMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memTargetSize = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_target_size_bytes"),
|
|
"(MemTargetSizeMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.memUsed = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "mem_used_bytes"),
|
|
"(MemUsedMB)",
|
|
nil,
|
|
nil,
|
|
)
|
|
|
|
c.cpuLimitMHz = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "cpu_limit_mhz"),
|
|
"(CpuLimitMHz)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.cpuReservationMHz = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "cpu_reservation_mhz"),
|
|
"(CpuReservationMHz)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.cpuShares = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "cpu_shares"),
|
|
"(CpuShares)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.cpuStolenTotal = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "cpu_stolen_seconds_total"),
|
|
"(CpuStolenMs)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.cpuTimeTotal = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "cpu_time_seconds_total"),
|
|
"(CpuTimePercents)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.effectiveVMSpeedMHz = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "effective_vm_speed_mhz"),
|
|
"(EffectiveVMSpeedMHz)",
|
|
nil,
|
|
nil,
|
|
)
|
|
c.hostProcessorSpeedMHz = prometheus.NewDesc(
|
|
prometheus.BuildFQName(types.Namespace, Name, "host_processor_speed_mhz"),
|
|
"(HostProcessorSpeedMHz)",
|
|
nil,
|
|
nil,
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Collect sends the metric values for each metric
|
|
// to the provided prometheus Metric channel.
|
|
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
|
logger = logger.With(slog.String("collector", Name))
|
|
if err := c.collectMem(ch); err != nil {
|
|
logger.Error("failed collecting vmware memory metrics",
|
|
slog.Any("err", err),
|
|
)
|
|
|
|
return err
|
|
}
|
|
|
|
if err := c.collectCpu(ch); err != nil {
|
|
logger.Error("failed collecting vmware cpu metrics",
|
|
slog.Any("err", err),
|
|
)
|
|
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type Win32_PerfRawData_vmGuestLib_VMem struct {
|
|
MemActiveMB uint64 `mi:"MemActiveMB"`
|
|
MemBalloonedMB uint64 `mi:"MemBalloonedMB"`
|
|
MemLimitMB uint64 `mi:"MemLimitMB"`
|
|
MemMappedMB uint64 `mi:"MemMappedMB"`
|
|
MemOverheadMB uint64 `mi:"MemOverheadMB"`
|
|
MemReservationMB uint64 `mi:"MemReservationMB"`
|
|
MemSharedMB uint64 `mi:"MemSharedMB"`
|
|
MemSharedSavedMB uint64 `mi:"MemSharedSavedMB"`
|
|
MemShares uint64 `mi:"MemShares"`
|
|
MemSwappedMB uint64 `mi:"MemSwappedMB"`
|
|
MemTargetSizeMB uint64 `mi:"MemTargetSizeMB"`
|
|
MemUsedMB uint64 `mi:"MemUsedMB"`
|
|
}
|
|
|
|
type Win32_PerfRawData_vmGuestLib_VCPU struct {
|
|
CpuLimitMHz uint64 `mi:"CpuLimitMHz"`
|
|
CpuReservationMHz uint64 `mi:"CpuReservationMHz"`
|
|
CpuShares uint64 `mi:"CpuShares"`
|
|
CpuStolenMs uint64 `mi:"CpuStolenMs"`
|
|
CpuTimePercents uint64 `mi:"CpuTimePercents"`
|
|
EffectiveVMSpeedMHz uint64 `mi:"EffectiveVMSpeedMHz"`
|
|
HostProcessorSpeedMHz uint64 `mi:"HostProcessorSpeedMHz"`
|
|
}
|
|
|
|
func (c *Collector) collectMem(ch chan<- prometheus.Metric) error {
|
|
var dst []Win32_PerfRawData_vmGuestLib_VMem
|
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQueryMem); err != nil {
|
|
return fmt.Errorf("WMI query failed: %w", err)
|
|
}
|
|
|
|
if len(dst) == 0 {
|
|
return errors.New("WMI query returned empty result set")
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
// mbToBytes moved to utils package
|
|
func mbToBytes(mb uint64) float64 {
|
|
return float64(mb * 1024 * 1024)
|
|
}
|
|
|
|
func (c *Collector) collectCpu(ch chan<- prometheus.Metric) error {
|
|
var dst []Win32_PerfRawData_vmGuestLib_VCPU
|
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQueryCPU); err != nil {
|
|
return fmt.Errorf("WMI query failed: %w", err)
|
|
}
|
|
|
|
if len(dst) == 0 {
|
|
return errors.New("WMI query returned empty result set")
|
|
}
|
|
|
|
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)*perftypes.TicksToSecondScaleFactor,
|
|
)
|
|
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.cpuTimeTotal,
|
|
prometheus.CounterValue,
|
|
float64(dst[0].CpuTimePercents)*perftypes.TicksToSecondScaleFactor,
|
|
)
|
|
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.effectiveVMSpeedMHz,
|
|
prometheus.GaugeValue,
|
|
float64(dst[0].EffectiveVMSpeedMHz),
|
|
)
|
|
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.hostProcessorSpeedMHz,
|
|
prometheus.GaugeValue,
|
|
float64(dst[0].HostProcessorSpeedMHz),
|
|
)
|
|
|
|
return nil
|
|
}
|