From 805d0139777fcde41a21204f6fec190825720464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Thu, 31 Oct 2024 00:55:58 +0100 Subject: [PATCH 01/12] hyperv: Added DataStore, Virtual SMB and Dynamic Memory Balancer metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- internal/collector/hyperv/hyperv.go | 702 +++++++++--------- .../collector/hyperv/hyperv_dynamic_memory.go | 1 + .../collector/hyperv/hyperv_hypervisor.go | 1 + internal/collector/hyperv/hyperv_network.go | 1 + internal/collector/hyperv/hyperv_storage.go | 1 + .../hyperv/hyperv_virtual_machine.go | 142 ++++ 6 files changed, 482 insertions(+), 366 deletions(-) create mode 100644 internal/collector/hyperv/hyperv_dynamic_memory.go create mode 100644 internal/collector/hyperv/hyperv_hypervisor.go create mode 100644 internal/collector/hyperv/hyperv_network.go create mode 100644 internal/collector/hyperv/hyperv_storage.go create mode 100644 internal/collector/hyperv/hyperv_virtual_machine.go diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index fead371e5..04dfdeeaa 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -9,10 +9,10 @@ import ( "strings" "github.com/alecthomas/kingpin/v2" - "github.com/prometheus-community/windows_exporter/internal/mi" + "github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/types" - "github.com/prometheus-community/windows_exporter/internal/utils" "github.com/prometheus/client_golang/prometheus" + "github.com/yusufpapurcu/wmi" ) const Name = "hyperv" @@ -23,122 +23,211 @@ var ConfigDefaults = Config{} // Collector is a Prometheus Collector for hyper-v. type Collector struct { - config Config - miSession *mi.Session - - // Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary - healthCritical *prometheus.Desc - healthOk *prometheus.Desc - - // Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition - physicalPagesAllocated *prometheus.Desc - preferredNUMANodeIndex *prometheus.Desc - remotePhysicalPages *prometheus.Desc - - // Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition - addressSpaces *prometheus.Desc - attachedDevices *prometheus.Desc - depositedPages *prometheus.Desc - deviceDMAErrors *prometheus.Desc - deviceInterruptErrors *prometheus.Desc - deviceInterruptMappings *prometheus.Desc - deviceInterruptThrottleEvents *prometheus.Desc - gpaPages *prometheus.Desc - gpaSpaceModifications *prometheus.Desc - ioTLBFlushCost *prometheus.Desc - ioTLBFlushes *prometheus.Desc - recommendedVirtualTLBSize *prometheus.Desc - skippedTimerTicks *prometheus.Desc - value1Gdevicepages *prometheus.Desc - value1GGPApages *prometheus.Desc - value2Mdevicepages *prometheus.Desc - value2MGPApages *prometheus.Desc - value4Kdevicepages *prometheus.Desc - value4KGPApages *prometheus.Desc - virtualTLBFlushEntires *prometheus.Desc - virtualTLBPages *prometheus.Desc + config Config + + // Hyper-V Virtual Machine Health Summa metrics + perfDataCollectorVirtualMachineHealthSummary perfdata.Collector + healthCritical *prometheus.Desc // \Hyper-V Virtual Machine Health Summary\Health Critical + healthOk *prometheus.Desc // \Hyper-V Virtual Machine Health Summary\Health Ok + + // Hyper-V VM Vid Partition metadata + perfDataCollectorVMVidPartition perfdata.Collector + physicalPagesAllocated *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Physical Pages Allocated + preferredNUMANodeIndex *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Preferred NUMA Node Index + remotePhysicalPages *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Remote Physical Pages + + // Hyper-V Hypervisor Root Partition metrics + addressSpaces *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Address Spaces + attachedDevices *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Attached Devices + depositedPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Deposited Pages + deviceDMAErrors *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device DMA Errors + deviceInterruptErrors *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Errors + deviceInterruptMappings *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Mappings + deviceInterruptThrottleEvents *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Throttle Events + gpaPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\GPA Pages + gpaSpaceModifications *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\GPA Space Modifications/sec + ioTLBFlushCost *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\I/O TLB Flush Cost + ioTLBFlushes *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\I/O TLB Flushes/sec + recommendedVirtualTLBSize *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Recommended Virtual TLB Size + skippedTimerTicks *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Skipped Timer Ticks + value1Gdevicepages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\1G device pages + value1GGPApages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\1G GPA pages + value2Mdevicepages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\2M device pages + value2MGPApages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\2M GPA pages + value4Kdevicepages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\4K device pages + value4KGPApages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\4K GPA pages + virtualTLBFlushEntires *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Flush Entires/sec + virtualTLBPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Pages // Win32_PerfRawData_HvStats_HyperVHypervisor - logicalProcessors *prometheus.Desc - virtualProcessors *prometheus.Desc + logicalProcessors *prometheus.Desc // \Hyper-V Hypervisor\Logical Processors + virtualProcessors *prometheus.Desc // \Hyper-V Hypervisor\Virtual Processors // Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor - hostLPGuestRunTimePercent *prometheus.Desc - hostLPHypervisorRunTimePercent *prometheus.Desc - hostLPTotalRunTimePercent *prometheus.Desc + hostLPGuestRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Guest Run Time + hostLPHypervisorRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Hypervisor Run Time + hostLPTotalRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Total Run Time + hostLPIdleRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Idle Time // Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor - hostGuestRunTime *prometheus.Desc - hostHypervisorRunTime *prometheus.Desc - hostRemoteRunTime *prometheus.Desc - hostTotalRunTime *prometheus.Desc - hostCPUWaitTimePerDispatch *prometheus.Desc + hostGuestRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Run Time + hostHypervisorRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Hypervisor Run Time + hostRemoteRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Remote Run Time + hostTotalRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Total Run Time + hostCPUWaitTimePerDispatch *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\CPU Wait Time Per Dispatch // Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor - vmGuestRunTime *prometheus.Desc - vmHypervisorRunTime *prometheus.Desc - vmRemoteRunTime *prometheus.Desc - vmTotalRunTime *prometheus.Desc - vmCPUWaitTimePerDispatch *prometheus.Desc - - // Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch - broadcastPacketsReceived *prometheus.Desc - broadcastPacketsSent *prometheus.Desc - bytes *prometheus.Desc - bytesReceived *prometheus.Desc - bytesSent *prometheus.Desc - directedPacketsReceived *prometheus.Desc - directedPacketsSent *prometheus.Desc - droppedPacketsIncoming *prometheus.Desc - droppedPacketsOutgoing *prometheus.Desc - extensionsDroppedPacketsIncoming *prometheus.Desc - extensionsDroppedPacketsOutgoing *prometheus.Desc - learnedMacAddresses *prometheus.Desc - multicastPacketsReceived *prometheus.Desc - multicastPacketsSent *prometheus.Desc - numberOfSendChannelMoves *prometheus.Desc - numberOfVMQMoves *prometheus.Desc - packetsFlooded *prometheus.Desc - packets *prometheus.Desc - packetsReceived *prometheus.Desc - packetsSent *prometheus.Desc - purgedMacAddresses *prometheus.Desc - - // Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter - adapterBytesDropped *prometheus.Desc - adapterBytesReceived *prometheus.Desc - adapterBytesSent *prometheus.Desc - adapterFramesDropped *prometheus.Desc - adapterFramesReceived *prometheus.Desc - adapterFramesSent *prometheus.Desc - - // Win32_PerfRawData_Counters_HyperVVirtualStorageDevice - vmStorageErrorCount *prometheus.Desc - vmStorageQueueLength *prometheus.Desc - vmStorageReadBytes *prometheus.Desc - vmStorageReadOperations *prometheus.Desc - vmStorageWriteBytes *prometheus.Desc - vmStorageWriteOperations *prometheus.Desc - - // Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter - vmStorageBytesReceived *prometheus.Desc - vmStorageBytesSent *prometheus.Desc - vmStorageDroppedPacketsIncoming *prometheus.Desc - vmStorageDroppedPacketsOutgoing *prometheus.Desc - vmStoragePacketsReceived *prometheus.Desc - vmStoragePacketsSent *prometheus.Desc - - // Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM - vmMemoryAddedMemory *prometheus.Desc - vmMemoryAveragePressure *prometheus.Desc - vmMemoryCurrentPressure *prometheus.Desc - vmMemoryGuestVisiblePhysicalMemory *prometheus.Desc - vmMemoryMaximumPressure *prometheus.Desc - vmMemoryMemoryAddOperations *prometheus.Desc - vmMemoryMemoryRemoveOperations *prometheus.Desc - vmMemoryMinimumPressure *prometheus.Desc - vmMemoryPhysicalMemory *prometheus.Desc - vmMemoryRemovedMemory *prometheus.Desc + vmGuestRunTime *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Guest Run Time + vmHypervisorRunTime *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Hypervisor Run Time + vmRemoteRunTime *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Remote Run Time + vmTotalRunTime *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Total Run Time + vmCPUWaitTimePerDispatch *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per Dispatch + + // Hyper-V Virtual Switch metrics + broadcastPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Broadcast Packets Received/sec + broadcastPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Broadcast Packets Sent/sec + bytes *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes/sec + bytesReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes Received/sec + bytesSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes Sent/sec + directedPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Directed Packets Received/sec + directedPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Directed Packets Sent/sec + droppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Switch(*)\Dropped Packets Incoming/sec + droppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Switch(*)\Dropped Packets Outgoing/sec + extensionsDroppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Switch(*)\Extensions Dropped Packets Incoming/sec + extensionsDroppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Switch(*)\Extensions Dropped Packets Outgoing/sec + learnedMacAddresses *prometheus.Desc // \Hyper-V Virtual Switch(*)\Learned Mac Addresses + multicastPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Multicast Packets Received/sec + multicastPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Multicast Packets Sent/sec + numberOfSendChannelMoves *prometheus.Desc // \Hyper-V Virtual Switch(*)\Number of Send Channel Moves/sec + numberOfVMQMoves *prometheus.Desc // \Hyper-V Virtual Switch(*)\Number of VMQ Moves/sec + packetsFlooded *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Flooded + packets *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets/sec + packetsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Received/sec + packetsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Sent/sec + purgedMacAddresses *prometheus.Desc // \Hyper-V Virtual Switch(*)\Purged Mac Addresses + + // Hyper-V Legacy Network Adapter metrics + adapterBytesDropped *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Dropped + adapterBytesReceived *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Received/sec + adapterBytesSent *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Sent/sec + adapterFramesDropped *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Dropped + adapterFramesReceived *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Received/sec + adapterFramesSent *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Sent/sec + + // Hyper-V Virtual Network Adapter metrics + vmStorageBytesReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Bytes Received/sec + vmStorageBytesSent *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Bytes Sent/sec + vmStorageDroppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Dropped Packets Incoming/sec + vmStorageDroppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Dropped Packets Outgoing/sec + vmStoragePacketsReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Received/sec + vmStoragePacketsSent *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Sent/sec + + // Hyper-V Dynamic Memory VM metrics + vmMemoryAddedMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Added Memory + vmMemoryAveragePressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Average Pressure + vmMemoryCurrentPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Current Pressure + vmMemoryGuestVisiblePhysicalMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Guest Visible Physical Memory + vmMemoryMaximumPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Maximum Pressure + vmMemoryMemoryAddOperations *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Memory Add Operations + vmMemoryMemoryRemoveOperations *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Memory Remove Operations + vmMemoryMinimumPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Minimum Pressure + vmMemoryPhysicalMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Physical Memory + vmMemoryRemovedMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Removed Memory + // TODO: \Hyper-V Dynamic Memory VM(*)\Guest Available Memory + + // Hyper-V Dynamic Memory Balancer metrics + // TODO: \Hyper-V Dynamic Memory Balancer(*)\Available Memory For Balancing + // TODO: \Hyper-V Dynamic Memory Balancer(*)\System Current Pressure + // TODO: \Hyper-V Dynamic Memory Balancer(*)\Available Memory + // TODO: \Hyper-V Dynamic Memory Balancer(*)\Average Pressure + + // Hyper-V Virtual Storage Device metrics + vmStorageErrorCount *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Error Count + vmStorageQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Queue Length + vmStorageReadBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Bytes/sec + vmStorageReadOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Operations/Sec + vmStorageWriteBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Bytes/sec + vmStorageWriteOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Operations/Sec + // TODO: \Hyper-V Virtual Storage Device(*)\Latency + // TODO: \Hyper-V Virtual Storage Device(*)\Throughput + // TODO: \Hyper-V Virtual Storage Device(*)\Normalized Throughput + + // Hyper-V DataStore metrics + // TODO: \Hyper-V DataStore(*)\Fragmentation ratio + // TODO: \Hyper-V DataStore(*)\Sector size + // TODO: \Hyper-V DataStore(*)\Data alignment + // TODO: \Hyper-V DataStore(*)\Current replay logSize + // TODO: \Hyper-V DataStore(*)\Number of available entries inside object tables + // TODO: \Hyper-V DataStore(*)\Number of empty entries inside object tables + // TODO: \Hyper-V DataStore(*)\Number of free bytes inside key tables + // TODO: \Hyper-V DataStore(*)\Data end + // TODO: \Hyper-V DataStore(*)\Number of file objects + // TODO: \Hyper-V DataStore(*)\Number of object tables + // TODO: \Hyper-V DataStore(*)\Number of key tables + // TODO: \Hyper-V DataStore(*)\File data size in bytes + // TODO: \Hyper-V DataStore(*)\Table data size in bytes + // TODO: \Hyper-V DataStore(*)\Names size in bytes + // TODO: \Hyper-V DataStore(*)\Number of keys + // TODO: \Hyper-V DataStore(*)\Reconnect latency microseconds + // TODO: \Hyper-V DataStore(*)\Disconnect count + // TODO: \Hyper-V DataStore(*)\Write to file byte latency microseconds + // TODO: \Hyper-V DataStore(*)\Write to file byte count + // TODO: \Hyper-V DataStore(*)\Write to file count + // TODO: \Hyper-V DataStore(*)\Read from file byte latency microseconds + // TODO: \Hyper-V DataStore(*)\Read from file byte count + // TODO: \Hyper-V DataStore(*)\Read from file count + // TODO: \Hyper-V DataStore(*)\Write to storage byte latency microseconds + // TODO: \Hyper-V DataStore(*)\Write to storage byte count + // TODO: \Hyper-V DataStore(*)\Write to storage count + // TODO: \Hyper-V DataStore(*)\Read from storage byte latency microseconds + // TODO: \Hyper-V DataStore(*)\Read from storage byte count + // TODO: \Hyper-V DataStore(*)\Read from storage count + // TODO: \Hyper-V DataStore(*)\Commit byte latency microseconds + // TODO: \Hyper-V DataStore(*)\Commit byte count + // TODO: \Hyper-V DataStore(*)\Commit count + // TODO: \Hyper-V DataStore(*)\Cache update operation latency microseconds + // TODO: \Hyper-V DataStore(*)\Cache update operation count + // TODO: \Hyper-V DataStore(*)\Commit operation latency microseconds + // TODO: \Hyper-V DataStore(*)\Commit operation count + // TODO: \Hyper-V DataStore(*)\Compact operation latency microseconds + // TODO: \Hyper-V DataStore(*)\Compact operation count + // TODO: \Hyper-V DataStore(*)\Load file operation latency microseconds + // TODO: \Hyper-V DataStore(*)\Load file operation count + // TODO: \Hyper-V DataStore(*)\Remove operation latency microseconds + // TODO: \Hyper-V DataStore(*)\Remove operation count + // TODO: \Hyper-V DataStore(*)\Query size operation latency microseconds + // TODO: \Hyper-V DataStore(*)\Query size operation count + // TODO: \Hyper-V DataStore(*)\Set operation latency microseconds + // TODO: \Hyper-V DataStore(*)\Set operation count + // TODO: \Hyper-V DataStore(*)\Get operation latency microseconds + // TODO: \Hyper-V DataStore(*)\Get operation count + // TODO: \Hyper-V DataStore(*)\File lock release latency microseconds + // TODO: \Hyper-V DataStore(*)\File lock acquire latency microseconds + // TODO: \Hyper-V DataStore(*)\File lock count + // TODO: \Hyper-V DataStore(*)\Storage lock release latency microseconds + // TODO: \Hyper-V DataStore(*)\Storage lock acquire latency microseconds + // TODO: \Hyper-V DataStore(*)\Storage lock count + + // Hyper-V Virtual SMB metrics + // TODO: \Hyper-V Virtual SMB(*)\Direct-Mapped Sections + // TODO: \Hyper-V Virtual SMB(*)\Direct-Mapped Pages + // TODO: \Hyper-V Virtual SMB(*)\Write Bytes/sec (RDMA) + // TODO: \Hyper-V Virtual SMB(*)\Write Bytes/sec + // TODO: \Hyper-V Virtual SMB(*)\Read Bytes/sec (RDMA) + // TODO: \Hyper-V Virtual SMB(*)\Read Bytes/sec + // TODO: \Hyper-V Virtual SMB(*)\Flush Requests/sec + // TODO: \Hyper-V Virtual SMB(*)\Write Requests/sec (RDMA) + // TODO: \Hyper-V Virtual SMB(*)\Write Requests/sec + // TODO: \Hyper-V Virtual SMB(*)\Read Requests/sec (RDMA) + // TODO: \Hyper-V Virtual SMB(*)\Read Requests/sec + // TODO: \Hyper-V Virtual SMB(*)\Avg. sec/Request + // TODO: \Hyper-V Virtual SMB(*)\Current Pending Requests + // TODO: \Hyper-V Virtual SMB(*)\Current Open File Count + // TODO: \Hyper-V Virtual SMB(*)\Tree Connect Count + // TODO: \Hyper-V Virtual SMB(*)\Requests/sec + // TODO: \Hyper-V Virtual SMB(*)\Sent Bytes/sec + // TODO: \Hyper-V Virtual SMB(*)\Received Bytes/sec + } func New(config *Config) *Collector { @@ -166,54 +255,19 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) { } func (c *Collector) Close(_ *slog.Logger) error { + c.perfDataCollectorVirtualMachineHealthSummary.Close() + c.perfDataCollectorVMVidPartition.Close() + return nil } -func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error { - if miSession == nil { - return errors.New("miSession is nil") +func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { + if err := c.buildVirtualMachine(); err != nil { + return err } - c.miSession = miSession - buildSubsystemName := func(component string) string { return "hyperv_" + component } - c.healthCritical = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("health"), "critical"), - "This counter represents the number of virtual machines with critical health", - nil, - nil, - ) - c.healthOk = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("health"), "ok"), - "This counter represents the number of virtual machines with ok health", - nil, - nil, - ) - - // - - c.physicalPagesAllocated = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vid"), "physical_pages_allocated"), - "The number of physical pages allocated", - []string{"vm"}, - nil, - ) - c.preferredNUMANodeIndex = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vid"), "preferred_numa_node_index"), - "The preferred NUMA node index associated with this partition", - []string{"vm"}, - nil, - ) - c.remotePhysicalPages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vid"), "remote_physical_pages"), - "The number of physical pages not allocated from the preferred NUMA node", - []string{"vm"}, - nil, - ) - - // - c.addressSpaces = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "address_spaces"), "The number of address spaces in the virtual TLB of the partition", @@ -756,22 +810,11 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error { // 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.collectVmHealth(ch); err != nil { - logger.Error("failed collecting hyperV health status metrics", - slog.Any("err", err), - ) +func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error { + errs := make([]error, 0) - return err - } - - if err := c.collectVmVid(ch); err != nil { - logger.Error("failed collecting hyperV pages metrics", - slog.Any("err", err), - ) - - return err + if err := c.collectVirtualMachine(ch); err != nil { + errs = append(errs, fmt.Errorf("failed collecting hyperV health status metrics: %w", err)) } if err := c.collectVmHv(ch); err != nil { @@ -854,116 +897,43 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan return err } - return nil -} - -// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary vm health status. -type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary struct { - HealthCritical uint32 `mi:"HealthCritical"` - HealthOk uint32 `mi:"HealthOK"` -} - -func (c *Collector) collectVmHealth(ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) - } - - for _, health := range dst { - ch <- prometheus.MustNewConstMetric( - c.healthCritical, - prometheus.GaugeValue, - float64(health.HealthCritical), - ) - - ch <- prometheus.MustNewConstMetric( - c.healthOk, - prometheus.GaugeValue, - float64(health.HealthOk), - ) - } - - return nil -} - -// Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition ..,. -type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct { - Name string `mi:"Name"` - PhysicalPagesAllocated uint64 `mi:"PhysicalPagesAllocated"` - PreferredNUMANodeIndex uint64 `mi:"PreferredNUMANodeIndex"` - RemotePhysicalPages uint64 `mi:"RemotePhysicalPages"` -} - -func (c *Collector) collectVmVid(ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) - } - - for _, page := range dst { - if strings.Contains(page.Name, "_Total") { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.physicalPagesAllocated, - prometheus.GaugeValue, - float64(page.PhysicalPagesAllocated), - page.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.preferredNUMANodeIndex, - prometheus.GaugeValue, - float64(page.PreferredNUMANodeIndex), - page.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.remotePhysicalPages, - prometheus.GaugeValue, - float64(page.RemotePhysicalPages), - page.Name, - ) - } - - return nil + return errors.Join(errs...) } // Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition ... type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct { - Name string `mi:"Name"` - AddressSpaces uint64 `mi:"AddressSpaces"` - AttachedDevices uint64 `mi:"AttachedDevices"` - DepositedPages uint64 `mi:"DepositedPages"` - DeviceDMAErrors uint64 `mi:"DeviceDMAErrors"` - DeviceInterruptErrors uint64 `mi:"DeviceInterruptErrors"` - DeviceInterruptMappings uint64 `mi:"DeviceInterruptMappings"` - DeviceInterruptThrottleEvents uint64 `mi:"DeviceInterruptThrottleEvents"` - GPAPages uint64 `mi:"GPAPages"` - GPASpaceModificationsPersec uint64 `mi:"GPASpaceModificationsPersec"` - IOTLBFlushCost uint64 `mi:"IOTLBFlushCost"` - IOTLBFlushesPersec uint64 `mi:"IOTLBFlushesPersec"` - RecommendedVirtualTLBSize uint64 `mi:"RecommendedVirtualTLBSize"` - SkippedTimerTicks uint64 `mi:"SkippedTimerTicks"` - Value1Gdevicepages uint64 `mi:"Value1Gdevicepages"` - Value1GGPApages uint64 `mi:"Value1GGPApages"` - Value2Mdevicepages uint64 `mi:"Value2Mdevicepages"` - Value2MGPApages uint64 `mi:"Value2MGPApages"` - Value4Kdevicepages uint64 `mi:"Value4Kdevicepages"` - Value4KGPApages uint64 `mi:"Value4KGPApages"` - VirtualTLBFlushEntiresPersec uint64 `mi:"VirtualTLBFlushEntiresPersec"` - VirtualTLBPages uint64 `mi:"VirtualTLBPages"` + Name string + AddressSpaces uint64 + AttachedDevices uint64 + DepositedPages uint64 + DeviceDMAErrors uint64 + DeviceInterruptErrors uint64 + DeviceInterruptMappings uint64 + DeviceInterruptThrottleEvents uint64 + GPAPages uint64 + GPASpaceModificationsPersec uint64 + IOTLBFlushCost uint64 + IOTLBFlushesPersec uint64 + RecommendedVirtualTLBSize uint64 + SkippedTimerTicks uint64 + Value1Gdevicepages uint64 + Value1GGPApages uint64 + Value2Mdevicepages uint64 + Value2MGPApages uint64 + Value4Kdevicepages uint64 + Value4KGPApages uint64 + VirtualTLBFlushEntiresPersec uint64 + VirtualTLBPages uint64 } func (c *Collector) collectVmHv(ch chan<- prometheus.Metric) error { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) + if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition", &dst); err != nil { + return err } for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { + if strings.Contains(obj.Name, "*") { continue } @@ -1088,14 +1058,14 @@ func (c *Collector) collectVmHv(ch chan<- prometheus.Metric) error { // Win32_PerfRawData_HvStats_HyperVHypervisor ... type Win32_PerfRawData_HvStats_HyperVHypervisor struct { - LogicalProcessors uint64 `mi:"LogicalProcessors"` - VirtualProcessors uint64 `mi:"VirtualProcessors"` + LogicalProcessors uint64 + VirtualProcessors uint64 } func (c *Collector) collectVmProcessor(ch chan<- prometheus.Metric) error { var dst []Win32_PerfRawData_HvStats_HyperVHypervisor - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisor"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) + if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisor", &dst); err != nil { + return err } for _, obj := range dst { @@ -1117,20 +1087,20 @@ func (c *Collector) collectVmProcessor(ch chan<- prometheus.Metric) error { // Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor ... type Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor struct { - Name string `mi:"Name"` - PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"` - PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"` - PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"` + Name string + PercentGuestRunTime uint64 + PercentHypervisorRunTime uint64 + PercentTotalRunTime uint } func (c *Collector) collectHostLPUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) + if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor", &dst); err != nil { + return err } for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { + if strings.Contains(obj.Name, "*") { continue } @@ -1171,22 +1141,22 @@ func (c *Collector) collectHostLPUsage(logger *slog.Logger, ch chan<- prometheus // Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor ... type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct { - Name string `mi:"Name"` - PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"` - PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"` - PercentRemoteRunTime uint64 `mi:"PercentRemoteRunTime"` - PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"` - CPUWaitTimePerDispatch uint64 `mi:"CPUWaitTimePerDispatch"` + Name string + PercentGuestRunTime uint64 + PercentHypervisorRunTime uint64 + PercentRemoteRunTime uint64 + PercentTotalRunTime uint64 + CPUWaitTimePerDispatch uint64 } func (c *Collector) collectHostCpuUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) + if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor", &dst); err != nil { + return err } for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { + if strings.Contains(obj.Name, "*") { continue } @@ -1241,22 +1211,22 @@ func (c *Collector) collectHostCpuUsage(logger *slog.Logger, ch chan<- prometheu // Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor ... type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct { - Name string `mi:"Name"` - PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"` - PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"` - PercentRemoteRunTime uint64 `mi:"PercentRemoteRunTime"` - PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"` - CPUWaitTimePerDispatch uint64 `mi:"CPUWaitTimePerDispatch"` + Name string + PercentGuestRunTime uint64 + PercentHypervisorRunTime uint64 + PercentRemoteRunTime uint64 + PercentTotalRunTime uint64 + CPUWaitTimePerDispatch uint64 } func (c *Collector) collectVmCpuUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) + if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor", &dst); err != nil { + return err } for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { + if strings.Contains(obj.Name, "*") { continue } @@ -1319,41 +1289,41 @@ func (c *Collector) collectVmCpuUsage(logger *slog.Logger, ch chan<- prometheus. // Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch ... type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct { - Name string `mi:"Name"` - BroadcastPacketsReceivedPersec uint64 `mi:"BroadcastPacketsReceivedPersec"` - BroadcastPacketsSentPersec uint64 `mi:"BroadcastPacketsSentPersec"` - BytesPersec uint64 `mi:"BytesPersec"` - BytesReceivedPersec uint64 `mi:"BytesReceivedPersec"` - BytesSentPersec uint64 `mi:"BytesSentPersec"` - DirectedPacketsReceivedPersec uint64 `mi:"DirectedPacketsReceivedPersec"` - DirectedPacketsSentPersec uint64 `mi:"DirectedPacketsSentPersec"` - DroppedPacketsIncomingPersec uint64 `mi:"DroppedPacketsIncomingPersec"` - DroppedPacketsOutgoingPersec uint64 `mi:"DroppedPacketsOutgoingPersec"` - ExtensionsDroppedPacketsIncomingPersec uint64 `mi:"ExtensionsDroppedPacketsIncomingPersec"` - ExtensionsDroppedPacketsOutgoingPersec uint64 `mi:"ExtensionsDroppedPacketsOutgoingPersec"` - LearnedMacAddresses uint64 `mi:"LearnedMacAddresses"` - LearnedMacAddressesPersec uint64 `mi:"LearnedMacAddressesPersec"` - MulticastPacketsReceivedPersec uint64 `mi:"MulticastPacketsReceivedPersec"` - MulticastPacketsSentPersec uint64 `mi:"MulticastPacketsSentPersec"` - NumberofSendChannelMovesPersec uint64 `mi:"NumberofSendChannelMovesPersec"` - NumberofVMQMovesPersec uint64 `mi:"NumberofVMQMovesPersec"` - PacketsFlooded uint64 `mi:"PacketsFlooded"` - PacketsFloodedPersec uint64 `mi:"PacketsFloodedPersec"` - PacketsPersec uint64 `mi:"PacketsPersec"` - PacketsReceivedPersec uint64 `mi:"PacketsReceivedPersec"` - PacketsSentPersec uint64 `mi:"PacketsSentPersec"` - PurgedMacAddresses uint64 `mi:"PurgedMacAddresses"` - PurgedMacAddressesPersec uint64 `mi:"PurgedMacAddressesPersec"` + Name string + BroadcastPacketsReceivedPersec uint64 + BroadcastPacketsSentPersec uint64 + BytesPersec uint64 + BytesReceivedPersec uint64 + BytesSentPersec uint64 + DirectedPacketsReceivedPersec uint64 + DirectedPacketsSentPersec uint64 + DroppedPacketsIncomingPersec uint64 + DroppedPacketsOutgoingPersec uint64 + ExtensionsDroppedPacketsIncomingPersec uint64 + ExtensionsDroppedPacketsOutgoingPersec uint64 + LearnedMacAddresses uint64 + LearnedMacAddressesPersec uint64 + MulticastPacketsReceivedPersec uint64 + MulticastPacketsSentPersec uint64 + NumberofSendChannelMovesPersec uint64 + NumberofVMQMovesPersec uint64 + PacketsFlooded uint64 + PacketsFloodedPersec uint64 + PacketsPersec uint64 + PacketsReceivedPersec uint64 + PacketsSentPersec uint64 + PurgedMacAddresses uint64 + PurgedMacAddressesPersec uint64 } func (c *Collector) collectVmSwitch(ch chan<- prometheus.Metric) error { var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) + if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch", &dst); err != nil { + return err } for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { + if strings.Contains(obj.Name, "*") { continue } @@ -1501,23 +1471,23 @@ func (c *Collector) collectVmSwitch(ch chan<- prometheus.Metric) error { // Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter ... type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct { - Name string `mi:"Name"` - BytesDropped uint64 `mi:"BytesDropped"` - BytesReceivedPersec uint64 `mi:"BytesReceivedPersec"` - BytesSentPersec uint64 `mi:"BytesSentPersec"` - FramesDropped uint64 `mi:"FramesDropped"` - FramesReceivedPersec uint64 `mi:"FramesReceivedPersec"` - FramesSentPersec uint64 `mi:"FramesSentPersec"` + Name string + BytesDropped uint64 + BytesReceivedPersec uint64 + BytesSentPersec uint64 + FramesDropped uint64 + FramesReceivedPersec uint64 + FramesSentPersec uint64 } func (c *Collector) collectVmEthernet(ch chan<- prometheus.Metric) error { var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) + if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter", &dst); err != nil { + return err } for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { + if strings.Contains(obj.Name, "*") { continue } @@ -1569,23 +1539,23 @@ func (c *Collector) collectVmEthernet(ch chan<- prometheus.Metric) error { // Win32_PerfRawData_Counters_HyperVVirtualStorageDevice ... type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct { - Name string `mi:"Name"` - ErrorCount uint64 `mi:"ErrorCount"` - QueueLength uint32 `mi:"QueueLength"` - ReadBytesPersec uint64 `mi:"ReadBytesPersec"` - ReadOperationsPerSec uint64 `mi:"ReadOperationsPerSec"` - WriteBytesPersec uint64 `mi:"WriteBytesPersec"` - WriteOperationsPerSec uint64 `mi:"WriteOperationsPerSec"` + Name string + ErrorCount uint64 + QueueLength uint32 + ReadBytesPersec uint64 + ReadOperationsPerSec uint64 + WriteBytesPersec uint64 + WriteOperationsPerSec uint64 } func (c *Collector) collectVmStorage(ch chan<- prometheus.Metric) error { var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_Counters_HyperVVirtualStorageDevice"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) + if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_Counters_HyperVVirtualStorageDevice", &dst); err != nil { + return err } for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { + if strings.Contains(obj.Name, "*") { continue } @@ -1637,23 +1607,23 @@ func (c *Collector) collectVmStorage(ch chan<- prometheus.Metric) error { // Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter ... type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct { - Name string `mi:"Name"` - BytesReceivedPersec uint64 `mi:"BytesReceivedPersec"` - BytesSentPersec uint64 `mi:"BytesSentPersec"` - DroppedPacketsIncomingPersec uint64 `mi:"DroppedPacketsIncomingPersec"` - DroppedPacketsOutgoingPersec uint64 `mi:"DroppedPacketsOutgoingPersec"` - PacketsReceivedPersec uint64 `mi:"PacketsReceivedPersec"` - PacketsSentPersec uint64 `mi:"PacketsSentPersec"` + Name string + BytesReceivedPersec uint64 + BytesSentPersec uint64 + DroppedPacketsIncomingPersec uint64 + DroppedPacketsOutgoingPersec uint64 + PacketsReceivedPersec uint64 + PacketsSentPersec uint64 } func (c *Collector) collectVmNetwork(ch chan<- prometheus.Metric) error { var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) + if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter", &dst); err != nil { + return err } for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { + if strings.Contains(obj.Name, "*") { continue } @@ -1705,27 +1675,27 @@ func (c *Collector) collectVmNetwork(ch chan<- prometheus.Metric) error { // Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM ... type Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM struct { - Name string `mi:"Name"` - AddedMemory uint64 `mi:"AddedMemory"` - AveragePressure uint64 `mi:"AveragePressure"` - CurrentPressure uint64 `mi:"CurrentPressure"` - GuestVisiblePhysicalMemory uint64 `mi:"GuestVisiblePhysicalMemory"` - MaximumPressure uint64 `mi:"MaximumPressure"` - MemoryAddOperations uint64 `mi:"MemoryAddOperations"` - MemoryRemoveOperations uint64 `mi:"MemoryRemoveOperations"` - MinimumPressure uint64 `mi:"MinimumPressure"` - PhysicalMemory uint64 `mi:"PhysicalMemory"` - RemovedMemory uint64 `mi:"RemovedMemory"` + Name string + AddedMemory uint64 + AveragePressure uint64 + CurrentPressure uint64 + GuestVisiblePhysicalMemory uint64 + MaximumPressure uint64 + MemoryAddOperations uint64 + MemoryRemoveOperations uint64 + MinimumPressure uint64 + PhysicalMemory uint64 + RemovedMemory uint64 } func (c *Collector) collectVmMemory(ch chan<- prometheus.Metric) error { var dst []Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM - if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM"))); err != nil { - return fmt.Errorf("WMI query failed: %w", err) + if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM", &dst); err != nil { + return err } for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { + if strings.Contains(obj.Name, "*") { continue } diff --git a/internal/collector/hyperv/hyperv_dynamic_memory.go b/internal/collector/hyperv/hyperv_dynamic_memory.go new file mode 100644 index 000000000..568364523 --- /dev/null +++ b/internal/collector/hyperv/hyperv_dynamic_memory.go @@ -0,0 +1 @@ +package hyperv diff --git a/internal/collector/hyperv/hyperv_hypervisor.go b/internal/collector/hyperv/hyperv_hypervisor.go new file mode 100644 index 000000000..568364523 --- /dev/null +++ b/internal/collector/hyperv/hyperv_hypervisor.go @@ -0,0 +1 @@ +package hyperv diff --git a/internal/collector/hyperv/hyperv_network.go b/internal/collector/hyperv/hyperv_network.go new file mode 100644 index 000000000..568364523 --- /dev/null +++ b/internal/collector/hyperv/hyperv_network.go @@ -0,0 +1 @@ +package hyperv diff --git a/internal/collector/hyperv/hyperv_storage.go b/internal/collector/hyperv/hyperv_storage.go new file mode 100644 index 000000000..568364523 --- /dev/null +++ b/internal/collector/hyperv/hyperv_storage.go @@ -0,0 +1 @@ +package hyperv diff --git a/internal/collector/hyperv/hyperv_virtual_machine.go b/internal/collector/hyperv/hyperv_virtual_machine.go new file mode 100644 index 000000000..8e295b483 --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_machine.go @@ -0,0 +1,142 @@ +package hyperv + +import ( + "errors" + "fmt" + "strings" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + // Hyper-V Virtual Machine Health Summary + healthCritical = "Health Critical" + healthOk = "Health Ok" + + // Hyper-V VM Vid Partition + physicalPagesAllocated = "Physical Pages Allocated" + preferredNUMANodeIndex = "Preferred NUMA Node Index" + remotePhysicalPages = "Remote Physical Pages" +) + +func (c *Collector) buildVirtualMachine() error { + var err error + + c.perfDataCollectorVirtualMachineHealthSummary, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Virtual Machine Health Summary", perfdata.AllInstances, []string{ + healthCritical, + healthOk, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err) + } + + c.healthCritical = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "health_critical"), + "This counter represents the number of virtual machines with critical health", + nil, + nil, + ) + c.healthOk = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "health_ok"), + "This counter represents the number of virtual machines with ok health", + nil, + nil, + ) + + c.perfDataCollectorVMVidPartition, err = perfdata.NewCollector(perfdata.V2, "Hyper-V VM Vid Partition", perfdata.AllInstances, []string{ + physicalPagesAllocated, + preferredNUMANodeIndex, + remotePhysicalPages, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V VM Vid Partition collector: %w", err) + } + + c.physicalPagesAllocated = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vid_physical_pages_allocated"), + "The number of physical pages allocated", + []string{"vm"}, + nil, + ) + c.preferredNUMANodeIndex = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vid_preferred_numa_node_index"), + "The preferred NUMA node index associated with this partition", + []string{"vm"}, + nil, + ) + c.remotePhysicalPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vid_remote_physical_pages"), + "The number of physical pages not allocated from the preferred NUMA node", + []string{"vm"}, + nil, + ) + + return nil +} + +func (c *Collector) collectVirtualMachine(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorVirtualMachineHealthSummary.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Virtual Machine Health Summary metrics: %w", err) + } else if len(data) == 0 { + return errors.New("perflib query for Hyper-V Virtual Machine Health Summary returned empty result set") + } + + healthData, ok := data[perftypes.EmptyInstance] + if !ok { + return errors.New("no data returned for Hyper-V Virtual Machine Health Summary") + } + + ch <- prometheus.MustNewConstMetric( + c.healthCritical, + prometheus.GaugeValue, + healthData[healthCritical].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.healthOk, + prometheus.GaugeValue, + healthData[healthOk].FirstValue, + ) + + data, err = c.perfDataCollectorVMVidPartition.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Virtual Machine Health Summary metrics: %w", err) + } else if len(data) == 0 { + return errors.New("perflib query for Hyper-V Virtual Machine Health Summary returned empty result set") + } + + for name, page := range data { + if strings.Contains(name, "*") { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.physicalPagesAllocated, + prometheus.GaugeValue, + page[physicalPagesAllocated].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.preferredNUMANodeIndex, + prometheus.GaugeValue, + page[preferredNUMANodeIndex].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.remotePhysicalPages, + prometheus.GaugeValue, + page[remotePhysicalPages].FirstValue, + name, + ) + } + + return nil +} From 18b4635ec8f9d3f49e86a4f6f57c8855e43e57e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Thu, 31 Oct 2024 16:53:19 +0100 Subject: [PATCH 02/12] hyperv: Added DataStore, Virtual SMB and Dynamic Memory Balancer metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- docs/collector.hyperv.md | 235 +++++---- internal/collector/hyperv/hyperv.go | 447 ++++-------------- .../collector/hyperv/hyperv_dynamic_memory.go | 1 - .../hyperv/hyperv_dynamic_memory_balancer.go | 112 +++++ .../hyperv/hyperv_dynamic_memory_vm.go | 204 ++++++++ .../hyperv/hyperv_virtual_machine.go | 142 ------ .../hyperv_virtual_machine_health_summary.go | 80 ++++ .../hyperv_virtual_machine_vid_partition.go | 90 ++++ internal/utils/utils.go | 8 + 9 files changed, 732 insertions(+), 587 deletions(-) delete mode 100644 internal/collector/hyperv/hyperv_dynamic_memory.go create mode 100644 internal/collector/hyperv/hyperv_dynamic_memory_balancer.go create mode 100644 internal/collector/hyperv/hyperv_dynamic_memory_vm.go delete mode 100644 internal/collector/hyperv/hyperv_virtual_machine.go create mode 100644 internal/collector/hyperv/hyperv_virtual_machine_health_summary.go create mode 100644 internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go diff --git a/docs/collector.hyperv.md b/docs/collector.hyperv.md index 0b799e6b5..d40a405af 100644 --- a/docs/collector.hyperv.md +++ b/docs/collector.hyperv.md @@ -2,11 +2,11 @@ The hyperv collector exposes metrics about the Hyper-V hypervisor -||| --|- -Metric name prefix | `hyperv` -Classes | `Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary`
`Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition`
`Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition`
`Win32_PerfRawData_HvStats_HyperVHypervisor`
`Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor`
`Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor`
`Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor`
`Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch`
`Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter`
`Win32_PerfRawData_Counters_HyperVVirtualStorageDevice`
`Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter` -Enabled by default? | No +| | | +|---------------------|----------------------| +| Metric name prefix | `hyperv` | +| Source | Performance counters | +| Enabled by default? | No | ## Flags @@ -14,98 +14,139 @@ None ## Metrics -Name | Description | Type | Labels ------|-------------|------|------- -`windows_hyperv_health_critical` | _Not yet documented_ | counter | None -`windows_hyperv_health_ok` | _Not yet documented_ | counter | None -`windows_hyperv_vid_physical_pages_allocated` | _Not yet documented_ | counter | `vm` -`windows_hyperv_vid_preferred_numa_node_index` | _Not yet documented_ | counter | `vm` -`windows_hyperv_vid_remote_physical_pages` | _Not yet documented_ | counter | `vm` -`windows_hyperv_root_partition_address_spaces` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_attached_devices` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_deposited_pages` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_device_dma_errors` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_device_interrupt_errors` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_device_interrupt_mappings` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_device_interrupt_throttle_events` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_preferred_numa_node_index` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_gpa_space_modifications` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_io_tlb_flush_cost` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_io_tlb_flush` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_recommended_virtual_tlb_size` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_physical_pages_allocated` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_1G_device_pages` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_1G_gpa_pages` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_2M_device_pages` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_2M_gpa_pages` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_4K_device_pages` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_4K_gpa_pages` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_virtual_tlb_flush_entires` | _Not yet documented_ | counter | None -`windows_hyperv_root_partition_virtual_tlb_pages` | _Not yet documented_ | counter | None -`windows_hyperv_hypervisor_virtual_processors` | _Not yet documented_ | counter | None -`windows_hyperv_hypervisor_logical_processors` | _Not yet documented_ | counter | None -`windows_hyperv_host_lp_guest_run_time_percent` | _Not yet documented_ | counter | `core` -`windows_hyperv_host_lp_hypervisor_run_time_percent` | _Not yet documented_ | counter | `core` -`windows_hyperv_host_lp_total_run_time_percent` | _Not yet documented_ | counter | `core` -`windows_hyperv_host_cpu_guest_run_time` | _Not yet documented_ | counter | `core` -`windows_hyperv_host_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `core` -`windows_hyperv_host_cpu_remote_run_time` | _Not yet documented_ | counter | `core` -`windows_hyperv_host_cpu_total_run_time` | _Not yet documented_ | counter | `core` -`windows_hyperv_host_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `core` -`windows_hyperv_vm_cpu_guest_run_time` | _Not yet documented_ | counter | `vm`, `core` -`windows_hyperv_vm_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `vm`, `core` -`windows_hyperv_vm_cpu_remote_run_time` | _Not yet documented_ | counter | `vm`, `core` -`windows_hyperv_vm_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `vm`, `core` -`windows_hyperv_vm_memory_added_total` | _Not yet documented_ | counter | `vm` -`windows_hyperv_vm_memory_pressure_average` | _Not yet documented_ | gauge | `vm` -`windows_hyperv_vm_memory_pressure_current` | _Not yet documented_ | counter | `vm` -`windows_hyperv_vm_memory_physical_guest_visible` | _Not yet documented_ | gauge | `vm` -`windows_hyperv_vm_memory_pressure_maximum` | _Not yet documented_ | gauge | `vm` -`windows_hyperv_vm_memory_add_operations_total` | _Not yet documented_ | counter | `vm` -`windows_hyperv_vm_memory_remove_operations_total` | _Not yet documented_ | counter | `vm` -`windows_hyperv_vm_memory_pressure_minumim` | _Not yet documented_ | gauge | `vm` -`windows_hyperv_vm_memory_physical` | _Not yet documented_ | gauge | `vm` -`windows_hyperv_vm_memory_removed_total` | _Not yet documented_ | counter | `vm` -`windows_hyperv_vm_cpu_total_run_time` | _Not yet documented_ | counter | `vm`, `core` -`windows_hyperv_vswitch_broadcast_packets_received_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_broadcast_packets_sent_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_bytes_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_bytes_received_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_bytes_sent_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_directed_packets_received_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_directed_packets_send_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_dropped_packets_incoming_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_dropped_packets_outcoming_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_extensions_dropped_packets_incoming_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_extensions_dropped_packets_outcoming_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_learned_mac_addresses_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_multicast_packets_received_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_multicast_packets_sent_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_number_of_send_channel_moves_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_number_of_vmq_moves_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_packets_flooded_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_packets_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_packets_received_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_packets_sent_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_vswitch_purged_mac_addresses_total` | _Not yet documented_ | counter | `vswitch` -`windows_hyperv_ethernet_bytes_dropped` | _Not yet documented_ | counter | `adapter` -`windows_hyperv_ethernet_bytes_received` | _Not yet documented_ | counter | `adapter` -`windows_hyperv_ethernet_bytes_sent` | _Not yet documented_ | counter | `adapter` -`windows_hyperv_ethernet_frames_dropped` | _Not yet documented_ | counter | `adapter` -`windows_hyperv_ethernet_frames_received` | _Not yet documented_ | counter | `adapter` -`windows_hyperv_ethernet_frames_sent` | _Not yet documented_ | counter | `adapter` -`windows_hyperv_vm_device_error_count` | _Not yet documented_ | counter | `vm_device` -`windows_hyperv_vm_device_queue_length` | _Not yet documented_ | counter | `vm_device` -`windows_hyperv_vm_device_bytes_read` | _Not yet documented_ | counter | `vm_device` -`windows_hyperv_vm_device_operations_read` | _Not yet documented_ | counter | `vm_device` -`windows_hyperv_vm_device_bytes_written` | _Not yet documented_ | counter | `vm_device` -`windows_hyperv_vm_device_operations_written` | _Not yet documented_ | counter | `vm_device` -`windows_hyperv_vm_interface_bytes_received` | _Not yet documented_ | counter | `vm_interface` -`windows_hyperv_vm_interface_bytes_sent` | _Not yet documented_ | counter | `vm_interface` -`windows_hyperv_vm_interface_packets_incoming_dropped` | _Not yet documented_ | counter | `vm_interface` -`windows_hyperv_vm_interface_packets_outgoing_dropped` | _Not yet documented_ | counter | `vm_interface` -`windows_hyperv_vm_interface_packets_received` | _Not yet documented_ | counter | `vm_interface` -`windows_hyperv_vm_interface_packets_sent` | _Not yet documented_ | counter | `vm_interface` +### All + +| Name | Description | Type | Labels | +|---------------------------------------------------------------------|----------------------|---------|----------------| +| `windows_hyperv_health_critical` | _Not yet documented_ | counter | None | +| `windows_hyperv_health_ok` | _Not yet documented_ | counter | None | +| `windows_hyperv_vid_physical_pages_allocated` | _Not yet documented_ | counter | `vm` | +| `windows_hyperv_vid_preferred_numa_node_index` | _Not yet documented_ | counter | `vm` | +| `windows_hyperv_vid_remote_physical_pages` | _Not yet documented_ | counter | `vm` | +| `windows_hyperv_root_partition_address_spaces` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_attached_devices` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_deposited_pages` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_device_dma_errors` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_device_interrupt_errors` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_device_interrupt_mappings` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_device_interrupt_throttle_events` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_preferred_numa_node_index` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_gpa_space_modifications` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_io_tlb_flush_cost` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_io_tlb_flush` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_recommended_virtual_tlb_size` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_physical_pages_allocated` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_1G_device_pages` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_1G_gpa_pages` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_2M_device_pages` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_2M_gpa_pages` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_4K_device_pages` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_4K_gpa_pages` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_virtual_tlb_flush_entires` | _Not yet documented_ | counter | None | +| `windows_hyperv_root_partition_virtual_tlb_pages` | _Not yet documented_ | counter | None | +| `windows_hyperv_hypervisor_virtual_processors` | _Not yet documented_ | counter | None | +| `windows_hyperv_hypervisor_logical_processors` | _Not yet documented_ | counter | None | +| `windows_hyperv_host_lp_guest_run_time_percent` | _Not yet documented_ | counter | `core` | +| `windows_hyperv_host_lp_hypervisor_run_time_percent` | _Not yet documented_ | counter | `core` | +| `windows_hyperv_host_lp_total_run_time_percent` | _Not yet documented_ | counter | `core` | +| `windows_hyperv_host_cpu_guest_run_time` | _Not yet documented_ | counter | `core` | +| `windows_hyperv_host_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `core` | +| `windows_hyperv_host_cpu_remote_run_time` | _Not yet documented_ | counter | `core` | +| `windows_hyperv_host_cpu_total_run_time` | _Not yet documented_ | counter | `core` | +| `windows_hyperv_host_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `core` | +| `windows_hyperv_vm_cpu_guest_run_time` | _Not yet documented_ | counter | `vm`, `core` | +| `windows_hyperv_vm_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `vm`, `core` | +| `windows_hyperv_vm_cpu_remote_run_time` | _Not yet documented_ | counter | `vm`, `core` | +| `windows_hyperv_vm_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `vm`, `core` | +| `windows_hyperv_vm_cpu_total_run_time` | _Not yet documented_ | counter | `vm`, `core` | +| `windows_hyperv_vswitch_broadcast_packets_received_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_broadcast_packets_sent_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_bytes_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_bytes_received_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_bytes_sent_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_directed_packets_received_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_directed_packets_send_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_dropped_packets_incoming_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_dropped_packets_outcoming_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_extensions_dropped_packets_incoming_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_extensions_dropped_packets_outcoming_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_learned_mac_addresses_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_multicast_packets_received_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_multicast_packets_sent_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_number_of_send_channel_moves_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_number_of_vmq_moves_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_flooded_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_received_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_sent_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_vswitch_purged_mac_addresses_total` | _Not yet documented_ | counter | `vswitch` | +| `windows_hyperv_ethernet_bytes_dropped` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_ethernet_bytes_received` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_ethernet_bytes_sent` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_ethernet_frames_dropped` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_ethernet_frames_received` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_ethernet_frames_sent` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_vm_device_error_count` | _Not yet documented_ | counter | `vm_device` | +| `windows_hyperv_vm_device_queue_length` | _Not yet documented_ | counter | `vm_device` | +| `windows_hyperv_vm_device_bytes_read` | _Not yet documented_ | counter | `vm_device` | +| `windows_hyperv_vm_device_operations_read` | _Not yet documented_ | counter | `vm_device` | +| `windows_hyperv_vm_device_bytes_written` | _Not yet documented_ | counter | `vm_device` | +| `windows_hyperv_vm_device_operations_written` | _Not yet documented_ | counter | `vm_device` | +| `windows_hyperv_vm_interface_bytes_received` | _Not yet documented_ | counter | `vm_interface` | +| `windows_hyperv_vm_interface_bytes_sent` | _Not yet documented_ | counter | `vm_interface` | +| `windows_hyperv_vm_interface_packets_incoming_dropped` | _Not yet documented_ | counter | `vm_interface` | +| `windows_hyperv_vm_interface_packets_outgoing_dropped` | _Not yet documented_ | counter | `vm_interface` | +| `windows_hyperv_vm_interface_packets_received` | _Not yet documented_ | counter | `vm_interface` | +| `windows_hyperv_vm_interface_packets_sent` | _Not yet documented_ | counter | `vm_interface` | + + + + + +### Hyper-V Dynamic Memory Balancer + +Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012 + +| Name | Description | Type | Labels | +|-------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|-------|------------| +| `windows_hyperv_dynamic_memory_balancer_available_memory_bytes` | This counter represents the amount of memory left on the node. | gauge | `balancer` | +| `windows_hyperv_dynamic_memory_balancer_available_memory_for_balancing_bytes` | This counter represents the available memory for balancing purposes. | gauge | `balancer` | +| `windows_hyperv_dynamic_memory_balancer_average_pressure_ratio` | This counter represents the average system pressure on the balancer node among all balanced objects. | gauge | `balancer` | +| `windows_hyperv_dynamic_memory_balancer_system_current_pressure_ratio` | This counter represents the current pressure in the system. | gauge | `balancer` | + + +### Hyper-V Dynamic Memory VM + + +| Name | Description | Type | Labels | +|------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|---------|--------| +| `windows_hyperv_dynamic_memory_vm_added_bytes_total` | This counter represents the cummulative amount of memory added to the VM. | counter | `vm` | +| `windows_hyperv_dynamic_memory_vm_pressure_current_ratio` | This counter represents the current pressure in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_guest_available_bytes` | This counter represents the current amount of available memory in the VM (reported by the VM). | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_guest_visible_physical_memory_bytes` | This counter represents the amount of memory visible in the VM | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_pressure_maximum_ratio` | This counter represents the maximum pressure band in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_add_operations_total` | This counter represents the total number of add operations for the VM. | counter | `vm` | +| `windows_hyperv_dynamic_memory_vm_remove_operations_total` | This counter represents the total number of remove operations for the VM. | counter | `vm` | +| `windows_hyperv_dynamic_memory_vm_pressure_minimum_ratio` | This counter represents the minimum pressure band in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_physical` | This counter represents the current amount of memory in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_removed_bytes_total` | This counter represents the cummulative amount of memory removed from the VM. | counter | `vm` | + +### Hyper-V VM Vid Partition + +| Name | Description | Type | Labels | +|------------------------------------------------|-------------------------------------------------------------------------|-------|--------| +| `windows_hyperv_vid_physical_pages_allocated` | The number of physical pages allocated | gauge | `vm` | +| `windows_hyperv_vid_preferred_numa_node_index` | The preferred NUMA node index associated with this partition | gauge | `vm` | +| `windows_hyperv_vid_remote_physical_pages` | The number of physical pages not allocated from the preferred NUMA node | gauge | `vm` | + + +### HyperHyper-V Virtual Machine Health Summary + +| Name | Description | Type | Labels | +|----------------------------------|-----------------------------------------------------------------------------|-------|--------| +| `windows_hyperv_health_critical` | This counter represents the number of virtual machines with critical health | gauge | None | +| `windows_hyperv_health_ok` | This counter represents the number of virtual machines with ok health | gauge | None | + ### Example metric _This collector does not yet have explained examples, we would appreciate your help adding them!_ diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index 04dfdeeaa..824c07479 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -9,7 +9,6 @@ import ( "strings" "github.com/alecthomas/kingpin/v2" - "github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" "github.com/yusufpapurcu/wmi" @@ -25,16 +24,10 @@ var ConfigDefaults = Config{} type Collector struct { config Config - // Hyper-V Virtual Machine Health Summa metrics - perfDataCollectorVirtualMachineHealthSummary perfdata.Collector - healthCritical *prometheus.Desc // \Hyper-V Virtual Machine Health Summary\Health Critical - healthOk *prometheus.Desc // \Hyper-V Virtual Machine Health Summary\Health Ok - - // Hyper-V VM Vid Partition metadata - perfDataCollectorVMVidPartition perfdata.Collector - physicalPagesAllocated *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Physical Pages Allocated - preferredNUMANodeIndex *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Preferred NUMA Node Index - remotePhysicalPages *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Remote Physical Pages + collectorDynamicMemoryBalancer + collectorDynamicMemoryVM + collectorVirtualMachineHealthSummary + collectorVirtualMachineVidPartition // Hyper-V Hypervisor Root Partition metrics addressSpaces *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Address Spaces @@ -122,25 +115,6 @@ type Collector struct { vmStoragePacketsReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Received/sec vmStoragePacketsSent *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Sent/sec - // Hyper-V Dynamic Memory VM metrics - vmMemoryAddedMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Added Memory - vmMemoryAveragePressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Average Pressure - vmMemoryCurrentPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Current Pressure - vmMemoryGuestVisiblePhysicalMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Guest Visible Physical Memory - vmMemoryMaximumPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Maximum Pressure - vmMemoryMemoryAddOperations *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Memory Add Operations - vmMemoryMemoryRemoveOperations *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Memory Remove Operations - vmMemoryMinimumPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Minimum Pressure - vmMemoryPhysicalMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Physical Memory - vmMemoryRemovedMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Removed Memory - // TODO: \Hyper-V Dynamic Memory VM(*)\Guest Available Memory - - // Hyper-V Dynamic Memory Balancer metrics - // TODO: \Hyper-V Dynamic Memory Balancer(*)\Available Memory For Balancing - // TODO: \Hyper-V Dynamic Memory Balancer(*)\System Current Pressure - // TODO: \Hyper-V Dynamic Memory Balancer(*)\Available Memory - // TODO: \Hyper-V Dynamic Memory Balancer(*)\Average Pressure - // Hyper-V Virtual Storage Device metrics vmStorageErrorCount *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Error Count vmStorageQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Queue Length @@ -262,134 +236,144 @@ func (c *Collector) Close(_ *slog.Logger) error { } func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { - if err := c.buildVirtualMachine(); err != nil { + if err := c.buildDynamicMemoryBalancer(); err != nil { + return err + } + + if err := c.buildDynamicMemoryVM(); err != nil { return err } - buildSubsystemName := func(component string) string { return "hyperv_" + component } + if err := c.buildDynamicMemoryVM(); err != nil { + return err + } + + if err := c.buildDynamicMemoryBalancer(); err != nil { + return err + } c.addressSpaces = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "address_spaces"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_address_spaces"), "The number of address spaces in the virtual TLB of the partition", nil, nil, ) c.attachedDevices = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "attached_devices"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_attached_devices"), "The number of devices attached to the partition", nil, nil, ) c.depositedPages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "deposited_pages"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_deposited_pages"), "The number of pages deposited into the partition", nil, nil, ) c.deviceDMAErrors = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "device_dma_errors"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_dma_errors"), "An indicator of illegal DMA requests generated by all devices assigned to the partition", nil, nil, ) c.deviceInterruptErrors = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "device_interrupt_errors"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_errors"), "An indicator of illegal interrupt requests generated by all devices assigned to the partition", nil, nil, ) c.deviceInterruptMappings = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "device_interrupt_mappings"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_mappings"), "The number of device interrupt mappings used by the partition", nil, nil, ) c.deviceInterruptThrottleEvents = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "device_interrupt_throttle_events"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_throttle_events"), "The number of times an interrupt from a device assigned to the partition was temporarily throttled because the device was generating too many interrupts", nil, nil, ) c.gpaPages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "preferred_numa_node_index"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_preferred_numa_node_index"), "The number of pages present in the GPA space of the partition (zero for root partition)", nil, nil, ) c.gpaSpaceModifications = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "gpa_space_modifications"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_gpa_space_modifications"), "The rate of modifications to the GPA space of the partition", nil, nil, ) c.ioTLBFlushCost = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "io_tlb_flush_cost"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_io_tlb_flush_cost"), "The average time (in nanoseconds) spent processing an I/O TLB flush", nil, nil, ) c.ioTLBFlushes = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "io_tlb_flush"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_io_tlb_flush"), "The rate of flushes of I/O TLBs of the partition", nil, nil, ) c.recommendedVirtualTLBSize = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "recommended_virtual_tlb_size"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_recommended_virtual_tlb_size"), "The recommended number of pages to be deposited for the virtual TLB", nil, nil, ) c.skippedTimerTicks = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "physical_pages_allocated"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_physical_pages_allocated"), "The number of timer interrupts skipped for the partition", nil, nil, ) c.value1Gdevicepages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "1G_device_pages"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_1G_device_pages"), "The number of 1G pages present in the device space of the partition", nil, nil, ) c.value1GGPApages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "1G_gpa_pages"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_1G_gpa_pages"), "The number of 1G pages present in the GPA space of the partition", nil, nil, ) c.value2Mdevicepages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "2M_device_pages"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_2M_device_pages"), "The number of 2M pages present in the device space of the partition", nil, nil, ) c.value2MGPApages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "2M_gpa_pages"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_2M_gpa_pages"), "The number of 2M pages present in the GPA space of the partition", nil, nil, ) c.value4Kdevicepages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "4K_device_pages"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_4K_device_pages"), "The number of 4K pages present in the device space of the partition", nil, nil, ) c.value4KGPApages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "4K_gpa_pages"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_4K_gpa_pages"), "The number of 4K pages present in the GPA space of the partition", nil, nil, ) c.virtualTLBFlushEntires = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "virtual_tlb_flush_entires"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_flush_entires"), "The rate of flushes of the entire virtual TLB", nil, nil, ) c.virtualTLBPages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "virtual_tlb_pages"), + prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_pages"), "The number of pages used by the virtual TLB of the partition", nil, nil, @@ -398,13 +382,13 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { // c.virtualProcessors = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("hypervisor"), "virtual_processors"), + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processors"), "The number of virtual processors present in the system", nil, nil, ) c.logicalProcessors = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("hypervisor"), "logical_processors"), + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_logical_processors"), "The number of logical processors present in the system", nil, nil, @@ -413,19 +397,19 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { // c.hostLPGuestRunTimePercent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_lp"), "guest_run_time_percent"), + prometheus.BuildFQName(types.Namespace, Name, "host_lp_guest_run_time_percent"), "The percentage of time spent by the processor in guest code", []string{"core"}, nil, ) c.hostLPHypervisorRunTimePercent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_lp"), "hypervisor_run_time_percent"), + prometheus.BuildFQName(types.Namespace, Name, "host_lp_hypervisor_run_time_percent"), "The percentage of time spent by the processor in hypervisor code", []string{"core"}, nil, ) c.hostLPTotalRunTimePercent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_lp"), "total_run_time_percent"), + prometheus.BuildFQName(types.Namespace, Name, "host_lp_total_run_time_percent"), "The percentage of time spent by the processor in guest and hypervisor code", []string{"core"}, nil, @@ -434,31 +418,31 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { // c.hostGuestRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_cpu"), "guest_run_time"), + prometheus.BuildFQName(types.Namespace, Name, "host_cpu_guest_run_time"), "The time spent by the virtual processor in guest code", []string{"core"}, nil, ) c.hostHypervisorRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_cpu"), "hypervisor_run_time"), + prometheus.BuildFQName(types.Namespace, Name, "host_cpu_hypervisor_run_time"), "The time spent by the virtual processor in hypervisor code", []string{"core"}, nil, ) c.hostRemoteRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_cpu"), "remote_run_time"), + prometheus.BuildFQName(types.Namespace, Name, "host_cpu_remote_run_time"), "The time spent by the virtual processor running on a remote node", []string{"core"}, nil, ) c.hostTotalRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_cpu"), "total_run_time"), + prometheus.BuildFQName(types.Namespace, Name, "host_cpu_total_run_time"), "The time spent by the virtual processor in guest and hypervisor code", []string{"core"}, nil, ) c.hostCPUWaitTimePerDispatch = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_cpu"), "wait_time_per_dispatch_total"), + prometheus.BuildFQName(types.Namespace, Name, "host_cpu_wait_time_per_dispatch_total"), "Time in nanoseconds waiting for a virtual processor to be dispatched onto a logical processor", []string{"core"}, nil, @@ -467,31 +451,31 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { // c.vmGuestRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_cpu"), "guest_run_time"), + prometheus.BuildFQName(types.Namespace, Name, "vm_cpu_guest_run_time"), "The time spent by the virtual processor in guest code", []string{"vm", "core"}, nil, ) c.vmHypervisorRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_cpu"), "hypervisor_run_time"), + prometheus.BuildFQName(types.Namespace, Name, "vm_cpu_hypervisor_run_time"), "The time spent by the virtual processor in hypervisor code", []string{"vm", "core"}, nil, ) c.vmRemoteRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_cpu"), "remote_run_time"), + prometheus.BuildFQName(types.Namespace, Name, "vm_cpu_remote_run_time"), "The time spent by the virtual processor running on a remote node", []string{"vm", "core"}, nil, ) c.vmTotalRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_cpu"), "total_run_time"), + prometheus.BuildFQName(types.Namespace, Name, "vm_cpu_total_run_time"), "The time spent by the virtual processor in guest and hypervisor code", []string{"vm", "core"}, nil, ) c.vmCPUWaitTimePerDispatch = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_cpu"), "wait_time_per_dispatch_total"), + prometheus.BuildFQName(types.Namespace, Name, "vm_cpu_wait_time_per_dispatch_total"), "Time in nanoseconds waiting for a virtual processor to be dispatched onto a logical processor", []string{"vm", "core"}, nil, @@ -499,127 +483,127 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { // c.broadcastPacketsReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "broadcast_packets_received_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_broadcast_packets_received_total"), "This represents the total number of broadcast packets received per second by the virtual switch", []string{"vswitch"}, nil, ) c.broadcastPacketsSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "broadcast_packets_sent_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_broadcast_packets_sent_total"), "This represents the total number of broadcast packets sent per second by the virtual switch", []string{"vswitch"}, nil, ) c.bytes = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "bytes_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_total"), "This represents the total number of bytes per second traversing the virtual switch", []string{"vswitch"}, nil, ) c.bytesReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "bytes_received_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_received_total"), "This represents the total number of bytes received per second by the virtual switch", []string{"vswitch"}, nil, ) c.bytesSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "bytes_sent_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_sent_total"), "This represents the total number of bytes sent per second by the virtual switch", []string{"vswitch"}, nil, ) c.directedPacketsReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "directed_packets_received_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_directed_packets_received_total"), "This represents the total number of directed packets received per second by the virtual switch", []string{"vswitch"}, nil, ) c.directedPacketsSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "directed_packets_send_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_directed_packets_send_total"), "This represents the total number of directed packets sent per second by the virtual switch", []string{"vswitch"}, nil, ) c.droppedPacketsIncoming = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "dropped_packets_incoming_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_dropped_packets_incoming_total"), "This represents the total number of packet dropped per second by the virtual switch in the incoming direction", []string{"vswitch"}, nil, ) c.droppedPacketsOutgoing = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "dropped_packets_outcoming_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_dropped_packets_outcoming_total"), "This represents the total number of packet dropped per second by the virtual switch in the outgoing direction", []string{"vswitch"}, nil, ) c.extensionsDroppedPacketsIncoming = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "extensions_dropped_packets_incoming_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_extensions_dropped_packets_incoming_total"), "This represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction", []string{"vswitch"}, nil, ) c.extensionsDroppedPacketsOutgoing = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "extensions_dropped_packets_outcoming_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_extensions_dropped_packets_outcoming_total"), "This represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction", []string{"vswitch"}, nil, ) c.learnedMacAddresses = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "learned_mac_addresses_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_learned_mac_addresses_total"), "This counter represents the total number of learned MAC addresses of the virtual switch", []string{"vswitch"}, nil, ) c.multicastPacketsReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "multicast_packets_received_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_multicast_packets_received_total"), "This represents the total number of multicast packets received per second by the virtual switch", []string{"vswitch"}, nil, ) c.multicastPacketsSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "multicast_packets_sent_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_multicast_packets_sent_total"), "This represents the total number of multicast packets sent per second by the virtual switch", []string{"vswitch"}, nil, ) c.numberOfSendChannelMoves = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "number_of_send_channel_moves_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_number_of_send_channel_moves_total"), "This represents the total number of send channel moves per second on this virtual switch", []string{"vswitch"}, nil, ) c.numberOfVMQMoves = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "number_of_vmq_moves_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_number_of_vmq_moves_total"), "This represents the total number of VMQ moves per second on this virtual switch", []string{"vswitch"}, nil, ) c.packetsFlooded = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "packets_flooded_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_flooded_total"), "This counter represents the total number of packets flooded by the virtual switch", []string{"vswitch"}, nil, ) c.packets = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "packets_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_total"), "This represents the total number of packets per second traversing the virtual switch", []string{"vswitch"}, nil, ) c.packetsReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "packets_received_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_received_total"), "This represents the total number of packets received per second by the virtual switch", []string{"vswitch"}, nil, ) c.packetsSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "packets_sent_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_sent_total"), "This represents the total number of packets send per second by the virtual switch", []string{"vswitch"}, nil, ) c.purgedMacAddresses = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "purged_mac_addresses_total"), + prometheus.BuildFQName(types.Namespace, Name, "vswitch_purged_mac_addresses_total"), "This counter represents the total number of purged MAC addresses of the virtual switch", []string{"vswitch"}, nil, @@ -628,37 +612,37 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { // c.adapterBytesDropped = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "bytes_dropped"), + prometheus.BuildFQName(types.Namespace, Name, "ethernet_bytes_dropped"), "Bytes Dropped is the number of bytes dropped on the network adapter", []string{"adapter"}, nil, ) c.adapterBytesReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "bytes_received"), + prometheus.BuildFQName(types.Namespace, Name, "ethernet_bytes_received"), "Bytes received is the number of bytes received on the network adapter", []string{"adapter"}, nil, ) c.adapterBytesSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "bytes_sent"), + prometheus.BuildFQName(types.Namespace, Name, "ethernet_bytes_sent"), "Bytes sent is the number of bytes sent over the network adapter", []string{"adapter"}, nil, ) c.adapterFramesDropped = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "frames_dropped"), + prometheus.BuildFQName(types.Namespace, Name, "ethernet_frames_dropped"), "Frames Dropped is the number of frames dropped on the network adapter", []string{"adapter"}, nil, ) c.adapterFramesReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "frames_received"), + prometheus.BuildFQName(types.Namespace, Name, "ethernet_frames_received"), "Frames received is the number of frames received on the network adapter", []string{"adapter"}, nil, ) c.adapterFramesSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "frames_sent"), + prometheus.BuildFQName(types.Namespace, Name, "ethernet_frames_sent"), "Frames sent is the number of frames sent over the network adapter", []string{"adapter"}, nil, @@ -667,37 +651,37 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { // c.vmStorageErrorCount = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "error_count"), + prometheus.BuildFQName(types.Namespace, Name, "vm_device_error_count"), "This counter represents the total number of errors that have occurred on this virtual device", []string{"vm_device"}, nil, ) c.vmStorageQueueLength = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "queue_length"), + prometheus.BuildFQName(types.Namespace, Name, "vm_device_queue_length"), "This counter represents the current queue length on this virtual device", []string{"vm_device"}, nil, ) c.vmStorageReadBytes = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "bytes_read"), + prometheus.BuildFQName(types.Namespace, Name, "vm_device_bytes_read"), "This counter represents the total number of bytes that have been read per second on this virtual device", []string{"vm_device"}, nil, ) c.vmStorageReadOperations = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "operations_read"), + prometheus.BuildFQName(types.Namespace, Name, "vm_device_operations_read"), "This counter represents the number of read operations that have occurred per second on this virtual device", []string{"vm_device"}, nil, ) c.vmStorageWriteBytes = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "bytes_written"), + prometheus.BuildFQName(types.Namespace, Name, "vm_device_bytes_written"), "This counter represents the total number of bytes that have been written per second on this virtual device", []string{"vm_device"}, nil, ) c.vmStorageWriteOperations = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "operations_written"), + prometheus.BuildFQName(types.Namespace, Name, "vm_device_operations_written"), "This counter represents the number of write operations that have occurred per second on this virtual device", []string{"vm_device"}, nil, @@ -706,195 +690,64 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { // c.vmStorageBytesReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "bytes_received"), + prometheus.BuildFQName(types.Namespace, Name, "vm_interface_bytes_received"), "This counter represents the total number of bytes received per second by the network adapter", []string{"vm_interface"}, nil, ) c.vmStorageBytesSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "bytes_sent"), + prometheus.BuildFQName(types.Namespace, Name, "vm_interface_bytes_sent"), "This counter represents the total number of bytes sent per second by the network adapter", []string{"vm_interface"}, nil, ) c.vmStorageDroppedPacketsIncoming = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "packets_incoming_dropped"), + prometheus.BuildFQName(types.Namespace, Name, "vm_interface_packets_incoming_dropped"), "This counter represents the total number of dropped packets per second in the incoming direction of the network adapter", []string{"vm_interface"}, nil, ) c.vmStorageDroppedPacketsOutgoing = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "packets_outgoing_dropped"), + prometheus.BuildFQName(types.Namespace, Name, "vm_interface_packets_outgoing_dropped"), "This counter represents the total number of dropped packets per second in the outgoing direction of the network adapter", []string{"vm_interface"}, nil, ) c.vmStoragePacketsReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "packets_received"), + prometheus.BuildFQName(types.Namespace, Name, "vm_interface_packets_received"), "This counter represents the total number of packets received per second by the network adapter", []string{"vm_interface"}, nil, ) c.vmStoragePacketsSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "packets_sent"), + prometheus.BuildFQName(types.Namespace, Name, "vm_interface_packets_sent"), "This counter represents the total number of packets sent per second by the network adapter", []string{"vm_interface"}, nil, ) - // - - c.vmMemoryAddedMemory = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "added_total"), - "This counter represents memory in MB added to the VM", - []string{"vm"}, - nil, - ) - c.vmMemoryAveragePressure = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "pressure_average"), - "This gauge represents the average pressure in the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryCurrentPressure = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "pressure_current"), - "This gauge represents the current pressure in the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryGuestVisiblePhysicalMemory = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "physical_guest_visible"), - "'This gauge represents the amount of memory in MB visible to the VM guest.'", - []string{"vm"}, - nil, - ) - c.vmMemoryMaximumPressure = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "pressure_maximum"), - "This gauge represents the maximum pressure band in the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryMemoryAddOperations = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "add_operations_total"), - "This counter represents the number of operations adding memory to the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryMemoryRemoveOperations = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "remove_operations_total"), - "This counter represents the number of operations removing memory from the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryMinimumPressure = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "pressure_minimum"), - "This gauge represents the minimum pressure band in the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryPhysicalMemory = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "physical"), - "This gauge represents the current amount of memory in MB assigned to the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryRemovedMemory = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "removed_total"), - "This counter represents memory in MB removed from the VM", - []string{"vm"}, - nil, - ) - return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error { - errs := make([]error, 0) + errs := make([]error, 0, 4) - if err := c.collectVirtualMachine(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting hyperV health status metrics: %w", err)) + if err := c.collectDynamicMemoryBalancer(ch); err != nil { + errs = append(errs, fmt.Errorf("failed collecting Hyper-V Dynamic Memory Balancer metrics: %w", err)) } - if err := c.collectVmHv(ch); err != nil { - logger.Error("failed collecting hyperV hv status metrics", - slog.Any("err", err), - ) - - return err + if err := c.collectDynamicMemoryVM(ch); err != nil { + errs = append(errs, fmt.Errorf("failed collecting Hyper-V Dynamic Memory VM metrics: %w", err)) } - if err := c.collectVmProcessor(ch); err != nil { - logger.Error("failed collecting hyperV processor metrics", - slog.Any("err", err), - ) - - return err - } - - if err := c.collectHostLPUsage(logger, ch); err != nil { - logger.Error("failed collecting hyperV host logical processors metrics", - slog.Any("err", err), - ) - - return err - } - - if err := c.collectHostCpuUsage(logger, ch); err != nil { - logger.Error("failed collecting hyperV host CPU metrics", - slog.Any("err", err), - ) - - return err + if err := c.collectVirtualMachineHealthSummary(ch); err != nil { + errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Machine Health Summary metrics: %w", err)) } - if err := c.collectVmCpuUsage(logger, ch); err != nil { - logger.Error("failed collecting hyperV VM CPU metrics", - slog.Any("err", err), - ) - - return err - } - - if err := c.collectVmSwitch(ch); err != nil { - logger.Error("failed collecting hyperV switch metrics", - slog.Any("err", err), - ) - - return err - } - - if err := c.collectVmEthernet(ch); err != nil { - logger.Error("failed collecting hyperV ethernet metrics", - slog.Any("err", err), - ) - - return err - } - - if err := c.collectVmStorage(ch); err != nil { - logger.Error("failed collecting hyperV virtual storage metrics", - slog.Any("err", err), - ) - - return err - } - - if err := c.collectVmNetwork(ch); err != nil { - logger.Error("failed collecting hyperV virtual network metrics", - slog.Any("err", err), - ) - - return err - } - - if err := c.collectVmMemory(ch); err != nil { - logger.Error("failed collecting hyperV virtual memory metrics", - slog.Any("err", err), - ) - - return err + if err := c.collectVirtualMachineVidPartition(ch); err != nil { + errs = append(errs, fmt.Errorf("failed collecting Hyper-V VM Vid Partition metrics: %w", err)) } return errors.Join(errs...) @@ -1672,103 +1525,3 @@ func (c *Collector) collectVmNetwork(ch chan<- prometheus.Metric) error { return nil } - -// Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM ... -type Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM struct { - Name string - AddedMemory uint64 - AveragePressure uint64 - CurrentPressure uint64 - GuestVisiblePhysicalMemory uint64 - MaximumPressure uint64 - MemoryAddOperations uint64 - MemoryRemoveOperations uint64 - MinimumPressure uint64 - PhysicalMemory uint64 - RemovedMemory uint64 -} - -func (c *Collector) collectVmMemory(ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM - if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM", &dst); err != nil { - return err - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "*") { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.vmMemoryAddedMemory, - prometheus.CounterValue, - float64(obj.AddedMemory), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmMemoryAveragePressure, - prometheus.GaugeValue, - float64(obj.AveragePressure), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmMemoryCurrentPressure, - prometheus.GaugeValue, - float64(obj.CurrentPressure), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmMemoryGuestVisiblePhysicalMemory, - prometheus.GaugeValue, - float64(obj.GuestVisiblePhysicalMemory), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmMemoryMaximumPressure, - prometheus.GaugeValue, - float64(obj.MaximumPressure), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmMemoryMemoryAddOperations, - prometheus.CounterValue, - float64(obj.MemoryAddOperations), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmMemoryMemoryRemoveOperations, - prometheus.CounterValue, - float64(obj.MemoryRemoveOperations), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmMemoryMinimumPressure, - prometheus.GaugeValue, - float64(obj.MinimumPressure), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmMemoryPhysicalMemory, - prometheus.GaugeValue, - float64(obj.PhysicalMemory), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmMemoryRemovedMemory, - prometheus.CounterValue, - float64(obj.RemovedMemory), - obj.Name, - ) - } - - return nil -} diff --git a/internal/collector/hyperv/hyperv_dynamic_memory.go b/internal/collector/hyperv/hyperv_dynamic_memory.go deleted file mode 100644 index 568364523..000000000 --- a/internal/collector/hyperv/hyperv_dynamic_memory.go +++ /dev/null @@ -1 +0,0 @@ -package hyperv diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go new file mode 100644 index 000000000..4d84bc77c --- /dev/null +++ b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go @@ -0,0 +1,112 @@ +package hyperv + +import ( + "errors" + "fmt" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus-community/windows_exporter/internal/utils" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorDynamicMemoryBalancer Hyper-V Dynamic Memory Balancer metrics +type collectorDynamicMemoryBalancer struct { + perfDataCollectorDynamicMemoryBalancer perfdata.Collector + vmDynamicMemoryBalancerAvailableMemoryForBalancing *prometheus.Desc // \Hyper-V Dynamic Memory Balancer(*)\Available Memory For Balancing + vmDynamicMemoryBalancerSystemCurrentPressure *prometheus.Desc // \Hyper-V Dynamic Memory Balancer(*)\System Current Pressure + vmDynamicMemoryBalancerAvailableMemory *prometheus.Desc // \Hyper-V Dynamic Memory Balancer(*)\Available Memory + vmDynamicMemoryBalancerAveragePressure *prometheus.Desc // \Hyper-V Dynamic Memory Balancer(*)\Average Pressure +} + +const ( + // Hyper-V Dynamic Memory Balancer metrics + vmDynamicMemoryBalancerAvailableMemory = "Available Memory" + vmDynamicMemoryBalancerAvailableMemoryForBalancing = "Available Memory For Balancing" + vmDynamicMemoryBalancerAveragePressure = "Average Pressure" + vmDynamicMemoryBalancerSystemCurrentPressure = "System Current Pressure" +) + +func (c *Collector) buildDynamicMemoryBalancer() error { + var err error + + // https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012 + c.perfDataCollectorDynamicMemoryBalancer, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Dynamic Memory Balancer", perfdata.AllInstances, []string{ + vmDynamicMemoryBalancerAvailableMemory, + vmDynamicMemoryBalancerAvailableMemoryForBalancing, + vmDynamicMemoryBalancerAveragePressure, + vmDynamicMemoryBalancerSystemCurrentPressure, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err) + } + + c.vmDynamicMemoryBalancerAvailableMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_available_memory_bytes"), + "This counter represents the amount of memory left on the node.", + []string{"balancer"}, + nil, + ) + c.vmDynamicMemoryBalancerAvailableMemoryForBalancing = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_available_memory_for_balancing_bytes"), + "This counter represents the available memory for balancing purposes.", + []string{"balancer"}, + nil, + ) + c.vmDynamicMemoryBalancerAveragePressure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_average_pressure_ratio"), + "This counter represents the average system pressure on the balancer node among all balanced objects.", + []string{"balancer"}, + nil, + ) + c.vmDynamicMemoryBalancerSystemCurrentPressure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_system_current_pressure_ratio"), + "This counter represents the current pressure in the system.", + []string{"balancer"}, + nil, + ) + + return nil +} + +func (c *Collector) collectDynamicMemoryBalancer(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorDynamicMemoryBalancer.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Dynamic Memory Balancer metrics: %w", err) + } else if len(data) == 0 { + return errors.New("perflib query for Hyper-V Dynamic Memory Balancer returned empty result set") + } + + for name, page := range data { + ch <- prometheus.MustNewConstMetric( + c.vmDynamicMemoryBalancerAvailableMemory, + prometheus.GaugeValue, + utils.MBToBytes(page[vmDynamicMemoryBalancerAvailableMemory].FirstValue), + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmDynamicMemoryBalancerAvailableMemoryForBalancing, + prometheus.GaugeValue, + utils.MBToBytes(page[vmDynamicMemoryBalancerAvailableMemoryForBalancing].FirstValue), + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmDynamicMemoryBalancerAveragePressure, + prometheus.GaugeValue, + utils.PercentageToRatio(page[vmDynamicMemoryBalancerAveragePressure].FirstValue), + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmDynamicMemoryBalancerSystemCurrentPressure, + prometheus.GaugeValue, + utils.PercentageToRatio(page[vmDynamicMemoryBalancerSystemCurrentPressure].FirstValue), + name, + ) + } + + return nil +} diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go new file mode 100644 index 000000000..a25e0f53d --- /dev/null +++ b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go @@ -0,0 +1,204 @@ +package hyperv + +import ( + "fmt" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus-community/windows_exporter/internal/utils" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorDynamicMemoryVM Hyper-V Dynamic Memory VM metrics +type collectorDynamicMemoryVM struct { + perfDataCollectorDynamicMemoryVM perfdata.Collector + vmMemoryAddedMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Added Memory + vmMemoryCurrentPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Current Pressure + vmMemoryGuestVisiblePhysicalMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Guest Visible Physical Memory + vmMemoryMaximumPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Maximum Pressure + vmMemoryMemoryAddOperations *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Memory Add Operations + vmMemoryMemoryRemoveOperations *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Memory Remove Operations + vmMemoryMinimumPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Minimum Pressure + vmMemoryPhysicalMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Physical Memory + vmMemoryRemovedMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Removed Memory + vmMemoryGuestAvailableMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Guest Available Memory +} + +const ( + // Hyper-V Dynamic Memory VM metrics + vmMemoryAddedMemory = "Added Memory" + vmMemoryCurrentPressure = "Current Pressure" + vmMemoryGuestAvailableMemory = "Guest Available Memory" + vmMemoryGuestVisiblePhysicalMemory = "Guest Visible Physical Memory" + vmMemoryMaximumPressure = "Maximum Pressure" + vmMemoryMemoryAddOperations = "Memory Add Operations" + vmMemoryMemoryRemoveOperations = "Memory Remove Operations" + vmMemoryMinimumPressure = "Minimum Pressure" + vmMemoryPhysicalMemory = "Physical Memory" + vmMemoryRemovedMemory = "Removed Memory" +) + +func (c *Collector) buildDynamicMemoryVM() error { + var err error + + c.perfDataCollectorDynamicMemoryVM, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Dynamic Memory VM", perfdata.AllInstances, []string{ + vmMemoryAddedMemory, + vmMemoryCurrentPressure, + vmMemoryGuestVisiblePhysicalMemory, + vmMemoryMaximumPressure, + vmMemoryMemoryAddOperations, + vmMemoryMemoryRemoveOperations, + vmMemoryMinimumPressure, + vmMemoryPhysicalMemory, + vmMemoryRemovedMemory, + vmMemoryGuestAvailableMemory, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Dynamic Memory VM collector: %w", err) + } + + c.vmMemoryAddedMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_added_total"), + "This counter represents the cummulative amount of memory added to the VM.", + []string{"vm"}, + nil, + ) + c.vmMemoryCurrentPressure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_pressure_current_ratio"), + "This counter represents the current pressure in the VM.", + []string{"vm"}, + nil, + ) + c.vmMemoryGuestAvailableMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_guest_available_bytes"), + "This counter represents the current amount of available memory in the VM (reported by the VM).", + []string{"vm"}, + nil, + ) + c.vmMemoryGuestVisiblePhysicalMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_guest_visible_physical_memory_bytes"), + "This counter represents the amount of memory visible in the VM.'", + []string{"vm"}, + nil, + ) + c.vmMemoryMaximumPressure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_pressure_maximum_ratio"), + "This counter represents the maximum pressure band in the VM.", + []string{"vm"}, + nil, + ) + c.vmMemoryMemoryAddOperations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_add_operations_total"), + "This counter represents the total number of add operations for the VM.", + []string{"vm"}, + nil, + ) + c.vmMemoryMemoryRemoveOperations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_remove_operations_total"), + "This counter represents the total number of remove operations for the VM.", + []string{"vm"}, + nil, + ) + c.vmMemoryMinimumPressure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_pressure_minimum_ratio"), + "This counter represents the minimum pressure band in the VM.", + []string{"vm"}, + nil, + ) + c.vmMemoryPhysicalMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_physical_bytes"), + "This counter represents the current amount of memory in the VM.", + []string{"vm"}, + nil, + ) + c.vmMemoryRemovedMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_removed_bytes_total"), + "This counter represents the cummulative amount of memory removed from the VM.", + []string{"vm"}, + nil, + ) + + return nil +} + +func (c *Collector) collectDynamicMemoryVM(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorDynamicMemoryVM.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Dynamic Memory VM metrics: %w", err) + } + + for vmName, vmData := range data { + ch <- prometheus.MustNewConstMetric( + c.vmMemoryAddedMemory, + prometheus.CounterValue, + utils.MBToBytes(vmData[vmMemoryAddedMemory].FirstValue), + vmName, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmMemoryCurrentPressure, + prometheus.GaugeValue, + utils.PercentageToRatio(vmData[vmMemoryCurrentPressure].FirstValue), + vmName, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmMemoryGuestAvailableMemory, + prometheus.GaugeValue, + utils.MBToBytes(vmData[vmMemoryGuestAvailableMemory].FirstValue), + vmName, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmMemoryGuestVisiblePhysicalMemory, + prometheus.GaugeValue, + utils.MBToBytes(vmData[vmMemoryGuestVisiblePhysicalMemory].FirstValue), + vmName, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmMemoryMaximumPressure, + prometheus.GaugeValue, + utils.PercentageToRatio(vmData[vmMemoryMaximumPressure].FirstValue), + vmName, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmMemoryMemoryAddOperations, + prometheus.CounterValue, + vmData[vmMemoryMemoryAddOperations].FirstValue, + vmName, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmMemoryMemoryRemoveOperations, + prometheus.CounterValue, + vmData[vmMemoryMemoryRemoveOperations].FirstValue, + vmName, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmMemoryMinimumPressure, + prometheus.GaugeValue, + utils.PercentageToRatio(vmData[vmMemoryMinimumPressure].FirstValue), + vmName, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmMemoryPhysicalMemory, + prometheus.GaugeValue, + utils.MBToBytes(vmData[vmMemoryPhysicalMemory].FirstValue), + vmName, + ) + + ch <- prometheus.MustNewConstMetric( + c.vmMemoryRemovedMemory, + prometheus.CounterValue, + utils.MBToBytes(vmData[vmMemoryRemovedMemory].FirstValue), + vmName, + ) + } + + return nil +} diff --git a/internal/collector/hyperv/hyperv_virtual_machine.go b/internal/collector/hyperv/hyperv_virtual_machine.go deleted file mode 100644 index 8e295b483..000000000 --- a/internal/collector/hyperv/hyperv_virtual_machine.go +++ /dev/null @@ -1,142 +0,0 @@ -package hyperv - -import ( - "errors" - "fmt" - "strings" - - "github.com/prometheus-community/windows_exporter/internal/perfdata" - "github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes" - "github.com/prometheus-community/windows_exporter/internal/types" - "github.com/prometheus/client_golang/prometheus" -) - -const ( - // Hyper-V Virtual Machine Health Summary - healthCritical = "Health Critical" - healthOk = "Health Ok" - - // Hyper-V VM Vid Partition - physicalPagesAllocated = "Physical Pages Allocated" - preferredNUMANodeIndex = "Preferred NUMA Node Index" - remotePhysicalPages = "Remote Physical Pages" -) - -func (c *Collector) buildVirtualMachine() error { - var err error - - c.perfDataCollectorVirtualMachineHealthSummary, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Virtual Machine Health Summary", perfdata.AllInstances, []string{ - healthCritical, - healthOk, - }) - - if err != nil { - return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err) - } - - c.healthCritical = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "health_critical"), - "This counter represents the number of virtual machines with critical health", - nil, - nil, - ) - c.healthOk = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "health_ok"), - "This counter represents the number of virtual machines with ok health", - nil, - nil, - ) - - c.perfDataCollectorVMVidPartition, err = perfdata.NewCollector(perfdata.V2, "Hyper-V VM Vid Partition", perfdata.AllInstances, []string{ - physicalPagesAllocated, - preferredNUMANodeIndex, - remotePhysicalPages, - }) - - if err != nil { - return fmt.Errorf("failed to create Hyper-V VM Vid Partition collector: %w", err) - } - - c.physicalPagesAllocated = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vid_physical_pages_allocated"), - "The number of physical pages allocated", - []string{"vm"}, - nil, - ) - c.preferredNUMANodeIndex = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vid_preferred_numa_node_index"), - "The preferred NUMA node index associated with this partition", - []string{"vm"}, - nil, - ) - c.remotePhysicalPages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vid_remote_physical_pages"), - "The number of physical pages not allocated from the preferred NUMA node", - []string{"vm"}, - nil, - ) - - return nil -} - -func (c *Collector) collectVirtualMachine(ch chan<- prometheus.Metric) error { - data, err := c.perfDataCollectorVirtualMachineHealthSummary.Collect() - if err != nil { - return fmt.Errorf("failed to collect Hyper-V Virtual Machine Health Summary metrics: %w", err) - } else if len(data) == 0 { - return errors.New("perflib query for Hyper-V Virtual Machine Health Summary returned empty result set") - } - - healthData, ok := data[perftypes.EmptyInstance] - if !ok { - return errors.New("no data returned for Hyper-V Virtual Machine Health Summary") - } - - ch <- prometheus.MustNewConstMetric( - c.healthCritical, - prometheus.GaugeValue, - healthData[healthCritical].FirstValue, - ) - - ch <- prometheus.MustNewConstMetric( - c.healthOk, - prometheus.GaugeValue, - healthData[healthOk].FirstValue, - ) - - data, err = c.perfDataCollectorVMVidPartition.Collect() - if err != nil { - return fmt.Errorf("failed to collect Hyper-V Virtual Machine Health Summary metrics: %w", err) - } else if len(data) == 0 { - return errors.New("perflib query for Hyper-V Virtual Machine Health Summary returned empty result set") - } - - for name, page := range data { - if strings.Contains(name, "*") { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.physicalPagesAllocated, - prometheus.GaugeValue, - page[physicalPagesAllocated].FirstValue, - name, - ) - - ch <- prometheus.MustNewConstMetric( - c.preferredNUMANodeIndex, - prometheus.GaugeValue, - page[preferredNUMANodeIndex].FirstValue, - name, - ) - - ch <- prometheus.MustNewConstMetric( - c.remotePhysicalPages, - prometheus.GaugeValue, - page[remotePhysicalPages].FirstValue, - name, - ) - } - - return nil -} diff --git a/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go new file mode 100644 index 000000000..2419b3161 --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go @@ -0,0 +1,80 @@ +package hyperv + +import ( + "errors" + "fmt" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorVirtualMachineHealthSummary Hyper-V Virtual Machine Health Summary metrics +type collectorVirtualMachineHealthSummary struct { + perfDataCollectorVirtualMachineHealthSummary perfdata.Collector + healthCritical *prometheus.Desc // \Hyper-V Virtual Machine Health Summary\Health Critical + healthOk *prometheus.Desc // \Hyper-V Virtual Machine Health Summary\Health Ok +} + +const ( + // Hyper-V Virtual Machine Health Summary + healthCritical = "Health Critical" + healthOk = "Health Ok" +) + +func (c *Collector) buildVirtualMachineHealthSummary() error { + var err error + + c.perfDataCollectorVirtualMachineHealthSummary, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Virtual Machine Health Summary", perfdata.AllInstances, []string{ + healthCritical, + healthOk, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err) + } + + c.healthCritical = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "health_critical"), + "This counter represents the number of virtual machines with critical health", + nil, + nil, + ) + c.healthOk = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "health_ok"), + "This counter represents the number of virtual machines with ok health", + nil, + nil, + ) + + return nil +} + +func (c *Collector) collectVirtualMachineHealthSummary(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorVirtualMachineHealthSummary.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Virtual Machine Health Summary metrics: %w", err) + } else if len(data) == 0 { + return errors.New("perflib query for Hyper-V Virtual Machine Health Summary returned empty result set") + } + + healthData, ok := data[perftypes.EmptyInstance] + if !ok { + return errors.New("no data returned for Hyper-V Virtual Machine Health Summary") + } + + ch <- prometheus.MustNewConstMetric( + c.healthCritical, + prometheus.GaugeValue, + healthData[healthCritical].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.healthOk, + prometheus.GaugeValue, + healthData[healthOk].FirstValue, + ) + + return nil +} diff --git a/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go new file mode 100644 index 000000000..4c8e00ef1 --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go @@ -0,0 +1,90 @@ +package hyperv + +import ( + "fmt" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorVirtualMachineVidPartition Hyper-V VM Vid Partition metrics +type collectorVirtualMachineVidPartition struct { + perfDataCollectorVMVidPartition perfdata.Collector + physicalPagesAllocated *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Physical Pages Allocated + preferredNUMANodeIndex *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Preferred NUMA Node Index + remotePhysicalPages *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Remote Physical Pages +} + +const ( + physicalPagesAllocated = "Physical Pages Allocated" + preferredNUMANodeIndex = "Preferred NUMA Node Index" + remotePhysicalPages = "Remote Physical Pages" +) + +func (c *Collector) buildVirtualMachineVidPartition() error { + var err error + + c.perfDataCollectorVMVidPartition, err = perfdata.NewCollector(perfdata.V2, "Hyper-V VM Vid Partition", perfdata.AllInstances, []string{ + physicalPagesAllocated, + preferredNUMANodeIndex, + remotePhysicalPages, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V VM Vid Partition collector: %w", err) + } + + c.physicalPagesAllocated = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vid_physical_pages_allocated"), + "The number of physical pages allocated", + []string{"vm"}, + nil, + ) + c.preferredNUMANodeIndex = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vid_preferred_numa_node_index"), + "The preferred NUMA node index associated with this partition", + []string{"vm"}, + nil, + ) + c.remotePhysicalPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vid_remote_physical_pages"), + "The number of physical pages not allocated from the preferred NUMA node", + []string{"vm"}, + nil, + ) + + return nil +} + +func (c *Collector) collectVirtualMachineVidPartition(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorVMVidPartition.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V VM Vid Partition metrics: %w", err) + } + + for name, page := range data { + ch <- prometheus.MustNewConstMetric( + c.physicalPagesAllocated, + prometheus.GaugeValue, + page[physicalPagesAllocated].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.preferredNUMANodeIndex, + prometheus.GaugeValue, + page[preferredNUMANodeIndex].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.remotePhysicalPages, + prometheus.GaugeValue, + page[remotePhysicalPages].FirstValue, + name, + ) + } + + return nil +} diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 5daf902ef..e58758276 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -18,6 +18,14 @@ func ToPTR[t any](v t) *t { return &v } +func MBToBytes(mb float64) float64 { + return mb * 1024 * 1024 +} + +func PercentageToRatio(percentage float64) float64 { + return percentage / 100 +} + // Must panics if the error is not nil. // //nolint:ireturn From 2c3c83a6d1c81c3a16a52e0caadd153b866b60c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Thu, 31 Oct 2024 18:40:04 +0100 Subject: [PATCH 03/12] hyperv: Added DataStore, Virtual SMB and Dynamic Memory Balancer metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- docs/collector.hyperv.md | 22 +- internal/collector/hyperv/hyperv.go | 66 ++---- .../hyperv/hyperv_virtual_storage_device.go | 218 ++++++++++++++++++ 3 files changed, 248 insertions(+), 58 deletions(-) create mode 100644 internal/collector/hyperv/hyperv_virtual_storage_device.go diff --git a/docs/collector.hyperv.md b/docs/collector.hyperv.md index d40a405af..2c4d7a54d 100644 --- a/docs/collector.hyperv.md +++ b/docs/collector.hyperv.md @@ -86,12 +86,6 @@ None | `windows_hyperv_ethernet_frames_dropped` | _Not yet documented_ | counter | `adapter` | | `windows_hyperv_ethernet_frames_received` | _Not yet documented_ | counter | `adapter` | | `windows_hyperv_ethernet_frames_sent` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_vm_device_error_count` | _Not yet documented_ | counter | `vm_device` | -| `windows_hyperv_vm_device_queue_length` | _Not yet documented_ | counter | `vm_device` | -| `windows_hyperv_vm_device_bytes_read` | _Not yet documented_ | counter | `vm_device` | -| `windows_hyperv_vm_device_operations_read` | _Not yet documented_ | counter | `vm_device` | -| `windows_hyperv_vm_device_bytes_written` | _Not yet documented_ | counter | `vm_device` | -| `windows_hyperv_vm_device_operations_written` | _Not yet documented_ | counter | `vm_device` | | `windows_hyperv_vm_interface_bytes_received` | _Not yet documented_ | counter | `vm_interface` | | `windows_hyperv_vm_interface_bytes_sent` | _Not yet documented_ | counter | `vm_interface` | | `windows_hyperv_vm_interface_packets_incoming_dropped` | _Not yet documented_ | counter | `vm_interface` | @@ -103,6 +97,22 @@ None +### Hyper-V Virtual Storage Device + +| Name | Description | Type | Labels | +|------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|---------|----------| +| `windows_hyperv_virtual_storage_device_error_count_total` | This counter represents the total number of errors that have occurred on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_queue_length` | This counter represents the average queue length on this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_bytes_read` | This counter represents the total number of bytes that have been read on this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_operations_read_total` | This counter represents the total number of read operations that have occured on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_bytes_written` | This counter represents the total number of bytes that have been written on this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_operations_written_total` | This counter represents the total number of write operations that have occured on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_latency_seconds` | This counter represents the average IO transfer latency for this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_throughput` | This counter represents the average number of 8KB IO transfers completed by this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_normalized_throughput` | This counter represents the average number of IO transfers completed by this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_lower_queue_length` | This counter represents the average queue length on the underlying storage subsystem for this device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_lower_latency_seconds` | This counter represents the average IO transfer latency on the underlying storage subsystem for this virtual device. | gauge | `device` | + ### Hyper-V Dynamic Memory Balancer Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012 diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index 824c07479..0b3e68f12 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -28,6 +28,7 @@ type Collector struct { collectorDynamicMemoryVM collectorVirtualMachineHealthSummary collectorVirtualMachineVidPartition + collectorVirtualStorageDevice // Hyper-V Hypervisor Root Partition metrics addressSpaces *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Address Spaces @@ -115,17 +116,6 @@ type Collector struct { vmStoragePacketsReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Received/sec vmStoragePacketsSent *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Sent/sec - // Hyper-V Virtual Storage Device metrics - vmStorageErrorCount *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Error Count - vmStorageQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Queue Length - vmStorageReadBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Bytes/sec - vmStorageReadOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Operations/Sec - vmStorageWriteBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Bytes/sec - vmStorageWriteOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Operations/Sec - // TODO: \Hyper-V Virtual Storage Device(*)\Latency - // TODO: \Hyper-V Virtual Storage Device(*)\Throughput - // TODO: \Hyper-V Virtual Storage Device(*)\Normalized Throughput - // Hyper-V DataStore metrics // TODO: \Hyper-V DataStore(*)\Fragmentation ratio // TODO: \Hyper-V DataStore(*)\Sector size @@ -229,6 +219,9 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) { } func (c *Collector) Close(_ *slog.Logger) error { + c.perfDataCollectorDynamicMemoryBalancer.Close() + c.perfDataCollectorDynamicMemoryVM.Close() + c.perfDataCollectorVirtualStorageDevice.Close() c.perfDataCollectorVirtualMachineHealthSummary.Close() c.perfDataCollectorVMVidPartition.Close() @@ -244,11 +237,15 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { return err } - if err := c.buildDynamicMemoryVM(); err != nil { + if err := c.buildVirtualStorageDevice(); err != nil { return err } - if err := c.buildDynamicMemoryBalancer(); err != nil { + if err := c.buildVirtualMachineHealthSummary(); err != nil { + return err + } + + if err := c.buildVirtualMachineVidPartition(); err != nil { return err } @@ -650,45 +647,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { // - c.vmStorageErrorCount = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_device_error_count"), - "This counter represents the total number of errors that have occurred on this virtual device", - []string{"vm_device"}, - nil, - ) - c.vmStorageQueueLength = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_device_queue_length"), - "This counter represents the current queue length on this virtual device", - []string{"vm_device"}, - nil, - ) - c.vmStorageReadBytes = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_device_bytes_read"), - "This counter represents the total number of bytes that have been read per second on this virtual device", - []string{"vm_device"}, - nil, - ) - c.vmStorageReadOperations = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_device_operations_read"), - "This counter represents the number of read operations that have occurred per second on this virtual device", - []string{"vm_device"}, - nil, - ) - c.vmStorageWriteBytes = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_device_bytes_written"), - "This counter represents the total number of bytes that have been written per second on this virtual device", - []string{"vm_device"}, - nil, - ) - c.vmStorageWriteOperations = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_device_operations_written"), - "This counter represents the number of write operations that have occurred per second on this virtual device", - []string{"vm_device"}, - nil, - ) - - // - c.vmStorageBytesReceived = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vm_interface_bytes_received"), "This counter represents the total number of bytes received per second by the network adapter", @@ -750,6 +708,10 @@ func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- pr errs = append(errs, fmt.Errorf("failed collecting Hyper-V VM Vid Partition metrics: %w", err)) } + if err := c.collectVirtualStorageDevice(ch); err != nil { + errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Storage Device metrics: %w", err)) + } + return errors.Join(errs...) } diff --git a/internal/collector/hyperv/hyperv_virtual_storage_device.go b/internal/collector/hyperv/hyperv_virtual_storage_device.go new file mode 100644 index 000000000..66fb2834f --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_storage_device.go @@ -0,0 +1,218 @@ +package hyperv + +import ( + "fmt" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +// Hyper-V Virtual Storage Device metrics +type collectorVirtualStorageDevice struct { + perfDataCollectorVirtualStorageDevice perfdata.Collector + + virtualStorageDeviceErrorCount *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Error Count + virtualStorageDeviceQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Queue Length + virtualStorageDeviceReadBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Bytes/sec + virtualStorageDeviceReadOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Operations/Sec + virtualStorageDeviceWriteBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Bytes/sec + virtualStorageDeviceWriteOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Operations/Sec + virtualStorageDeviceLatency *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Latency + virtualStorageDeviceThroughput *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Throughput + virtualStorageDeviceNormalizedThroughput *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Normalized Throughput + virtualStorageDeviceLowerQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Lower Queue Length + virtualStorageDeviceLowerLatency *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Lower Latency +} + +const ( + virtualStorageDeviceErrorCount = "Error Count" + virtualStorageDeviceQueueLength = "Queue Length" + virtualStorageDeviceReadBytes = "Read Bytes/sec" + virtualStorageDeviceReadOperations = "Read Count" + virtualStorageDeviceWriteBytes = "Write Bytes/sec" + virtualStorageDeviceWriteOperations = "Write Count" + virtualStorageDeviceLatency = "Latency" + virtualStorageDeviceThroughput = "Throughput" + virtualStorageDeviceNormalizedThroughput = "Normalized Throughput" + virtualStorageDeviceLowerQueueLength = "Lower Queue Length" + virtualStorageDeviceLowerLatency = "Lower Latency" +) + +func (c *Collector) buildVirtualStorageDevice() error { + var err error + + c.perfDataCollectorVirtualStorageDevice, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Virtual Storage Device", perfdata.AllInstances, []string{ + virtualStorageDeviceErrorCount, + virtualStorageDeviceQueueLength, + virtualStorageDeviceReadBytes, + virtualStorageDeviceReadOperations, + virtualStorageDeviceWriteBytes, + virtualStorageDeviceWriteOperations, + virtualStorageDeviceLatency, + virtualStorageDeviceThroughput, + virtualStorageDeviceNormalizedThroughput, + virtualStorageDeviceLowerQueueLength, + virtualStorageDeviceLowerLatency, + }) + if err != nil { + return fmt.Errorf("failed to create Hyper-V Virtual Storage Device collector: %w", err) + } + + c.virtualStorageDeviceErrorCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_error_count_total"), + "This counter represents the total number of errors that have occurred on this virtual device.", + []string{"device"}, + nil, + ) + c.virtualStorageDeviceQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_queue_length"), + "This counter represents the average queue length on this virtual device.", + []string{"device"}, + nil, + ) + c.virtualStorageDeviceReadBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_bytes_read"), + "This counter represents the total number of bytes that have been read on this virtual device.", + []string{"device"}, + nil, + ) + c.virtualStorageDeviceReadOperations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_operations_read_total"), + "This counter represents the total number of read operations that have occured on this virtual device.", + []string{"device"}, + nil, + ) + c.virtualStorageDeviceWriteBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_bytes_written"), + "This counter represents the total number of bytes that have been written on this virtual device.", + []string{"device"}, + nil, + ) + c.virtualStorageDeviceWriteOperations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_operations_written_total"), + "This counter represents the total number of write operations that have occured on this virtual device.", + []string{"device"}, + nil, + ) + c.virtualStorageDeviceLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_latency_seconds"), + "This counter represents the average IO transfer latency for this virtual device.", + []string{"device"}, + nil, + ) + c.virtualStorageDeviceThroughput = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_throughput"), + "This counter represents the average number of 8KB IO transfers completed by this virtual device.", + []string{"device"}, + nil, + ) + c.virtualStorageDeviceNormalizedThroughput = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_normalized_throughput"), + "This counter represents the average number of IO transfers completed by this virtual device.", + []string{"device"}, + nil, + ) + c.virtualStorageDeviceLowerQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_lower_queue_length"), + "This counter represents the average queue length on the underlying storage subsystem for this device.", + []string{"device"}, + nil, + ) + c.virtualStorageDeviceLowerLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_lower_latency_seconds"), + "This counter represents the average IO transfer latency on the underlying storage subsystem for this virtual device.", + []string{"device"}, + nil, + ) + + return nil +} + +func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorVirtualStorageDevice.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Virtual Storage Device metrics: %w", err) + } + + for name, device := range data { + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceErrorCount, + prometheus.CounterValue, + device[virtualStorageDeviceErrorCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceQueueLength, + prometheus.GaugeValue, + device[virtualStorageDeviceQueueLength].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceReadBytes, + prometheus.CounterValue, + device[virtualStorageDeviceReadBytes].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceReadOperations, + prometheus.CounterValue, + device[virtualStorageDeviceReadOperations].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceWriteBytes, + prometheus.CounterValue, + device[virtualStorageDeviceWriteBytes].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceWriteOperations, + prometheus.CounterValue, + device[virtualStorageDeviceWriteOperations].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceLatency, + prometheus.GaugeValue, + device[virtualStorageDeviceLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceThroughput, + prometheus.GaugeValue, + device[virtualStorageDeviceThroughput].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceNormalizedThroughput, + prometheus.GaugeValue, + device[virtualStorageDeviceNormalizedThroughput].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceLowerQueueLength, + prometheus.GaugeValue, + device[virtualStorageDeviceLowerQueueLength].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceLowerLatency, + prometheus.GaugeValue, + device[virtualStorageDeviceLowerLatency].FirstValue, + name, + ) + } + + return nil +} From 292cfc59e902db3e4470856770044a776898ff06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Thu, 31 Oct 2024 20:28:26 +0100 Subject: [PATCH 04/12] hyperv: Added DataStore, Virtual SMB and Dynamic Memory Balancer metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- docs/collector.hyperv.md | 59 ++- internal/collector/hyperv/hyperv.go | 345 +--------------- .../collector/hyperv/hyperv_hypervisor.go | 1 - internal/collector/hyperv/hyperv_network.go | 1 - internal/collector/hyperv/hyperv_storage.go | 1 - .../collector/hyperv/hyperv_virtual_switch.go | 368 ++++++++++++++++++ 6 files changed, 406 insertions(+), 369 deletions(-) delete mode 100644 internal/collector/hyperv/hyperv_hypervisor.go delete mode 100644 internal/collector/hyperv/hyperv_network.go delete mode 100644 internal/collector/hyperv/hyperv_storage.go create mode 100644 internal/collector/hyperv/hyperv_virtual_switch.go diff --git a/docs/collector.hyperv.md b/docs/collector.hyperv.md index 2c4d7a54d..9bc8a21a3 100644 --- a/docs/collector.hyperv.md +++ b/docs/collector.hyperv.md @@ -18,11 +18,6 @@ None | Name | Description | Type | Labels | |---------------------------------------------------------------------|----------------------|---------|----------------| -| `windows_hyperv_health_critical` | _Not yet documented_ | counter | None | -| `windows_hyperv_health_ok` | _Not yet documented_ | counter | None | -| `windows_hyperv_vid_physical_pages_allocated` | _Not yet documented_ | counter | `vm` | -| `windows_hyperv_vid_preferred_numa_node_index` | _Not yet documented_ | counter | `vm` | -| `windows_hyperv_vid_remote_physical_pages` | _Not yet documented_ | counter | `vm` | | `windows_hyperv_root_partition_address_spaces` | _Not yet documented_ | counter | None | | `windows_hyperv_root_partition_attached_devices` | _Not yet documented_ | counter | None | | `windows_hyperv_root_partition_deposited_pages` | _Not yet documented_ | counter | None | @@ -59,27 +54,6 @@ None | `windows_hyperv_vm_cpu_remote_run_time` | _Not yet documented_ | counter | `vm`, `core` | | `windows_hyperv_vm_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `vm`, `core` | | `windows_hyperv_vm_cpu_total_run_time` | _Not yet documented_ | counter | `vm`, `core` | -| `windows_hyperv_vswitch_broadcast_packets_received_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_broadcast_packets_sent_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_bytes_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_bytes_received_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_bytes_sent_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_directed_packets_received_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_directed_packets_send_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_dropped_packets_incoming_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_dropped_packets_outcoming_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_extensions_dropped_packets_incoming_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_extensions_dropped_packets_outcoming_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_learned_mac_addresses_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_multicast_packets_received_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_multicast_packets_sent_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_number_of_send_channel_moves_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_number_of_vmq_moves_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_packets_flooded_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_packets_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_packets_received_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_packets_sent_total` | _Not yet documented_ | counter | `vswitch` | -| `windows_hyperv_vswitch_purged_mac_addresses_total` | _Not yet documented_ | counter | `vswitch` | | `windows_hyperv_ethernet_bytes_dropped` | _Not yet documented_ | counter | `adapter` | | `windows_hyperv_ethernet_bytes_received` | _Not yet documented_ | counter | `adapter` | | `windows_hyperv_ethernet_bytes_sent` | _Not yet documented_ | counter | `adapter` | @@ -93,9 +67,31 @@ None | `windows_hyperv_vm_interface_packets_received` | _Not yet documented_ | counter | `vm_interface` | | `windows_hyperv_vm_interface_packets_sent` | _Not yet documented_ | counter | `vm_interface` | - - - +### Hyper-V Virtual Switch + +| Name | Description | Type | Labels | +|---------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|---------|-----------| +| `windows_hyperv_vswitch_broadcast_packets_received_total` | This represents the total number of broadcast packets received per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_broadcast_packets_sent_total` | This represents the total number of broadcast packets sent per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_bytes_total` | This represents the total number of bytes per second traversing the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_bytes_received_total` | This represents the total number of bytes received per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_bytes_sent_total` | This represents the total number of bytes sent per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_directed_packets_received_total` | This represents the total number of directed packets received per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_directed_packets_send_total` | This represents the total number of directed packets sent per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_dropped_packets_incoming_total` | This represents the total number of packet dropped per second by the virtual switch in the incoming direction | counter | `vswitch` | +| `windows_hyperv_vswitch_dropped_packets_outcoming_total` | This represents the total number of packet dropped per second by the virtual switch in the outgoing direction | counter | `vswitch` | +| `windows_hyperv_vswitch_extensions_dropped_packets_incoming_total` | This represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction | counter | `vswitch` | +| `windows_hyperv_vswitch_extensions_dropped_packets_outcoming_total` | This represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction | counter | `vswitch` | +| `windows_hyperv_vswitch_learned_mac_addresses_total` | This counter represents the total number of learned MAC addresses of the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_multicast_packets_received_total` | This represents the total number of multicast packets received per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_multicast_packets_sent_total` | This represents the total number of multicast packets sent per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_number_of_send_channel_moves_total` | This represents the total number of send channel moves per second on this virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_number_of_vmq_moves_total` | This represents the total number of VMQ moves per second on this virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_flooded_total` | This counter represents the total number of packets flooded by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_total` | This represents the total number of packets per second traversing the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_received_total` | This represents the total number of packets received per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_sent_total` | This represents the total number of packets send per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_purged_mac_addresses_total` | This counter represents the total number of purged MAC addresses of the virtual switch | counter | `vswitch` | ### Hyper-V Virtual Storage Device @@ -103,9 +99,9 @@ None |------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|---------|----------| | `windows_hyperv_virtual_storage_device_error_count_total` | This counter represents the total number of errors that have occurred on this virtual device. | counter | `device` | | `windows_hyperv_virtual_storage_device_queue_length` | This counter represents the average queue length on this virtual device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_bytes_read` | This counter represents the total number of bytes that have been read on this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_bytes_read` | This counter represents the total number of bytes that have been read on this virtual device. | counter | `device` | | `windows_hyperv_virtual_storage_device_operations_read_total` | This counter represents the total number of read operations that have occured on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_bytes_written` | This counter represents the total number of bytes that have been written on this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_bytes_written` | This counter represents the total number of bytes that have been written on this virtual device. | counter | `device` | | `windows_hyperv_virtual_storage_device_operations_written_total` | This counter represents the total number of write operations that have occured on this virtual device. | counter | `device` | | `windows_hyperv_virtual_storage_device_latency_seconds` | This counter represents the average IO transfer latency for this virtual device. | gauge | `device` | | `windows_hyperv_virtual_storage_device_throughput` | This counter represents the average number of 8KB IO transfers completed by this virtual device. | gauge | `device` | @@ -127,7 +123,6 @@ Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavi ### Hyper-V Dynamic Memory VM - | Name | Description | Type | Labels | |------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|---------|--------| | `windows_hyperv_dynamic_memory_vm_added_bytes_total` | This counter represents the cummulative amount of memory added to the VM. | counter | `vm` | diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index 0b3e68f12..bc3a63c12 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -29,6 +29,7 @@ type Collector struct { collectorVirtualMachineHealthSummary collectorVirtualMachineVidPartition collectorVirtualStorageDevice + collectorVirtualSwitch // Hyper-V Hypervisor Root Partition metrics addressSpaces *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Address Spaces @@ -77,29 +78,6 @@ type Collector struct { vmTotalRunTime *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Total Run Time vmCPUWaitTimePerDispatch *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per Dispatch - // Hyper-V Virtual Switch metrics - broadcastPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Broadcast Packets Received/sec - broadcastPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Broadcast Packets Sent/sec - bytes *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes/sec - bytesReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes Received/sec - bytesSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes Sent/sec - directedPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Directed Packets Received/sec - directedPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Directed Packets Sent/sec - droppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Switch(*)\Dropped Packets Incoming/sec - droppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Switch(*)\Dropped Packets Outgoing/sec - extensionsDroppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Switch(*)\Extensions Dropped Packets Incoming/sec - extensionsDroppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Switch(*)\Extensions Dropped Packets Outgoing/sec - learnedMacAddresses *prometheus.Desc // \Hyper-V Virtual Switch(*)\Learned Mac Addresses - multicastPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Multicast Packets Received/sec - multicastPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Multicast Packets Sent/sec - numberOfSendChannelMoves *prometheus.Desc // \Hyper-V Virtual Switch(*)\Number of Send Channel Moves/sec - numberOfVMQMoves *prometheus.Desc // \Hyper-V Virtual Switch(*)\Number of VMQ Moves/sec - packetsFlooded *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Flooded - packets *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets/sec - packetsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Received/sec - packetsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Sent/sec - purgedMacAddresses *prometheus.Desc // \Hyper-V Virtual Switch(*)\Purged Mac Addresses - // Hyper-V Legacy Network Adapter metrics adapterBytesDropped *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Dropped adapterBytesReceived *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Received/sec @@ -221,8 +199,9 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) { func (c *Collector) Close(_ *slog.Logger) error { c.perfDataCollectorDynamicMemoryBalancer.Close() c.perfDataCollectorDynamicMemoryVM.Close() - c.perfDataCollectorVirtualStorageDevice.Close() c.perfDataCollectorVirtualMachineHealthSummary.Close() + c.perfDataCollectorVirtualStorageDevice.Close() + c.perfDataCollectorVirtualSwitch.Close() c.perfDataCollectorVMVidPartition.Close() return nil @@ -249,6 +228,10 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { return err } + if err := c.buildVirtualSwitch(); err != nil { + return err + } + c.addressSpaces = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "root_partition_address_spaces"), "The number of address spaces in the virtual TLB of the partition", @@ -478,134 +461,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { nil, ) - // - c.broadcastPacketsReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_broadcast_packets_received_total"), - "This represents the total number of broadcast packets received per second by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.broadcastPacketsSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_broadcast_packets_sent_total"), - "This represents the total number of broadcast packets sent per second by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.bytes = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_total"), - "This represents the total number of bytes per second traversing the virtual switch", - []string{"vswitch"}, - nil, - ) - c.bytesReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_received_total"), - "This represents the total number of bytes received per second by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.bytesSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_sent_total"), - "This represents the total number of bytes sent per second by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.directedPacketsReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_directed_packets_received_total"), - "This represents the total number of directed packets received per second by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.directedPacketsSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_directed_packets_send_total"), - "This represents the total number of directed packets sent per second by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.droppedPacketsIncoming = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_dropped_packets_incoming_total"), - "This represents the total number of packet dropped per second by the virtual switch in the incoming direction", - []string{"vswitch"}, - nil, - ) - c.droppedPacketsOutgoing = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_dropped_packets_outcoming_total"), - "This represents the total number of packet dropped per second by the virtual switch in the outgoing direction", - []string{"vswitch"}, - nil, - ) - c.extensionsDroppedPacketsIncoming = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_extensions_dropped_packets_incoming_total"), - "This represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction", - []string{"vswitch"}, - nil, - ) - c.extensionsDroppedPacketsOutgoing = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_extensions_dropped_packets_outcoming_total"), - "This represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction", - []string{"vswitch"}, - nil, - ) - c.learnedMacAddresses = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_learned_mac_addresses_total"), - "This counter represents the total number of learned MAC addresses of the virtual switch", - []string{"vswitch"}, - nil, - ) - c.multicastPacketsReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_multicast_packets_received_total"), - "This represents the total number of multicast packets received per second by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.multicastPacketsSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_multicast_packets_sent_total"), - "This represents the total number of multicast packets sent per second by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.numberOfSendChannelMoves = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_number_of_send_channel_moves_total"), - "This represents the total number of send channel moves per second on this virtual switch", - []string{"vswitch"}, - nil, - ) - c.numberOfVMQMoves = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_number_of_vmq_moves_total"), - "This represents the total number of VMQ moves per second on this virtual switch", - []string{"vswitch"}, - nil, - ) - c.packetsFlooded = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_flooded_total"), - "This counter represents the total number of packets flooded by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.packets = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_total"), - "This represents the total number of packets per second traversing the virtual switch", - []string{"vswitch"}, - nil, - ) - c.packetsReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_received_total"), - "This represents the total number of packets received per second by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.packetsSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_sent_total"), - "This represents the total number of packets send per second by the virtual switch", - []string{"vswitch"}, - nil, - ) - c.purgedMacAddresses = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vswitch_purged_mac_addresses_total"), - "This counter represents the total number of purged MAC addresses of the virtual switch", - []string{"vswitch"}, - nil, - ) - // c.adapterBytesDropped = prometheus.NewDesc( @@ -712,6 +567,10 @@ func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- pr errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Storage Device metrics: %w", err)) } + if err := c.collectVirtualSwitch(ch); err != nil { + errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Storage Device metrics: %w", err)) + } + return errors.Join(errs...) } @@ -1102,188 +961,6 @@ func (c *Collector) collectVmCpuUsage(logger *slog.Logger, ch chan<- prometheus. return nil } -// Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch ... -type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct { - Name string - BroadcastPacketsReceivedPersec uint64 - BroadcastPacketsSentPersec uint64 - BytesPersec uint64 - BytesReceivedPersec uint64 - BytesSentPersec uint64 - DirectedPacketsReceivedPersec uint64 - DirectedPacketsSentPersec uint64 - DroppedPacketsIncomingPersec uint64 - DroppedPacketsOutgoingPersec uint64 - ExtensionsDroppedPacketsIncomingPersec uint64 - ExtensionsDroppedPacketsOutgoingPersec uint64 - LearnedMacAddresses uint64 - LearnedMacAddressesPersec uint64 - MulticastPacketsReceivedPersec uint64 - MulticastPacketsSentPersec uint64 - NumberofSendChannelMovesPersec uint64 - NumberofVMQMovesPersec uint64 - PacketsFlooded uint64 - PacketsFloodedPersec uint64 - PacketsPersec uint64 - PacketsReceivedPersec uint64 - PacketsSentPersec uint64 - PurgedMacAddresses uint64 - PurgedMacAddressesPersec uint64 -} - -func (c *Collector) collectVmSwitch(ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch - if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch", &dst); err != nil { - return err - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "*") { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.broadcastPacketsReceived, - prometheus.CounterValue, - float64(obj.BroadcastPacketsReceivedPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.broadcastPacketsSent, - prometheus.CounterValue, - float64(obj.BroadcastPacketsSentPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.bytes, - prometheus.CounterValue, - float64(obj.BytesPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.bytesReceived, - prometheus.CounterValue, - float64(obj.BytesReceivedPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.bytesSent, - prometheus.CounterValue, - float64(obj.BytesSentPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.directedPacketsReceived, - prometheus.CounterValue, - float64(obj.DirectedPacketsReceivedPersec), - obj.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.directedPacketsSent, - prometheus.CounterValue, - float64(obj.DirectedPacketsSentPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.droppedPacketsIncoming, - prometheus.CounterValue, - float64(obj.DroppedPacketsIncomingPersec), - obj.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.droppedPacketsOutgoing, - prometheus.CounterValue, - float64(obj.DroppedPacketsOutgoingPersec), - obj.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.extensionsDroppedPacketsIncoming, - prometheus.CounterValue, - float64(obj.ExtensionsDroppedPacketsIncomingPersec), - obj.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.extensionsDroppedPacketsOutgoing, - prometheus.CounterValue, - float64(obj.ExtensionsDroppedPacketsOutgoingPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.learnedMacAddresses, - prometheus.CounterValue, - float64(obj.LearnedMacAddresses), - obj.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.multicastPacketsReceived, - prometheus.CounterValue, - float64(obj.MulticastPacketsReceivedPersec), - obj.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.multicastPacketsSent, - prometheus.CounterValue, - float64(obj.MulticastPacketsSentPersec), - obj.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.numberOfSendChannelMoves, - prometheus.CounterValue, - float64(obj.NumberofSendChannelMovesPersec), - obj.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.numberOfVMQMoves, - prometheus.CounterValue, - float64(obj.NumberofVMQMovesPersec), - obj.Name, - ) - - // ... - ch <- prometheus.MustNewConstMetric( - c.packetsFlooded, - prometheus.CounterValue, - float64(obj.PacketsFlooded), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.packets, - prometheus.CounterValue, - float64(obj.PacketsPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.packetsReceived, - prometheus.CounterValue, - float64(obj.PacketsReceivedPersec), - obj.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.packetsSent, - prometheus.CounterValue, - float64(obj.PacketsSentPersec), - obj.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.purgedMacAddresses, - prometheus.CounterValue, - float64(obj.PurgedMacAddresses), - obj.Name, - ) - } - - return nil -} - // Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter ... type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct { Name string diff --git a/internal/collector/hyperv/hyperv_hypervisor.go b/internal/collector/hyperv/hyperv_hypervisor.go deleted file mode 100644 index 568364523..000000000 --- a/internal/collector/hyperv/hyperv_hypervisor.go +++ /dev/null @@ -1 +0,0 @@ -package hyperv diff --git a/internal/collector/hyperv/hyperv_network.go b/internal/collector/hyperv/hyperv_network.go deleted file mode 100644 index 568364523..000000000 --- a/internal/collector/hyperv/hyperv_network.go +++ /dev/null @@ -1 +0,0 @@ -package hyperv diff --git a/internal/collector/hyperv/hyperv_storage.go b/internal/collector/hyperv/hyperv_storage.go deleted file mode 100644 index 568364523..000000000 --- a/internal/collector/hyperv/hyperv_storage.go +++ /dev/null @@ -1 +0,0 @@ -package hyperv diff --git a/internal/collector/hyperv/hyperv_virtual_switch.go b/internal/collector/hyperv/hyperv_virtual_switch.go new file mode 100644 index 000000000..200077c18 --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_switch.go @@ -0,0 +1,368 @@ +package hyperv + +import ( + "fmt" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorVirtualMachineHealthSummary Hyper-V Virtual Switch Summary metrics +type collectorVirtualSwitch struct { + perfDataCollectorVirtualSwitch perfdata.Collector + virtualSwitchBroadcastPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Broadcast Packets Received/sec + virtualSwitchBroadcastPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Broadcast Packets Sent/sec + virtualSwitchBytes *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes/sec + virtualSwitchBytesReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes Received/sec + virtualSwitchBytesSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes Sent/sec + virtualSwitchDirectedPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Directed Packets Received/sec + virtualSwitchDirectedPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Directed Packets Sent/sec + virtualSwitchDroppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Switch(*)\Dropped Packets Incoming/sec + virtualSwitchDroppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Switch(*)\Dropped Packets Outgoing/sec + virtualSwitchExtensionsDroppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Switch(*)\Extensions Dropped Packets Incoming/sec + virtualSwitchExtensionsDroppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Switch(*)\Extensions Dropped Packets Outgoing/sec + virtualSwitchLearnedMacAddresses *prometheus.Desc // \Hyper-V Virtual Switch(*)\Learned Mac Addresses + virtualSwitchMulticastPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Multicast Packets Received/sec + virtualSwitchMulticastPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Multicast Packets Sent/sec + virtualSwitchNumberOfSendChannelMoves *prometheus.Desc // \Hyper-V Virtual Switch(*)\Number of Send Channel Moves/sec + virtualSwitchNumberOfVMQMoves *prometheus.Desc // \Hyper-V Virtual Switch(*)\Number of VMQ Moves/sec + virtualSwitchPacketsFlooded *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Flooded + virtualSwitchPackets *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets/sec + virtualSwitchPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Received/sec + virtualSwitchPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Sent/sec + virtualSwitchPurgedMacAddresses *prometheus.Desc // \Hyper-V Virtual Switch(*)\Purged Mac Addresses +} + +const ( + virtualSwitchBroadcastPacketsReceived = "Broadcast Packets Received/sec" + virtualSwitchBroadcastPacketsSent = "Broadcast Packets Sent/sec" + virtualSwitchBytes = "Bytes/sec" + virtualSwitchBytesReceived = "Bytes Received/sec" + virtualSwitchBytesSent = "Bytes Sent/sec" + virtualSwitchDirectedPacketsReceived = "Directed Packets Received/sec" + virtualSwitchDirectedPacketsSent = "Directed Packets Sent/sec" + virtualSwitchDroppedPacketsIncoming = "Dropped Packets Incoming/sec" + virtualSwitchDroppedPacketsOutgoing = "Dropped Packets Outgoing/sec" + virtualSwitchExtensionsDroppedPacketsIncoming = "Extensions Dropped Packets Incoming/sec" + virtualSwitchExtensionsDroppedPacketsOutgoing = "Extensions Dropped Packets Outgoing/sec" + virtualSwitchLearnedMacAddresses = "Learned Mac Addresses" + virtualSwitchMulticastPacketsReceived = "Multicast Packets Received/sec" + virtualSwitchMulticastPacketsSent = "Multicast Packets Sent/sec" + virtualSwitchNumberOfSendChannelMoves = "Number of Send Channel Moves/sec" + virtualSwitchNumberOfVMQMoves = "Number of VMQ Moves/sec" + virtualSwitchPacketsFlooded = "Packets Flooded" + virtualSwitchPackets = "Packets/sec" + virtualSwitchPacketsReceived = "Packets Received/sec" + virtualSwitchPacketsSent = "Packets Sent/sec" + virtualSwitchPurgedMacAddresses = "Purged Mac Addresses" +) + +func (c *Collector) buildVirtualSwitch() error { + var err error + + c.perfDataCollectorVirtualSwitch, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Virtual Switch", perfdata.AllInstances, []string{ + virtualSwitchBroadcastPacketsReceived, + virtualSwitchBroadcastPacketsSent, + virtualSwitchBytes, + virtualSwitchBytesReceived, + virtualSwitchBytesSent, + virtualSwitchDirectedPacketsReceived, + virtualSwitchDirectedPacketsSent, + virtualSwitchDroppedPacketsIncoming, + virtualSwitchDroppedPacketsOutgoing, + virtualSwitchExtensionsDroppedPacketsIncoming, + virtualSwitchExtensionsDroppedPacketsOutgoing, + virtualSwitchLearnedMacAddresses, + virtualSwitchMulticastPacketsReceived, + virtualSwitchMulticastPacketsSent, + virtualSwitchNumberOfSendChannelMoves, + virtualSwitchNumberOfVMQMoves, + virtualSwitchPacketsFlooded, + virtualSwitchPackets, + virtualSwitchPacketsReceived, + virtualSwitchPacketsSent, + virtualSwitchPurgedMacAddresses, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Virtual Switch collector: %w", err) + } + + c.virtualSwitchBroadcastPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_broadcast_packets_received_total"), + "This represents the total number of broadcast packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchBroadcastPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_broadcast_packets_sent_total"), + "This represents the total number of broadcast packets sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_total"), + "This represents the total number of bytes per second traversing the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_received_total"), + "This represents the total number of bytes received per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchBytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_sent_total"), + "This represents the total number of bytes sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchDirectedPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_directed_packets_received_total"), + "This represents the total number of directed packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchDirectedPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_directed_packets_send_total"), + "This represents the total number of directed packets sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchDroppedPacketsIncoming = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_dropped_packets_incoming_total"), + "This represents the total number of packet dropped per second by the virtual switch in the incoming direction", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchDroppedPacketsOutgoing = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_dropped_packets_outcoming_total"), + "This represents the total number of packet dropped per second by the virtual switch in the outgoing direction", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchExtensionsDroppedPacketsIncoming = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_extensions_dropped_packets_incoming_total"), + "This represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchExtensionsDroppedPacketsOutgoing = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_extensions_dropped_packets_outcoming_total"), + "This represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchLearnedMacAddresses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_learned_mac_addresses_total"), + "This counter represents the total number of learned MAC addresses of the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchMulticastPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_multicast_packets_received_total"), + "This represents the total number of multicast packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchMulticastPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_multicast_packets_sent_total"), + "This represents the total number of multicast packets sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchNumberOfSendChannelMoves = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_number_of_send_channel_moves_total"), + "This represents the total number of send channel moves per second on this virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchNumberOfVMQMoves = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_number_of_vmq_moves_total"), + "This represents the total number of VMQ moves per second on this virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchPacketsFlooded = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_flooded_total"), + "This counter represents the total number of packets flooded by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_total"), + "This represents the total number of packets per second traversing the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_received_total"), + "This represents the total number of packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_sent_total"), + "This represents the total number of packets send per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.virtualSwitchPurgedMacAddresses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "vswitch_purged_mac_addresses_total"), + "This counter represents the total number of purged MAC addresses of the virtual switch", + []string{"vswitch"}, + nil, + ) + + return nil +} + +func (c *Collector) collectVirtualSwitch(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorVirtualSwitch.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Virtual Switch metrics: %w", err) + } + + for name, switchData := range data { + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchBroadcastPacketsReceived, + prometheus.CounterValue, + switchData[virtualSwitchBroadcastPacketsReceived].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchBroadcastPacketsSent, + prometheus.CounterValue, + switchData[virtualSwitchBroadcastPacketsSent].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchBytes, + prometheus.CounterValue, + switchData[virtualSwitchBytes].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchBytesReceived, + prometheus.CounterValue, + switchData[virtualSwitchBytesReceived].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchBytesSent, + prometheus.CounterValue, + switchData[virtualSwitchBytesSent].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchDirectedPacketsReceived, + prometheus.CounterValue, + switchData[virtualSwitchDirectedPacketsReceived].FirstValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchDirectedPacketsSent, + prometheus.CounterValue, + switchData[virtualSwitchDirectedPacketsSent].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchDroppedPacketsIncoming, + prometheus.CounterValue, + switchData[virtualSwitchDroppedPacketsIncoming].FirstValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchDroppedPacketsOutgoing, + prometheus.CounterValue, + switchData[virtualSwitchDroppedPacketsOutgoing].FirstValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchExtensionsDroppedPacketsIncoming, + prometheus.CounterValue, + switchData[virtualSwitchExtensionsDroppedPacketsIncoming].FirstValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchExtensionsDroppedPacketsOutgoing, + prometheus.CounterValue, + switchData[virtualSwitchExtensionsDroppedPacketsOutgoing].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchLearnedMacAddresses, + prometheus.CounterValue, + switchData[virtualSwitchLearnedMacAddresses].FirstValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchMulticastPacketsReceived, + prometheus.CounterValue, + switchData[virtualSwitchMulticastPacketsReceived].FirstValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchMulticastPacketsSent, + prometheus.CounterValue, + switchData[virtualSwitchMulticastPacketsSent].FirstValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchNumberOfSendChannelMoves, + prometheus.CounterValue, + switchData[virtualSwitchNumberOfSendChannelMoves].FirstValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchNumberOfVMQMoves, + prometheus.CounterValue, + switchData[virtualSwitchNumberOfVMQMoves].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchPacketsFlooded, + prometheus.CounterValue, + switchData[virtualSwitchPacketsFlooded].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchPackets, + prometheus.CounterValue, + switchData[virtualSwitchPackets].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchPacketsReceived, + prometheus.CounterValue, + switchData[virtualSwitchPacketsReceived].FirstValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchPacketsSent, + prometheus.CounterValue, + switchData[virtualSwitchPacketsSent].FirstValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.virtualSwitchPurgedMacAddresses, + prometheus.CounterValue, + switchData[virtualSwitchPurgedMacAddresses].FirstValue, + name, + ) + } + + return nil +} From 7f2f6d11bd8a0a28617fe5ed8b45fb8785f424aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Fri, 1 Nov 2024 00:07:47 +0100 Subject: [PATCH 05/12] hyperv: Added DataStore, Virtual SMB and Dynamic Memory Balancer metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- docs/collector.hyperv.md | 46 ++-- internal/collector/hyperv/hyperv.go | 226 +++++++----------- .../hyperv_virtual_machine_vid_partition.go | 12 +- .../hyperv/hyperv_virtual_network_adapter.go | 139 +++++++++++ .../hyperv/hyperv_virtual_storage_device.go | 60 +++-- 5 files changed, 298 insertions(+), 185 deletions(-) create mode 100644 internal/collector/hyperv/hyperv_virtual_network_adapter.go diff --git a/docs/collector.hyperv.md b/docs/collector.hyperv.md index 9bc8a21a3..a97709917 100644 --- a/docs/collector.hyperv.md +++ b/docs/collector.hyperv.md @@ -39,8 +39,6 @@ None | `windows_hyperv_root_partition_4K_gpa_pages` | _Not yet documented_ | counter | None | | `windows_hyperv_root_partition_virtual_tlb_flush_entires` | _Not yet documented_ | counter | None | | `windows_hyperv_root_partition_virtual_tlb_pages` | _Not yet documented_ | counter | None | -| `windows_hyperv_hypervisor_virtual_processors` | _Not yet documented_ | counter | None | -| `windows_hyperv_hypervisor_logical_processors` | _Not yet documented_ | counter | None | | `windows_hyperv_host_lp_guest_run_time_percent` | _Not yet documented_ | counter | `core` | | `windows_hyperv_host_lp_hypervisor_run_time_percent` | _Not yet documented_ | counter | `core` | | `windows_hyperv_host_lp_total_run_time_percent` | _Not yet documented_ | counter | `core` | @@ -60,12 +58,17 @@ None | `windows_hyperv_ethernet_frames_dropped` | _Not yet documented_ | counter | `adapter` | | `windows_hyperv_ethernet_frames_received` | _Not yet documented_ | counter | `adapter` | | `windows_hyperv_ethernet_frames_sent` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_vm_interface_bytes_received` | _Not yet documented_ | counter | `vm_interface` | -| `windows_hyperv_vm_interface_bytes_sent` | _Not yet documented_ | counter | `vm_interface` | -| `windows_hyperv_vm_interface_packets_incoming_dropped` | _Not yet documented_ | counter | `vm_interface` | -| `windows_hyperv_vm_interface_packets_outgoing_dropped` | _Not yet documented_ | counter | `vm_interface` | -| `windows_hyperv_vm_interface_packets_received` | _Not yet documented_ | counter | `vm_interface` | -| `windows_hyperv_vm_interface_packets_sent` | _Not yet documented_ | counter | `vm_interface` | + +### Hyper-V Virtual Network Adapter + +| Name | Description | Type | Labels | +|-------------------------------------------------------------------------|----------------------|---------|-----------| +| `windows_hyperv_virtual_network_adapter_received_bytes_total` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_sent_bytes_total` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_incoming_dropped_packets_total` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_outgoing_dropped_packets_total` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_received_packets_total` | _Not yet documented_ | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_sent_packets_total` | _Not yet documented_ | counter | `adapter` | ### Hyper-V Virtual Switch @@ -95,19 +98,20 @@ None ### Hyper-V Virtual Storage Device -| Name | Description | Type | Labels | -|------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|---------|----------| -| `windows_hyperv_virtual_storage_device_error_count_total` | This counter represents the total number of errors that have occurred on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_queue_length` | This counter represents the average queue length on this virtual device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_bytes_read` | This counter represents the total number of bytes that have been read on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_operations_read_total` | This counter represents the total number of read operations that have occured on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_bytes_written` | This counter represents the total number of bytes that have been written on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_operations_written_total` | This counter represents the total number of write operations that have occured on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_latency_seconds` | This counter represents the average IO transfer latency for this virtual device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_throughput` | This counter represents the average number of 8KB IO transfers completed by this virtual device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_normalized_throughput` | This counter represents the average number of IO transfers completed by this virtual device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_lower_queue_length` | This counter represents the average queue length on the underlying storage subsystem for this device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_lower_latency_seconds` | This counter represents the average IO transfer latency on the underlying storage subsystem for this virtual device. | gauge | `device` | +| Name | Description | Type | Labels | +|---------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|---------|----------| +| `windows_hyperv_virtual_storage_device_error_count_total` | This counter represents the total number of errors that have occurred on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_queue_length` | This counter represents the average queue length on this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_bytes_read` | This counter represents the total number of bytes that have been read on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_operations_read_total` | This counter represents the total number of read operations that have occured on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_bytes_written` | This counter represents the total number of bytes that have been written on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_operations_written_total` | This counter represents the total number of write operations that have occured on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_latency_seconds` | This counter represents the average IO transfer latency for this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_throughput` | This counter represents the average number of 8KB IO transfers completed by this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_normalized_throughput` | This counter represents the average number of IO transfers completed by this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_lower_queue_length` | This counter represents the average queue length on the underlying storage subsystem for this device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_lower_latency_seconds` | This counter represents the average IO transfer latency on the underlying storage subsystem for this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_io_quota_replenishment_rate` | This counter represents the IO quota replenishment rate for this virtual device. | gauge | `device` | ### Hyper-V Dynamic Memory Balancer diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index bc3a63c12..f05505493 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -28,6 +28,7 @@ type Collector struct { collectorDynamicMemoryVM collectorVirtualMachineHealthSummary collectorVirtualMachineVidPartition + collectorVirtualNetworkAdapter collectorVirtualStorageDevice collectorVirtualSwitch @@ -54,15 +55,12 @@ type Collector struct { virtualTLBFlushEntires *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Flush Entires/sec virtualTLBPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Pages - // Win32_PerfRawData_HvStats_HyperVHypervisor - logicalProcessors *prometheus.Desc // \Hyper-V Hypervisor\Logical Processors - virtualProcessors *prometheus.Desc // \Hyper-V Hypervisor\Virtual Processors - // Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor hostLPGuestRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Guest Run Time hostLPHypervisorRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Hypervisor Run Time hostLPTotalRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Total Run Time hostLPIdleRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Idle Time + // TODO: Hyper-V Hypervisor Logical Processor(*)\Context Switches/sec // Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor hostGuestRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Run Time @@ -86,14 +84,6 @@ type Collector struct { adapterFramesReceived *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Received/sec adapterFramesSent *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Sent/sec - // Hyper-V Virtual Network Adapter metrics - vmStorageBytesReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Bytes Received/sec - vmStorageBytesSent *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Bytes Sent/sec - vmStorageDroppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Dropped Packets Incoming/sec - vmStorageDroppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Dropped Packets Outgoing/sec - vmStoragePacketsReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Received/sec - vmStoragePacketsSent *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Sent/sec - // Hyper-V DataStore metrics // TODO: \Hyper-V DataStore(*)\Fragmentation ratio // TODO: \Hyper-V DataStore(*)\Sector size @@ -170,6 +160,83 @@ type Collector struct { // TODO: \Hyper-V Virtual SMB(*)\Sent Bytes/sec // TODO: \Hyper-V Virtual SMB(*)\Received Bytes/sec + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing LowPowerPacketFilter + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming LowPowerPacketFilter + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidPDQueue + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidPDQueue + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FilteredIsolationUntagged + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FilteredIsolationUntagged + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing SwitchDataFlowDisabled + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming SwitchDataFlowDisabled + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedPacketFilter + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedPacketFilter + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NicDisabled + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NicDisabled + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedDestinationListUpdate + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedDestinationListUpdate + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InjectedIcmp + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InjectedIcmp + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing StormLimit + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming StormLimit + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidFirstNBTooSmall + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidFirstNBTooSmall + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidSourceMac + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidSourceMac + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidDestMac + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidDestMac + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidVlanFormat + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidVlanFormat + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NativeFwdingReq + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NativeFwdingReq + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing MTUMismatch + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming MTUMismatch + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidConfig + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidConfig + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing RequiredExtensionMissing + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming RequiredExtensionMissing + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing VirtualSubnetId + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming VirtualSubnetId + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing BridgeReserved + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming BridgeReserved + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing RouterGuard + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming RouterGuard + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing DhcpGuard + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming DhcpGuard + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing MacSpoofing + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming MacSpoofing + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Ipsec + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Ipsec + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Qos + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Qos + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedPvlanSetting + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedPvlanSetting + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedSecurityPolicy + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedSecurityPolicy + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing UnauthorizedMAC + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming UnauthorizedMAC + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing UnauthorizedVLAN + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming UnauthorizedVLAN + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FilteredVLAN + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FilteredVLAN + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Filtered + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Filtered + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Busy + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Busy + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NotAccepted + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NotAccepted + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Disconnected + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Disconnected + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NotReady + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NotReady + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Resources + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Resources + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidPacket + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidPacket + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidData + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidData + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Unknown + // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Unknown + } func New(config *Config) *Collector { @@ -200,9 +267,10 @@ func (c *Collector) Close(_ *slog.Logger) error { c.perfDataCollectorDynamicMemoryBalancer.Close() c.perfDataCollectorDynamicMemoryVM.Close() c.perfDataCollectorVirtualMachineHealthSummary.Close() + c.perfDataCollectorVirtualMachineVidPartition.Close() + c.perfDataCollectorVirtualNetworkAdapter.Close() c.perfDataCollectorVirtualStorageDevice.Close() c.perfDataCollectorVirtualSwitch.Close() - c.perfDataCollectorVMVidPartition.Close() return nil } @@ -228,6 +296,10 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { return err } + if err := c.buildVirtualNetworkAdapter(); err != nil { + return err + } + if err := c.buildVirtualSwitch(); err != nil { return err } @@ -361,21 +433,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { // - c.virtualProcessors = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processors"), - "The number of virtual processors present in the system", - nil, - nil, - ) - c.logicalProcessors = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "hypervisor_logical_processors"), - "The number of logical processors present in the system", - nil, - nil, - ) - - // - c.hostLPGuestRunTimePercent = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "host_lp_guest_run_time_percent"), "The percentage of time spent by the processor in guest code", @@ -500,45 +557,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { nil, ) - // - - c.vmStorageBytesReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_interface_bytes_received"), - "This counter represents the total number of bytes received per second by the network adapter", - []string{"vm_interface"}, - nil, - ) - c.vmStorageBytesSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_interface_bytes_sent"), - "This counter represents the total number of bytes sent per second by the network adapter", - []string{"vm_interface"}, - nil, - ) - c.vmStorageDroppedPacketsIncoming = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_interface_packets_incoming_dropped"), - "This counter represents the total number of dropped packets per second in the incoming direction of the network adapter", - []string{"vm_interface"}, - nil, - ) - c.vmStorageDroppedPacketsOutgoing = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_interface_packets_outgoing_dropped"), - "This counter represents the total number of dropped packets per second in the outgoing direction of the network adapter", - []string{"vm_interface"}, - nil, - ) - c.vmStoragePacketsReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_interface_packets_received"), - "This counter represents the total number of packets received per second by the network adapter", - []string{"vm_interface"}, - nil, - ) - c.vmStoragePacketsSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_interface_packets_sent"), - "This counter represents the total number of packets sent per second by the network adapter", - []string{"vm_interface"}, - nil, - ) - return nil } @@ -563,12 +581,16 @@ func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- pr errs = append(errs, fmt.Errorf("failed collecting Hyper-V VM Vid Partition metrics: %w", err)) } + if err := c.collectVirtualNetworkAdapter(ch); err != nil { + errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Network Adapter metrics: %w", err)) + } + if err := c.collectVirtualStorageDevice(ch); err != nil { errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Storage Device metrics: %w", err)) } if err := c.collectVirtualSwitch(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Storage Device metrics: %w", err)) + errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Switch metrics: %w", err)) } return errors.Join(errs...) @@ -1096,71 +1118,3 @@ func (c *Collector) collectVmStorage(ch chan<- prometheus.Metric) error { return nil } - -// Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter ... -type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct { - Name string - BytesReceivedPersec uint64 - BytesSentPersec uint64 - DroppedPacketsIncomingPersec uint64 - DroppedPacketsOutgoingPersec uint64 - PacketsReceivedPersec uint64 - PacketsSentPersec uint64 -} - -func (c *Collector) collectVmNetwork(ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter - if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter", &dst); err != nil { - return err - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "*") { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.vmStorageBytesReceived, - prometheus.CounterValue, - float64(obj.BytesReceivedPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmStorageBytesSent, - prometheus.CounterValue, - float64(obj.BytesSentPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmStorageDroppedPacketsIncoming, - prometheus.CounterValue, - float64(obj.DroppedPacketsIncomingPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmStorageDroppedPacketsOutgoing, - prometheus.CounterValue, - float64(obj.DroppedPacketsOutgoingPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmStoragePacketsReceived, - prometheus.CounterValue, - float64(obj.PacketsReceivedPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmStoragePacketsSent, - prometheus.CounterValue, - float64(obj.PacketsSentPersec), - obj.Name, - ) - } - - return nil -} diff --git a/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go index 4c8e00ef1..22c1c9ab4 100644 --- a/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go +++ b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go @@ -10,10 +10,10 @@ import ( // collectorVirtualMachineVidPartition Hyper-V VM Vid Partition metrics type collectorVirtualMachineVidPartition struct { - perfDataCollectorVMVidPartition perfdata.Collector - physicalPagesAllocated *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Physical Pages Allocated - preferredNUMANodeIndex *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Preferred NUMA Node Index - remotePhysicalPages *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Remote Physical Pages + perfDataCollectorVirtualMachineVidPartition perfdata.Collector + physicalPagesAllocated *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Physical Pages Allocated + preferredNUMANodeIndex *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Preferred NUMA Node Index + remotePhysicalPages *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Remote Physical Pages } const ( @@ -25,7 +25,7 @@ const ( func (c *Collector) buildVirtualMachineVidPartition() error { var err error - c.perfDataCollectorVMVidPartition, err = perfdata.NewCollector(perfdata.V2, "Hyper-V VM Vid Partition", perfdata.AllInstances, []string{ + c.perfDataCollectorVirtualMachineVidPartition, err = perfdata.NewCollector(perfdata.V2, "Hyper-V VM Vid Partition", perfdata.AllInstances, []string{ physicalPagesAllocated, preferredNUMANodeIndex, remotePhysicalPages, @@ -58,7 +58,7 @@ func (c *Collector) buildVirtualMachineVidPartition() error { } func (c *Collector) collectVirtualMachineVidPartition(ch chan<- prometheus.Metric) error { - data, err := c.perfDataCollectorVMVidPartition.Collect() + data, err := c.perfDataCollectorVirtualMachineVidPartition.Collect() if err != nil { return fmt.Errorf("failed to collect Hyper-V VM Vid Partition metrics: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_network_adapter.go b/internal/collector/hyperv/hyperv_virtual_network_adapter.go new file mode 100644 index 000000000..ca67ae64f --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_network_adapter.go @@ -0,0 +1,139 @@ +package hyperv + +import ( + "fmt" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorVirtualNetworkAdapter Hyper-V Virtual Network Adapter metrics +type collectorVirtualNetworkAdapter struct { + perfDataCollectorVirtualNetworkAdapter perfdata.Collector + + virtualNetworkAdapterBytesReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Bytes Received/sec + virtualNetworkAdapterBytesSent *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Bytes Sent/sec + virtualNetworkAdapterDroppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Dropped Packets Incoming/sec + virtualNetworkAdapterDroppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Dropped Packets Outgoing/sec + virtualNetworkAdapterPacketsReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Received/sec + virtualNetworkAdapterPacketsSent *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Sent/sec +} + +const ( + virtualNetworkAdapterBytesReceived = "Bytes Received/sec" + virtualNetworkAdapterBytesSent = "Bytes Sent/sec" + virtualNetworkAdapterDroppedPacketsIncoming = "Dropped Packets Incoming/sec" + virtualNetworkAdapterDroppedPacketsOutgoing = "Dropped Packets Outgoing/sec" + virtualNetworkAdapterPacketsReceived = "Packets Received/sec" + virtualNetworkAdapterPacketsSent = "Packets Sent/sec" +) + +func (c *Collector) buildVirtualNetworkAdapter() error { + var err error + + c.perfDataCollectorVirtualSwitch, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Virtual Network Adapter", perfdata.AllInstances, []string{ + virtualNetworkAdapterBytesReceived, + virtualNetworkAdapterBytesSent, + virtualNetworkAdapterDroppedPacketsIncoming, + virtualNetworkAdapterDroppedPacketsOutgoing, + virtualNetworkAdapterPacketsReceived, + virtualNetworkAdapterPacketsSent, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter collector: %w", err) + } + + c.virtualNetworkAdapterBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_received_bytes_total"), + "This counter represents the total number of bytes received per second by the network adapter", + []string{"adapter"}, + nil, + ) + c.virtualNetworkAdapterBytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_sent_bytes_total"), + "This counter represents the total number of bytes sent per second by the network adapter", + []string{"adapter"}, + nil, + ) + c.virtualNetworkAdapterDroppedPacketsIncoming = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_incoming_dropped_packets_total"), + "This counter represents the total number of dropped packets per second in the incoming direction of the network adapter", + []string{"adapter"}, + nil, + ) + c.virtualNetworkAdapterDroppedPacketsOutgoing = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_outgoing_dropped_packets_total"), + "This counter represents the total number of dropped packets per second in the outgoing direction of the network adapter", + []string{"adapter"}, + nil, + ) + c.virtualNetworkAdapterPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_received_packets_total"), + "This counter represents the total number of packets received per second by the network adapter", + []string{"adapter"}, + nil, + ) + c.virtualNetworkAdapterPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_sent_packets_total"), + "This counter represents the total number of packets sent per second by the network adapter", + []string{"adapter"}, + nil, + ) + + return nil +} + +func (c *Collector) collectVirtualNetworkAdapter(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorVirtualSwitch.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Virtual Network Adapter metrics: %w", err) + } + + for name, adapterData := range data { + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterBytesReceived, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterBytesReceived].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterBytesSent, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterBytesSent].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDroppedPacketsIncoming, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDroppedPacketsIncoming].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDroppedPacketsOutgoing, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDroppedPacketsOutgoing].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterPacketsReceived, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterPacketsReceived].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterPacketsSent, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterPacketsSent].FirstValue, + name, + ) + } + + return nil +} diff --git a/internal/collector/hyperv/hyperv_virtual_storage_device.go b/internal/collector/hyperv/hyperv_virtual_storage_device.go index 66fb2834f..b68af14bf 100644 --- a/internal/collector/hyperv/hyperv_virtual_storage_device.go +++ b/internal/collector/hyperv/hyperv_virtual_storage_device.go @@ -12,31 +12,33 @@ import ( type collectorVirtualStorageDevice struct { perfDataCollectorVirtualStorageDevice perfdata.Collector - virtualStorageDeviceErrorCount *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Error Count - virtualStorageDeviceQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Queue Length - virtualStorageDeviceReadBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Bytes/sec - virtualStorageDeviceReadOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Operations/Sec - virtualStorageDeviceWriteBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Bytes/sec - virtualStorageDeviceWriteOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Operations/Sec - virtualStorageDeviceLatency *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Latency - virtualStorageDeviceThroughput *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Throughput - virtualStorageDeviceNormalizedThroughput *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Normalized Throughput - virtualStorageDeviceLowerQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Lower Queue Length - virtualStorageDeviceLowerLatency *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Lower Latency + virtualStorageDeviceErrorCount *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Error Count + virtualStorageDeviceQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Queue Length + virtualStorageDeviceReadBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Bytes/sec + virtualStorageDeviceReadOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Operations/Sec + virtualStorageDeviceWriteBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Bytes/sec + virtualStorageDeviceWriteOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Operations/Sec + virtualStorageDeviceLatency *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Latency + virtualStorageDeviceThroughput *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Throughput + virtualStorageDeviceNormalizedThroughput *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Normalized Throughput + virtualStorageDeviceLowerQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Lower Queue Length + virtualStorageDeviceLowerLatency *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Lower Latency + virtualStorageDeviceIOQuotaReplenishmentRate *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\IO Quota Replenishment Rate } const ( - virtualStorageDeviceErrorCount = "Error Count" - virtualStorageDeviceQueueLength = "Queue Length" - virtualStorageDeviceReadBytes = "Read Bytes/sec" - virtualStorageDeviceReadOperations = "Read Count" - virtualStorageDeviceWriteBytes = "Write Bytes/sec" - virtualStorageDeviceWriteOperations = "Write Count" - virtualStorageDeviceLatency = "Latency" - virtualStorageDeviceThroughput = "Throughput" - virtualStorageDeviceNormalizedThroughput = "Normalized Throughput" - virtualStorageDeviceLowerQueueLength = "Lower Queue Length" - virtualStorageDeviceLowerLatency = "Lower Latency" + virtualStorageDeviceErrorCount = "Error Count" + virtualStorageDeviceQueueLength = "Queue Length" + virtualStorageDeviceReadBytes = "Read Bytes/sec" + virtualStorageDeviceReadOperations = "Read Count" + virtualStorageDeviceWriteBytes = "Write Bytes/sec" + virtualStorageDeviceWriteOperations = "Write Count" + virtualStorageDeviceLatency = "Latency" + virtualStorageDeviceThroughput = "Throughput" + virtualStorageDeviceNormalizedThroughput = "Normalized Throughput" + virtualStorageDeviceLowerQueueLength = "Lower Queue Length" + virtualStorageDeviceLowerLatency = "Lower Latency" + virtualStorageDeviceIOQuotaReplenishmentRate = "IO Quota Replenishment Rate" ) func (c *Collector) buildVirtualStorageDevice() error { @@ -54,6 +56,7 @@ func (c *Collector) buildVirtualStorageDevice() error { virtualStorageDeviceNormalizedThroughput, virtualStorageDeviceLowerQueueLength, virtualStorageDeviceLowerLatency, + virtualStorageDeviceIOQuotaReplenishmentRate, }) if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Storage Device collector: %w", err) @@ -125,6 +128,12 @@ func (c *Collector) buildVirtualStorageDevice() error { []string{"device"}, nil, ) + c.virtualStorageDeviceIOQuotaReplenishmentRate = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "io_quota_replenishment_rate"), + "This counter represents the IO quota replenishment rate for this virtual device.", + []string{"device"}, + nil, + ) return nil } @@ -212,6 +221,13 @@ func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric) err device[virtualStorageDeviceLowerLatency].FirstValue, name, ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceIOQuotaReplenishmentRate, + prometheus.GaugeValue, + device[virtualStorageDeviceIOQuotaReplenishmentRate].FirstValue, + name, + ) } return nil From 36c9ce0ab3f72f488158ed4231e054632785eda4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Fri, 1 Nov 2024 00:44:59 +0100 Subject: [PATCH 06/12] hyperv: Added DataStore, Virtual SMB and Dynamic Memory Balancer metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- docs/collector.hyperv.md | 63 ++-- internal/collector/hyperv/hyperv.go | 312 +--------------- .../hyperv_hypervisor_root_partition.go | 352 ++++++++++++++++++ 3 files changed, 392 insertions(+), 335 deletions(-) create mode 100644 internal/collector/hyperv/hyperv_hypervisor_root_partition.go diff --git a/docs/collector.hyperv.md b/docs/collector.hyperv.md index a97709917..3401675c7 100644 --- a/docs/collector.hyperv.md +++ b/docs/collector.hyperv.md @@ -18,27 +18,6 @@ None | Name | Description | Type | Labels | |---------------------------------------------------------------------|----------------------|---------|----------------| -| `windows_hyperv_root_partition_address_spaces` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_attached_devices` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_deposited_pages` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_device_dma_errors` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_device_interrupt_errors` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_device_interrupt_mappings` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_device_interrupt_throttle_events` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_preferred_numa_node_index` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_gpa_space_modifications` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_io_tlb_flush_cost` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_io_tlb_flush` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_recommended_virtual_tlb_size` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_physical_pages_allocated` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_1G_device_pages` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_1G_gpa_pages` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_2M_device_pages` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_2M_gpa_pages` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_4K_device_pages` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_4K_gpa_pages` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_virtual_tlb_flush_entires` | _Not yet documented_ | counter | None | -| `windows_hyperv_root_partition_virtual_tlb_pages` | _Not yet documented_ | counter | None | | `windows_hyperv_host_lp_guest_run_time_percent` | _Not yet documented_ | counter | `core` | | `windows_hyperv_host_lp_hypervisor_run_time_percent` | _Not yet documented_ | counter | `core` | | `windows_hyperv_host_lp_total_run_time_percent` | _Not yet documented_ | counter | `core` | @@ -59,16 +38,42 @@ None | `windows_hyperv_ethernet_frames_received` | _Not yet documented_ | counter | `adapter` | | `windows_hyperv_ethernet_frames_sent` | _Not yet documented_ | counter | `adapter` | +### Hyper-V Hypervisor Root Partition + +| Name | Description | Type | Labels | +|------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------| +| `windows_hyperv_root_partition_address_spaces` | The number of address spaces in the virtual TLB of the partition | gauge | None | +| `windows_hyperv_root_partition_attached_devices` | The number of devices attached to the partition | gauge | None | +| `windows_hyperv_root_partition_deposited_pages` | The number of pages deposited into the partition | gauge | None | +| `windows_hyperv_root_partition_device_dma_errors` | An indicator of illegal DMA requests generated by all devices assigned to the partition | gauge | None | +| `windows_hyperv_root_partition_device_interrupt_errors` | An indicator of illegal interrupt requests generated by all devices assigned to the partition | gauge | None | +| `windows_hyperv_root_partition_device_interrupt_mappings` | The number of device interrupt mappings used by the partition | gauge | None | +| `windows_hyperv_root_partition_device_interrupt_throttle_events` | The number of times an interrupt from a device assigned to the partition was temporarily throttled because the device was generating too many interrupts | gauge | None | +| `windows_hyperv_root_partition_preferred_numa_node_index` | The number of pages present in the GPA space of the partition (zero for root partition) | gauge | None | +| `windows_hyperv_root_partition_gpa_space_modifications` | The rate of modifications to the GPA space of the partition | counter | None | +| `windows_hyperv_root_partition_io_tlb_flush_cost` | The average time (in nanoseconds) spent processing an I/O TLB flush | gauge | None | +| `windows_hyperv_root_partition_io_tlb_flush` | The rate of flushes of I/O TLBs of the partition | counter | None | +| `windows_hyperv_root_partition_recommended_virtual_tlb_size` | The recommended number of pages to be deposited for the virtual TLB | gauge | None | +| `windows_hyperv_root_partition_physical_pages_allocated` | The number of timer interrupts skipped for the partition | gauge | None | +| `windows_hyperv_root_partition_1G_device_pages` | The number of 1G pages present in the device space of the partition | gauge | None | +| `windows_hyperv_root_partition_1G_gpa_pages` | The number of 1G pages present in the GPA space of the partition | gauge | None | +| `windows_hyperv_root_partition_2M_device_pages` | The number of 2M pages present in the device space of the partition | gauge | None | +| `windows_hyperv_root_partition_2M_gpa_pages` | The number of 2M pages present in the GPA space of the partition | gauge | None | +| `windows_hyperv_root_partition_4K_device_pages` | The number of 4K pages present in the device space of the partition | gauge | None | +| `windows_hyperv_root_partition_4K_gpa_pages` | The number of 4K pages present in the GPA space of the partition | gauge | None | +| `windows_hyperv_root_partition_virtual_tlb_flush_entires` | The rate of flushes of the entire virtual TLB | counter | None | +| `windows_hyperv_root_partition_virtual_tlb_pages` | The number of pages used by the virtual TLB of the partition | gauge | None | + ### Hyper-V Virtual Network Adapter -| Name | Description | Type | Labels | -|-------------------------------------------------------------------------|----------------------|---------|-----------| -| `windows_hyperv_virtual_network_adapter_received_bytes_total` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_virtual_network_adapter_sent_bytes_total` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_virtual_network_adapter_incoming_dropped_packets_total` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_virtual_network_adapter_outgoing_dropped_packets_total` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_virtual_network_adapter_received_packets_total` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_virtual_network_adapter_sent_packets_total` | _Not yet documented_ | counter | `adapter` | +| Name | Description | Type | Labels | +|-------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|---------|-----------| +| `windows_hyperv_virtual_network_adapter_received_bytes_total` | This counter represents the total number of bytes received per second by the network adapter | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_sent_bytes_total` | This counter represents the total number of bytes sent per second by the network adapter | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_incoming_dropped_packets_total` | This counter represents the total number of dropped packets per second in the incoming direction of the network adapter | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_outgoing_dropped_packets_total` | This counter represents the total number of dropped packets per second in the outgoing direction of the network adapter | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_received_packets_total` | This counter represents the total number of packets received per second by the network adapter | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_sent_packets_total` | This counter represents the total number of packets sent per second by the network adapter | counter | `adapter` | ### Hyper-V Virtual Switch diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index f05505493..90bad1b53 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -26,35 +26,13 @@ type Collector struct { collectorDynamicMemoryBalancer collectorDynamicMemoryVM + collectorHypervisorRootPartition collectorVirtualMachineHealthSummary collectorVirtualMachineVidPartition collectorVirtualNetworkAdapter collectorVirtualStorageDevice collectorVirtualSwitch - // Hyper-V Hypervisor Root Partition metrics - addressSpaces *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Address Spaces - attachedDevices *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Attached Devices - depositedPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Deposited Pages - deviceDMAErrors *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device DMA Errors - deviceInterruptErrors *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Errors - deviceInterruptMappings *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Mappings - deviceInterruptThrottleEvents *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Throttle Events - gpaPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\GPA Pages - gpaSpaceModifications *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\GPA Space Modifications/sec - ioTLBFlushCost *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\I/O TLB Flush Cost - ioTLBFlushes *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\I/O TLB Flushes/sec - recommendedVirtualTLBSize *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Recommended Virtual TLB Size - skippedTimerTicks *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Skipped Timer Ticks - value1Gdevicepages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\1G device pages - value1GGPApages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\1G GPA pages - value2Mdevicepages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\2M device pages - value2MGPApages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\2M GPA pages - value4Kdevicepages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\4K device pages - value4KGPApages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\4K GPA pages - virtualTLBFlushEntires *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Flush Entires/sec - virtualTLBPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Pages - // Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor hostLPGuestRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Guest Run Time hostLPHypervisorRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Hypervisor Run Time @@ -266,6 +244,7 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) { func (c *Collector) Close(_ *slog.Logger) error { c.perfDataCollectorDynamicMemoryBalancer.Close() c.perfDataCollectorDynamicMemoryVM.Close() + c.perfDataCollectorHypervisorRootPartition.Close() c.perfDataCollectorVirtualMachineHealthSummary.Close() c.perfDataCollectorVirtualMachineVidPartition.Close() c.perfDataCollectorVirtualNetworkAdapter.Close() @@ -284,6 +263,10 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { return err } + if err := c.buildHypervisorRootPartition(); err != nil { + return err + } + if err := c.buildVirtualStorageDevice(); err != nil { return err } @@ -304,133 +287,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { return err } - c.addressSpaces = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_address_spaces"), - "The number of address spaces in the virtual TLB of the partition", - nil, - nil, - ) - c.attachedDevices = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_attached_devices"), - "The number of devices attached to the partition", - nil, - nil, - ) - c.depositedPages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_deposited_pages"), - "The number of pages deposited into the partition", - nil, - nil, - ) - c.deviceDMAErrors = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_dma_errors"), - "An indicator of illegal DMA requests generated by all devices assigned to the partition", - nil, - nil, - ) - c.deviceInterruptErrors = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_errors"), - "An indicator of illegal interrupt requests generated by all devices assigned to the partition", - nil, - nil, - ) - c.deviceInterruptMappings = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_mappings"), - "The number of device interrupt mappings used by the partition", - nil, - nil, - ) - c.deviceInterruptThrottleEvents = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_throttle_events"), - "The number of times an interrupt from a device assigned to the partition was temporarily throttled because the device was generating too many interrupts", - nil, - nil, - ) - c.gpaPages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_preferred_numa_node_index"), - "The number of pages present in the GPA space of the partition (zero for root partition)", - nil, - nil, - ) - c.gpaSpaceModifications = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_gpa_space_modifications"), - "The rate of modifications to the GPA space of the partition", - nil, - nil, - ) - c.ioTLBFlushCost = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_io_tlb_flush_cost"), - "The average time (in nanoseconds) spent processing an I/O TLB flush", - nil, - nil, - ) - c.ioTLBFlushes = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_io_tlb_flush"), - "The rate of flushes of I/O TLBs of the partition", - nil, - nil, - ) - c.recommendedVirtualTLBSize = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_recommended_virtual_tlb_size"), - "The recommended number of pages to be deposited for the virtual TLB", - nil, - nil, - ) - c.skippedTimerTicks = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_physical_pages_allocated"), - "The number of timer interrupts skipped for the partition", - nil, - nil, - ) - c.value1Gdevicepages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_1G_device_pages"), - "The number of 1G pages present in the device space of the partition", - nil, - nil, - ) - c.value1GGPApages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_1G_gpa_pages"), - "The number of 1G pages present in the GPA space of the partition", - nil, - nil, - ) - c.value2Mdevicepages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_2M_device_pages"), - "The number of 2M pages present in the device space of the partition", - nil, - nil, - ) - c.value2MGPApages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_2M_gpa_pages"), - "The number of 2M pages present in the GPA space of the partition", - nil, - nil, - ) - c.value4Kdevicepages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_4K_device_pages"), - "The number of 4K pages present in the device space of the partition", - nil, - nil, - ) - c.value4KGPApages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_4K_gpa_pages"), - "The number of 4K pages present in the GPA space of the partition", - nil, - nil, - ) - c.virtualTLBFlushEntires = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_flush_entires"), - "The rate of flushes of the entire virtual TLB", - nil, - nil, - ) - c.virtualTLBPages = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_pages"), - "The number of pages used by the virtual TLB of the partition", - nil, - nil, - ) - // c.hostLPGuestRunTimePercent = prometheus.NewDesc( @@ -596,162 +452,6 @@ func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- pr return errors.Join(errs...) } -// Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition ... -type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct { - Name string - AddressSpaces uint64 - AttachedDevices uint64 - DepositedPages uint64 - DeviceDMAErrors uint64 - DeviceInterruptErrors uint64 - DeviceInterruptMappings uint64 - DeviceInterruptThrottleEvents uint64 - GPAPages uint64 - GPASpaceModificationsPersec uint64 - IOTLBFlushCost uint64 - IOTLBFlushesPersec uint64 - RecommendedVirtualTLBSize uint64 - SkippedTimerTicks uint64 - Value1Gdevicepages uint64 - Value1GGPApages uint64 - Value2Mdevicepages uint64 - Value2MGPApages uint64 - Value4Kdevicepages uint64 - Value4KGPApages uint64 - VirtualTLBFlushEntiresPersec uint64 - VirtualTLBPages uint64 -} - -func (c *Collector) collectVmHv(ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition - if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition", &dst); err != nil { - return err - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "*") { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.addressSpaces, - prometheus.GaugeValue, - float64(obj.AddressSpaces), - ) - - ch <- prometheus.MustNewConstMetric( - c.attachedDevices, - prometheus.GaugeValue, - float64(obj.AttachedDevices), - ) - - ch <- prometheus.MustNewConstMetric( - c.depositedPages, - prometheus.GaugeValue, - float64(obj.DepositedPages), - ) - - ch <- prometheus.MustNewConstMetric( - c.deviceDMAErrors, - prometheus.GaugeValue, - float64(obj.DeviceDMAErrors), - ) - - ch <- prometheus.MustNewConstMetric( - c.deviceInterruptErrors, - prometheus.GaugeValue, - float64(obj.DeviceInterruptErrors), - ) - - ch <- prometheus.MustNewConstMetric( - c.deviceInterruptThrottleEvents, - prometheus.GaugeValue, - float64(obj.DeviceInterruptThrottleEvents), - ) - - ch <- prometheus.MustNewConstMetric( - c.gpaPages, - prometheus.GaugeValue, - float64(obj.GPAPages), - ) - - ch <- prometheus.MustNewConstMetric( - c.gpaSpaceModifications, - prometheus.CounterValue, - float64(obj.GPASpaceModificationsPersec), - ) - - ch <- prometheus.MustNewConstMetric( - c.ioTLBFlushCost, - prometheus.GaugeValue, - float64(obj.IOTLBFlushCost), - ) - - ch <- prometheus.MustNewConstMetric( - c.ioTLBFlushes, - prometheus.CounterValue, - float64(obj.IOTLBFlushesPersec), - ) - - ch <- prometheus.MustNewConstMetric( - c.recommendedVirtualTLBSize, - prometheus.GaugeValue, - float64(obj.RecommendedVirtualTLBSize), - ) - - ch <- prometheus.MustNewConstMetric( - c.skippedTimerTicks, - prometheus.GaugeValue, - float64(obj.SkippedTimerTicks), - ) - - ch <- prometheus.MustNewConstMetric( - c.value1Gdevicepages, - prometheus.GaugeValue, - float64(obj.Value1Gdevicepages), - ) - - ch <- prometheus.MustNewConstMetric( - c.value1GGPApages, - prometheus.GaugeValue, - float64(obj.Value1GGPApages), - ) - - ch <- prometheus.MustNewConstMetric( - c.value2Mdevicepages, - prometheus.GaugeValue, - float64(obj.Value2Mdevicepages), - ) - ch <- prometheus.MustNewConstMetric( - c.value2MGPApages, - prometheus.GaugeValue, - float64(obj.Value2MGPApages), - ) - ch <- prometheus.MustNewConstMetric( - c.value4Kdevicepages, - prometheus.GaugeValue, - float64(obj.Value4Kdevicepages), - ) - ch <- prometheus.MustNewConstMetric( - c.value4KGPApages, - prometheus.GaugeValue, - float64(obj.Value4KGPApages), - ) - ch <- prometheus.MustNewConstMetric( - c.virtualTLBFlushEntires, - prometheus.CounterValue, - float64(obj.VirtualTLBFlushEntiresPersec), - ) - ch <- prometheus.MustNewConstMetric( - c.virtualTLBPages, - prometheus.GaugeValue, - float64(obj.VirtualTLBPages), - ) - } - - return nil -} - // Win32_PerfRawData_HvStats_HyperVHypervisor ... type Win32_PerfRawData_HvStats_HyperVHypervisor struct { LogicalProcessors uint64 diff --git a/internal/collector/hyperv/hyperv_hypervisor_root_partition.go b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go new file mode 100644 index 000000000..98afe5024 --- /dev/null +++ b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go @@ -0,0 +1,352 @@ +package hyperv + +import ( + "errors" + "fmt" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorHypervisorRootPartition Hyper-V Hypervisor Root Partition metrics +type collectorHypervisorRootPartition struct { + perfDataCollectorHypervisorRootPartition perfdata.Collector + hypervisorRootPartitionAddressSpaces *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Address Spaces + hypervisorRootPartitionAttachedDevices *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Attached Devices + hypervisorRootPartitionDepositedPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Deposited Pages + hypervisorRootPartitionDeviceDMAErrors *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device DMA Errors + hypervisorRootPartitionDeviceInterruptErrors *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Errors + hypervisorRootPartitionDeviceInterruptMappings *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Mappings + hypervisorRootPartitionDeviceInterruptThrottleEvents *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Throttle Events + hypervisorRootPartitionGPAPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\GPA Pages + hypervisorRootPartitionGPASpaceModifications *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\GPA Space Modifications/sec + hypervisorRootPartitionIOTLBFlushCost *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\I/O TLB Flush Cost + hypervisorRootPartitionIOTLBFlushes *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\I/O TLB Flushes/sec + hypervisorRootPartitionRecommendedVirtualTLBSize *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Recommended Virtual TLB Size + hypervisorRootPartitionSkippedTimerTicks *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Skipped Timer Ticks + hypervisorRootPartition1GDevicePages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\1G device pages + hypervisorRootPartition1GGPAPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\1G GPA pages + hypervisorRootPartition2MDevicePages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\2M device pages + hypervisorRootPartition2MGPAPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\2M GPA pages + hypervisorRootPartition4KDevicePages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\4K device pages + hypervisorRootPartition4KGPAPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\4K GPA pages + hypervisorRootPartitionVirtualTLBFlushEntires *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Flush Entires/sec + hypervisorRootPartitionVirtualTLBPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Pages +} + +const ( + hypervisorRootPartitionAddressSpaces = "Address Spaces" + hypervisorRootPartitionAttachedDevices = "Attached Devices" + hypervisorRootPartitionDepositedPages = "Deposited Pages" + hypervisorRootPartitionDeviceDMAErrors = "Device DMA Errors" + hypervisorRootPartitionDeviceInterruptErrors = "Device Interrupt Errors" + hypervisorRootPartitionDeviceInterruptMappings = "Device Interrupt Mappings" + hypervisorRootPartitionDeviceInterruptThrottleEvents = "Device Interrupt Throttle Events" + hypervisorRootPartitionGPAPages = "GPA Pages" + hypervisorRootPartitionGPASpaceModifications = "GPA Space Modifications/sec" + hypervisorRootPartitionIOTLBFlushCost = "I/O TLB Flush Cost" + hypervisorRootPartitionIOTLBFlushes = "I/O TLB Flushes/sec" + hypervisorRootPartitionRecommendedVirtualTLBSize = "Recommended Virtual TLB Size" + hypervisorRootPartitionSkippedTimerTicks = "Skipped Timer Ticks" + hypervisorRootPartition1GDevicePages = "1G device pages" + hypervisorRootPartition1GGPAPages = "1G GPA pages" + hypervisorRootPartition2MDevicePages = "2M device pages" + hypervisorRootPartition2MGPAPages = "2M GPA pages" + hypervisorRootPartition4KDevicePages = "4K device pages" + hypervisorRootPartition4KGPAPages = "4K GPA pages" + hypervisorRootPartitionVirtualTLBFlushEntires = "Virtual TLB Flush Entires/sec" + hypervisorRootPartitionVirtualTLBPages = "Virtual TLB Pages" +) + +func (c *Collector) buildHypervisorRootPartition() error { + var err error + + c.perfDataCollectorHypervisorRootPartition, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Hypervisor Root Partition", []string{"Root"}, []string{ + hypervisorRootPartitionAddressSpaces, + hypervisorRootPartitionAttachedDevices, + hypervisorRootPartitionDepositedPages, + hypervisorRootPartitionDeviceDMAErrors, + hypervisorRootPartitionDeviceInterruptErrors, + hypervisorRootPartitionDeviceInterruptMappings, + hypervisorRootPartitionDeviceInterruptThrottleEvents, + hypervisorRootPartitionGPAPages, + hypervisorRootPartitionGPASpaceModifications, + hypervisorRootPartitionIOTLBFlushCost, + hypervisorRootPartitionIOTLBFlushes, + hypervisorRootPartitionRecommendedVirtualTLBSize, + hypervisorRootPartitionSkippedTimerTicks, + hypervisorRootPartition1GDevicePages, + hypervisorRootPartition1GGPAPages, + hypervisorRootPartition2MDevicePages, + hypervisorRootPartition2MGPAPages, + hypervisorRootPartition4KDevicePages, + hypervisorRootPartition4KGPAPages, + hypervisorRootPartitionVirtualTLBFlushEntires, + hypervisorRootPartitionVirtualTLBPages, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Hypervisor Root Partition collector: %w", err) + } + + c.hypervisorRootPartitionAddressSpaces = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_address_spaces"), + "The number of address spaces in the virtual TLB of the partition", + nil, + nil, + ) + c.hypervisorRootPartitionAttachedDevices = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_attached_devices"), + "The number of devices attached to the partition", + nil, + nil, + ) + c.hypervisorRootPartitionDepositedPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_deposited_pages"), + "The number of pages deposited into the partition", + nil, + nil, + ) + c.hypervisorRootPartitionDeviceDMAErrors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_dma_errors"), + "An indicator of illegal DMA requests generated by all devices assigned to the partition", + nil, + nil, + ) + c.hypervisorRootPartitionDeviceInterruptErrors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_errors"), + "An indicator of illegal interrupt requests generated by all devices assigned to the partition", + nil, + nil, + ) + c.hypervisorRootPartitionDeviceInterruptMappings = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_mappings"), + "The number of device interrupt mappings used by the partition", + nil, + nil, + ) + c.hypervisorRootPartitionDeviceInterruptThrottleEvents = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_throttle_events"), + "The number of times an interrupt from a device assigned to the partition was temporarily throttled because the device was generating too many interrupts", + nil, + nil, + ) + c.hypervisorRootPartitionGPAPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_preferred_numa_node_index"), + "The number of pages present in the GPA space of the partition (zero for root partition)", + nil, + nil, + ) + c.hypervisorRootPartitionGPASpaceModifications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_gpa_space_modifications"), + "The rate of modifications to the GPA space of the partition", + nil, + nil, + ) + c.hypervisorRootPartitionIOTLBFlushCost = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_io_tlb_flush_cost"), + "The average time (in nanoseconds) spent processing an I/O TLB flush", + nil, + nil, + ) + c.hypervisorRootPartitionIOTLBFlushes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_io_tlb_flush"), + "The rate of flushes of I/O TLBs of the partition", + nil, + nil, + ) + c.hypervisorRootPartitionRecommendedVirtualTLBSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_recommended_virtual_tlb_size"), + "The recommended number of pages to be deposited for the virtual TLB", + nil, + nil, + ) + c.hypervisorRootPartitionSkippedTimerTicks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_physical_pages_allocated"), + "The number of timer interrupts skipped for the partition", + nil, + nil, + ) + c.hypervisorRootPartition1GDevicePages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_1G_device_pages"), + "The number of 1G pages present in the device space of the partition", + nil, + nil, + ) + c.hypervisorRootPartition1GGPAPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_1G_gpa_pages"), + "The number of 1G pages present in the GPA space of the partition", + nil, + nil, + ) + c.hypervisorRootPartition2MDevicePages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_2M_device_pages"), + "The number of 2M pages present in the device space of the partition", + nil, + nil, + ) + c.hypervisorRootPartition2MGPAPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_2M_gpa_pages"), + "The number of 2M pages present in the GPA space of the partition", + nil, + nil, + ) + c.hypervisorRootPartition4KDevicePages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_4K_device_pages"), + "The number of 4K pages present in the device space of the partition", + nil, + nil, + ) + c.hypervisorRootPartition4KGPAPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_4K_gpa_pages"), + "The number of 4K pages present in the GPA space of the partition", + nil, + nil, + ) + c.hypervisorRootPartitionVirtualTLBFlushEntires = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_flush_entires"), + "The rate of flushes of the entire virtual TLB", + nil, + nil, + ) + c.hypervisorRootPartitionVirtualTLBPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_pages"), + "The number of pages used by the virtual TLB of the partition", + nil, + nil, + ) + + return nil +} + +func (c *Collector) collectHypervisorRootPartition(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorHypervisorRootPartition.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Hypervisor Root Partition metrics: %w", err) + } else if len(data) == 0 { + return errors.New("no data returned from Hyper-V Hypervisor Root Partition") + } + + rootData, ok := data["Root"] + if !ok { + return errors.New("no data returned from Hyper-V Hypervisor Root Partition") + } + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionAddressSpaces, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionAddressSpaces].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionAttachedDevices, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionAttachedDevices].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionDepositedPages, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionDepositedPages].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionDeviceDMAErrors, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionDeviceDMAErrors].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionDeviceInterruptErrors, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionDeviceInterruptErrors].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionDeviceInterruptThrottleEvents, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionDeviceInterruptThrottleEvents].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionGPAPages, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionGPAPages].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionGPASpaceModifications, + prometheus.CounterValue, + rootData[hypervisorRootPartitionGPASpaceModifications].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionIOTLBFlushCost, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionIOTLBFlushCost].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionIOTLBFlushes, + prometheus.CounterValue, + rootData[hypervisorRootPartitionIOTLBFlushes].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionRecommendedVirtualTLBSize, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionRecommendedVirtualTLBSize].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionSkippedTimerTicks, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionSkippedTimerTicks].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartition1GDevicePages, + prometheus.GaugeValue, + rootData[hypervisorRootPartition1GDevicePages].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartition1GGPAPages, + prometheus.GaugeValue, + rootData[hypervisorRootPartition1GGPAPages].FirstValue, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartition2MDevicePages, + prometheus.GaugeValue, + rootData[hypervisorRootPartition2MDevicePages].FirstValue, + ) + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartition2MGPAPages, + prometheus.GaugeValue, + rootData[hypervisorRootPartition2MGPAPages].FirstValue, + ) + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartition4KDevicePages, + prometheus.GaugeValue, + rootData[hypervisorRootPartition4KDevicePages].FirstValue, + ) + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartition4KGPAPages, + prometheus.GaugeValue, + rootData[hypervisorRootPartition4KGPAPages].FirstValue, + ) + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionVirtualTLBFlushEntires, + prometheus.CounterValue, + rootData[hypervisorRootPartitionVirtualTLBFlushEntires].FirstValue, + ) + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionVirtualTLBPages, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionVirtualTLBPages].FirstValue, + ) + + return nil +} From f6b0c9151f968eddfff755003ae0699e4f7f6bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sun, 3 Nov 2024 17:49:49 +0100 Subject: [PATCH 07/12] mi: replace all WMI calls with MI calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- docs/collector.hyperv.md | 67 +++--- internal/collector/cpu/cpu.go | 25 --- internal/collector/hyperv/hyperv.go | 195 ++---------------- .../hyperv_hypervisor_logical_processor.go | 119 +++++++++++ 4 files changed, 169 insertions(+), 237 deletions(-) create mode 100644 internal/collector/hyperv/hyperv_hypervisor_logical_processor.go diff --git a/docs/collector.hyperv.md b/docs/collector.hyperv.md index 3401675c7..a633c9062 100644 --- a/docs/collector.hyperv.md +++ b/docs/collector.hyperv.md @@ -18,9 +18,6 @@ None | Name | Description | Type | Labels | |---------------------------------------------------------------------|----------------------|---------|----------------| -| `windows_hyperv_host_lp_guest_run_time_percent` | _Not yet documented_ | counter | `core` | -| `windows_hyperv_host_lp_hypervisor_run_time_percent` | _Not yet documented_ | counter | `core` | -| `windows_hyperv_host_lp_total_run_time_percent` | _Not yet documented_ | counter | `core` | | `windows_hyperv_host_cpu_guest_run_time` | _Not yet documented_ | counter | `core` | | `windows_hyperv_host_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `core` | | `windows_hyperv_host_cpu_remote_run_time` | _Not yet documented_ | counter | `core` | @@ -38,6 +35,41 @@ None | `windows_hyperv_ethernet_frames_received` | _Not yet documented_ | counter | `adapter` | | `windows_hyperv_ethernet_frames_sent` | _Not yet documented_ | counter | `adapter` | +### Hyper-V Dynamic Memory Balancer + +Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012 + +| Name | Description | Type | Labels | +|-------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|-------|------------| +| `windows_hyperv_dynamic_memory_balancer_available_memory_bytes` | This counter represents the amount of memory left on the node. | gauge | `balancer` | +| `windows_hyperv_dynamic_memory_balancer_available_memory_for_balancing_bytes` | This counter represents the available memory for balancing purposes. | gauge | `balancer` | +| `windows_hyperv_dynamic_memory_balancer_average_pressure_ratio` | This counter represents the average system pressure on the balancer node among all balanced objects. | gauge | `balancer` | +| `windows_hyperv_dynamic_memory_balancer_system_current_pressure_ratio` | This counter represents the current pressure in the system. | gauge | `balancer` | + + +### Hyper-V Dynamic Memory VM + +| Name | Description | Type | Labels | +|------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|---------|--------| +| `windows_hyperv_dynamic_memory_vm_added_bytes_total` | This counter represents the cumulative amount of memory added to the VM. | counter | `vm` | +| `windows_hyperv_dynamic_memory_vm_pressure_current_ratio` | This counter represents the current pressure in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_guest_available_bytes` | This counter represents the current amount of available memory in the VM (reported by the VM). | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_guest_visible_physical_memory_bytes` | This counter represents the amount of memory visible in the VM | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_pressure_maximum_ratio` | This counter represents the maximum pressure band in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_add_operations_total` | This counter represents the total number of add operations for the VM. | counter | `vm` | +| `windows_hyperv_dynamic_memory_vm_remove_operations_total` | This counter represents the total number of remove operations for the VM. | counter | `vm` | +| `windows_hyperv_dynamic_memory_vm_pressure_minimum_ratio` | This counter represents the minimum pressure band in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_physical` | This counter represents the current amount of memory in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_removed_bytes_total` | This counter represents the cumulative amount of memory removed from the VM. | counter | `vm` | + +### Hyper-V Hypervisor Logical Processor + +| Name | Description | Type | Labels | +|----------------------------------------------------------------------|------------------------------------------------------------------------|---------|----------------| +| `windows_hyperv_hypervisor_logical_processor_time_total` | Time that processor spent in different modes (hypervisor, guest, idle) | counter | `core`.`state` | +| `windows_hyperv_hypervisor_logical_processor_context_switches_total` | The rate of virtual processor context switches on the processor. | counter | `core` | + + ### Hyper-V Hypervisor Root Partition | Name | Description | Type | Labels | @@ -118,33 +150,6 @@ None | `windows_hyperv_virtual_storage_device_lower_latency_seconds` | This counter represents the average IO transfer latency on the underlying storage subsystem for this virtual device. | gauge | `device` | | `windows_hyperv_virtual_storage_device_io_quota_replenishment_rate` | This counter represents the IO quota replenishment rate for this virtual device. | gauge | `device` | -### Hyper-V Dynamic Memory Balancer - -Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012 - -| Name | Description | Type | Labels | -|-------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|-------|------------| -| `windows_hyperv_dynamic_memory_balancer_available_memory_bytes` | This counter represents the amount of memory left on the node. | gauge | `balancer` | -| `windows_hyperv_dynamic_memory_balancer_available_memory_for_balancing_bytes` | This counter represents the available memory for balancing purposes. | gauge | `balancer` | -| `windows_hyperv_dynamic_memory_balancer_average_pressure_ratio` | This counter represents the average system pressure on the balancer node among all balanced objects. | gauge | `balancer` | -| `windows_hyperv_dynamic_memory_balancer_system_current_pressure_ratio` | This counter represents the current pressure in the system. | gauge | `balancer` | - - -### Hyper-V Dynamic Memory VM - -| Name | Description | Type | Labels | -|------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|---------|--------| -| `windows_hyperv_dynamic_memory_vm_added_bytes_total` | This counter represents the cummulative amount of memory added to the VM. | counter | `vm` | -| `windows_hyperv_dynamic_memory_vm_pressure_current_ratio` | This counter represents the current pressure in the VM. | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_guest_available_bytes` | This counter represents the current amount of available memory in the VM (reported by the VM). | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_guest_visible_physical_memory_bytes` | This counter represents the amount of memory visible in the VM | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_pressure_maximum_ratio` | This counter represents the maximum pressure band in the VM. | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_add_operations_total` | This counter represents the total number of add operations for the VM. | counter | `vm` | -| `windows_hyperv_dynamic_memory_vm_remove_operations_total` | This counter represents the total number of remove operations for the VM. | counter | `vm` | -| `windows_hyperv_dynamic_memory_vm_pressure_minimum_ratio` | This counter represents the minimum pressure band in the VM. | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_physical` | This counter represents the current amount of memory in the VM. | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_removed_bytes_total` | This counter represents the cummulative amount of memory removed from the VM. | counter | `vm` | - ### Hyper-V VM Vid Partition | Name | Description | Type | Labels | @@ -154,7 +159,7 @@ Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavi | `windows_hyperv_vid_remote_physical_pages` | The number of physical pages not allocated from the preferred NUMA node | gauge | `vm` | -### HyperHyper-V Virtual Machine Health Summary +### Hyper-V Virtual Machine Health Summary | Name | Description | Type | Labels | |----------------------------------|-----------------------------------------------------------------------------|-------|--------| diff --git a/internal/collector/cpu/cpu.go b/internal/collector/cpu/cpu.go index e881516e8..f9d7cd06c 100644 --- a/internal/collector/cpu/cpu.go +++ b/internal/collector/cpu/cpu.go @@ -125,31 +125,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { nil, nil, ) - - c.cStateSecondsTotal = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "cstate_seconds_total"), - "Time spent in low-power idle state", - []string{"core", "state"}, - nil, - ) - c.timeTotal = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "time_total"), - "Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)", - []string{"core", "mode"}, - nil, - ) - c.interruptsTotal = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "interrupts_total"), - "Total number of received and serviced hardware interrupts", - []string{"core"}, - nil, - ) - c.dpcsTotal = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "dpcs_total"), - "Total number of received and serviced deferred procedure calls (DPCs)", - []string{"core"}, - nil, - ) c.cStateSecondsTotal = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "cstate_seconds_total"), "Time spent in low-power idle state", diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index 90bad1b53..aeb9949c3 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -26,6 +26,7 @@ type Collector struct { collectorDynamicMemoryBalancer collectorDynamicMemoryVM + collectorHypervisorLogicalProcessor collectorHypervisorRootPartition collectorVirtualMachineHealthSummary collectorVirtualMachineVidPartition @@ -33,13 +34,6 @@ type Collector struct { collectorVirtualStorageDevice collectorVirtualSwitch - // Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor - hostLPGuestRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Guest Run Time - hostLPHypervisorRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Hypervisor Run Time - hostLPTotalRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Total Run Time - hostLPIdleRunTimePercent *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Idle Time - // TODO: Hyper-V Hypervisor Logical Processor(*)\Context Switches/sec - // Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor hostGuestRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Run Time hostHypervisorRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Hypervisor Run Time @@ -244,6 +238,7 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) { func (c *Collector) Close(_ *slog.Logger) error { c.perfDataCollectorDynamicMemoryBalancer.Close() c.perfDataCollectorDynamicMemoryVM.Close() + c.perfDataCollectorHypervisorLogicalProcessor.Close() c.perfDataCollectorHypervisorRootPartition.Close() c.perfDataCollectorVirtualMachineHealthSummary.Close() c.perfDataCollectorVirtualMachineVidPartition.Close() @@ -263,6 +258,10 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { return err } + if err := c.buildHypervisorLogicalProcessor(); err != nil { + return err + } + if err := c.buildHypervisorRootPartition(); err != nil { return err } @@ -287,29 +286,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { return err } - // - - c.hostLPGuestRunTimePercent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "host_lp_guest_run_time_percent"), - "The percentage of time spent by the processor in guest code", - []string{"core"}, - nil, - ) - c.hostLPHypervisorRunTimePercent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "host_lp_hypervisor_run_time_percent"), - "The percentage of time spent by the processor in hypervisor code", - []string{"core"}, - nil, - ) - c.hostLPTotalRunTimePercent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "host_lp_total_run_time_percent"), - "The percentage of time spent by the processor in guest and hypervisor code", - []string{"core"}, - nil, - ) - - // - c.hostGuestRunTime = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "host_cpu_guest_run_time"), "The time spent by the virtual processor in guest code", @@ -429,6 +405,14 @@ func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- pr errs = append(errs, fmt.Errorf("failed collecting Hyper-V Dynamic Memory VM metrics: %w", err)) } + if err := c.collectHypervisorLogicalProcessor(ch); err != nil { + errs = append(errs, fmt.Errorf("failed collecting Hyper-V Hypervisor Logical Processor metrics: %w", err)) + } + + if err := c.collectHypervisorRootPartition(ch); err != nil { + errs = append(errs, fmt.Errorf("failed collecting Hyper-V Hypervisor Root Partition metrics: %w", err)) + } + if err := c.collectVirtualMachineHealthSummary(ch); err != nil { errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Machine Health Summary metrics: %w", err)) } @@ -452,89 +436,6 @@ func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- pr return errors.Join(errs...) } -// Win32_PerfRawData_HvStats_HyperVHypervisor ... -type Win32_PerfRawData_HvStats_HyperVHypervisor struct { - LogicalProcessors uint64 - VirtualProcessors uint64 -} - -func (c *Collector) collectVmProcessor(ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_HvStats_HyperVHypervisor - if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisor", &dst); err != nil { - return err - } - - for _, obj := range dst { - ch <- prometheus.MustNewConstMetric( - c.logicalProcessors, - prometheus.GaugeValue, - float64(obj.LogicalProcessors), - ) - - ch <- prometheus.MustNewConstMetric( - c.virtualProcessors, - prometheus.GaugeValue, - float64(obj.VirtualProcessors), - ) - } - - return nil -} - -// Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor ... -type Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor struct { - Name string - PercentGuestRunTime uint64 - PercentHypervisorRunTime uint64 - PercentTotalRunTime uint -} - -func (c *Collector) collectHostLPUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor - if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor", &dst); err != nil { - return err - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "*") { - continue - } - - // The name format is Hv LP - parts := strings.Split(obj.Name, " ") - if len(parts) != 3 { - logger.Warn(fmt.Sprintf("Unexpected format of Name in collectHostLPUsage: %q", obj.Name)) - - continue - } - - coreId := parts[2] - - ch <- prometheus.MustNewConstMetric( - c.hostLPGuestRunTimePercent, - prometheus.GaugeValue, - float64(obj.PercentGuestRunTime), - coreId, - ) - - ch <- prometheus.MustNewConstMetric( - c.hostLPHypervisorRunTimePercent, - prometheus.GaugeValue, - float64(obj.PercentHypervisorRunTime), - coreId, - ) - - ch <- prometheus.MustNewConstMetric( - c.hostLPTotalRunTimePercent, - prometheus.GaugeValue, - float64(obj.PercentTotalRunTime), - coreId, - ) - } - - return nil -} - // Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor ... type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct { Name string @@ -750,71 +651,3 @@ func (c *Collector) collectVmEthernet(ch chan<- prometheus.Metric) error { return nil } - -// Win32_PerfRawData_Counters_HyperVVirtualStorageDevice ... -type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct { - Name string - ErrorCount uint64 - QueueLength uint32 - ReadBytesPersec uint64 - ReadOperationsPerSec uint64 - WriteBytesPersec uint64 - WriteOperationsPerSec uint64 -} - -func (c *Collector) collectVmStorage(ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice - if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_Counters_HyperVVirtualStorageDevice", &dst); err != nil { - return err - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "*") { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.vmStorageErrorCount, - prometheus.CounterValue, - float64(obj.ErrorCount), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmStorageQueueLength, - prometheus.CounterValue, - float64(obj.QueueLength), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmStorageReadBytes, - prometheus.CounterValue, - float64(obj.ReadBytesPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmStorageReadOperations, - prometheus.CounterValue, - float64(obj.ReadOperationsPerSec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmStorageWriteBytes, - prometheus.CounterValue, - float64(obj.WriteBytesPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmStorageWriteOperations, - prometheus.CounterValue, - float64(obj.WriteOperationsPerSec), - obj.Name, - ) - } - - return nil -} diff --git a/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go new file mode 100644 index 000000000..9f433b981 --- /dev/null +++ b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go @@ -0,0 +1,119 @@ +package hyperv + +import ( + "errors" + "fmt" + "strings" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorHypervisorLogicalProcessor Hyper-V Hypervisor Logical Processor metrics +type collectorHypervisorLogicalProcessor struct { + perfDataCollectorHypervisorLogicalProcessor perfdata.Collector + + // \Hyper-V Hypervisor Logical Processor(*)\% Guest Run Time + // \Hyper-V Hypervisor Logical Processor(*)\% Total Run Time + // \Hyper-V Hypervisor Logical Processor(*)\% Hypervisor Run Time + // \Hyper-V Hypervisor Logical Processor(*)\% Idle Time + hypervisorLogicalProcessorRunTimeTotal *prometheus.Desc + hypervisorLogicalProcessorContextSwitches *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\Context Switches/sec +} + +const ( + hypervisorLogicalProcessorGuestRunTimePercent = "% Guest Run Time" + hypervisorLogicalProcessorHypervisorRunTimePercent = "% Hypervisor Run Time" + hypervisorLogicalProcessorTotalRunTimePercent = "% Total Run Time" + hypervisorLogicalProcessorIdleRunTimePercent = "% Idle Time" + hypervisorLogicalProcessorContextSwitches = "Context Switches/sec" +) + +func (c *Collector) buildHypervisorLogicalProcessor() error { + var err error + + c.perfDataCollectorHypervisorLogicalProcessor, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Hypervisor Logical Processor", perfdata.AllInstances, []string{ + hypervisorLogicalProcessorGuestRunTimePercent, + hypervisorLogicalProcessorHypervisorRunTimePercent, + hypervisorLogicalProcessorTotalRunTimePercent, + hypervisorLogicalProcessorIdleRunTimePercent, + hypervisorLogicalProcessorContextSwitches, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Hypervisor Logical Processor collector: %w", err) + } + + c.hypervisorLogicalProcessorRunTimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_logical_processor_time_total"), + "Time that processor spent in different modes (hypervisor, guest, idle)", + []string{"core", "state"}, + nil, + ) + + c.hypervisorLogicalProcessorContextSwitches = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_logical_processor_context_switches_total"), + "The rate of virtual processor context switches on the processor.", + []string{"core"}, + nil, + ) + + return nil +} + +func (c *Collector) collectHypervisorLogicalProcessor(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorHypervisorLogicalProcessor.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Hypervisor Logical Processor metrics: %w", err) + } else if len(data) == 0 { + return errors.New("no data returned from Hyper-V Hypervisor Root Partition") + } + + for coreName, coreData := range data { + // The name format is Hv LP + parts := strings.Split(coreName, " ") + if len(parts) != 3 { + return fmt.Errorf("unexpected Hyper-V Hypervisor Logical Processor name format: %s", coreName) + } + + coreId := parts[2] + + ch <- prometheus.MustNewConstMetric( + c.hypervisorLogicalProcessorRunTimeTotal, + prometheus.CounterValue, + coreData[hypervisorLogicalProcessorGuestRunTimePercent].FirstValue, + coreId, "guest", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorLogicalProcessorRunTimeTotal, + prometheus.CounterValue, + coreData[hypervisorLogicalProcessorHypervisorRunTimePercent].FirstValue, + coreId, "hypervisor", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorLogicalProcessorRunTimeTotal, + prometheus.CounterValue, + coreData[hypervisorLogicalProcessorIdleRunTimePercent].FirstValue, + coreId, "idle", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorLogicalProcessorRunTimeTotal, + prometheus.CounterValue, + coreData[hypervisorLogicalProcessorTotalRunTimePercent].FirstValue, + coreId, "total", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorLogicalProcessorContextSwitches, + prometheus.CounterValue, + coreData[hypervisorLogicalProcessorContextSwitches].FirstValue, + coreId, + ) + } + + return nil +} From 7ae9d60ac97c8c66829ae74812130759c00f7603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sun, 3 Nov 2024 17:52:07 +0100 Subject: [PATCH 08/12] mi: replace all WMI calls with MI calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- internal/collector/mscluster/mscluster.go | 140 +----------------- .../collector/mscluster/mscluster_cluster.go | 80 ++++++++++ .../collector/mscluster/mscluster_network.go | 8 + .../collector/mscluster/mscluster_node.go | 17 +++ .../collector/mscluster/mscluster_resource.go | 20 +++ .../mscluster/mscluster_resourcegroup.go | 17 +++ 6 files changed, 147 insertions(+), 135 deletions(-) diff --git a/internal/collector/mscluster/mscluster.go b/internal/collector/mscluster/mscluster.go index 40f03c012..91d573bb3 100644 --- a/internal/collector/mscluster/mscluster.go +++ b/internal/collector/mscluster/mscluster.go @@ -34,141 +34,11 @@ type Collector struct { config Config miSession *mi.Session - // cluster - clusterAddEvictDelay *prometheus.Desc - clusterAdminAccessPoint *prometheus.Desc - clusterAutoAssignNodeSite *prometheus.Desc - clusterAutoBalancerLevel *prometheus.Desc - clusterAutoBalancerMode *prometheus.Desc - clusterBackupInProgress *prometheus.Desc - clusterBlockCacheSize *prometheus.Desc - clusterClusSvcHangTimeout *prometheus.Desc - clusterClusSvcRegroupOpeningTimeout *prometheus.Desc - clusterClusSvcRegroupPruningTimeout *prometheus.Desc - clusterClusSvcRegroupStageTimeout *prometheus.Desc - clusterClusSvcRegroupTickInMilliseconds *prometheus.Desc - clusterClusterEnforcedAntiAffinity *prometheus.Desc - clusterClusterFunctionalLevel *prometheus.Desc - clusterClusterGroupWaitDelay *prometheus.Desc - clusterClusterLogLevel *prometheus.Desc - clusterClusterLogSize *prometheus.Desc - clusterClusterUpgradeVersion *prometheus.Desc - clusterCrossSiteDelay *prometheus.Desc - clusterCrossSiteThreshold *prometheus.Desc - clusterCrossSubnetDelay *prometheus.Desc - clusterCrossSubnetThreshold *prometheus.Desc - clusterCsvBalancer *prometheus.Desc - clusterDatabaseReadWriteMode *prometheus.Desc - clusterDefaultNetworkRole *prometheus.Desc - clusterDetectedCloudPlatform *prometheus.Desc - clusterDetectManagedEvents *prometheus.Desc - clusterDetectManagedEventsThreshold *prometheus.Desc - clusterDisableGroupPreferredOwnerRandomization *prometheus.Desc - clusterDrainOnShutdown *prometheus.Desc - clusterDynamicQuorumEnabled *prometheus.Desc - clusterEnableSharedVolumes *prometheus.Desc - clusterFixQuorum *prometheus.Desc - clusterGracePeriodEnabled *prometheus.Desc - clusterGracePeriodTimeout *prometheus.Desc - clusterGroupDependencyTimeout *prometheus.Desc - clusterHangRecoveryAction *prometheus.Desc - clusterIgnorePersistentStateOnStartup *prometheus.Desc - clusterLogResourceControls *prometheus.Desc - clusterLowerQuorumPriorityNodeId *prometheus.Desc - clusterMaxNumberOfNodes *prometheus.Desc - clusterMessageBufferLength *prometheus.Desc - clusterMinimumNeverPreemptPriority *prometheus.Desc - clusterMinimumPreemptorPriority *prometheus.Desc - clusterNetftIPSecEnabled *prometheus.Desc - clusterPlacementOptions *prometheus.Desc - clusterPlumbAllCrossSubnetRoutes *prometheus.Desc - clusterPreventQuorum *prometheus.Desc - clusterQuarantineDuration *prometheus.Desc - clusterQuarantineThreshold *prometheus.Desc - clusterQuorumArbitrationTimeMax *prometheus.Desc - clusterQuorumArbitrationTimeMin *prometheus.Desc - clusterQuorumLogFileSize *prometheus.Desc - clusterQuorumTypeValue *prometheus.Desc - clusterRequestReplyTimeout *prometheus.Desc - clusterResiliencyDefaultPeriod *prometheus.Desc - clusterResiliencyLevel *prometheus.Desc - clusterResourceDllDeadlockPeriod *prometheus.Desc - clusterRootMemoryReserved *prometheus.Desc - clusterRouteHistoryLength *prometheus.Desc - clusterS2DBusTypes *prometheus.Desc - clusterS2DCacheDesiredState *prometheus.Desc - clusterS2DCacheFlashReservePercent *prometheus.Desc - clusterS2DCachePageSizeKBytes *prometheus.Desc - clusterS2DEnabled *prometheus.Desc - clusterS2DIOLatencyThreshold *prometheus.Desc - clusterS2DOptimizations *prometheus.Desc - clusterSameSubnetDelay *prometheus.Desc - clusterSameSubnetThreshold *prometheus.Desc - clusterSecurityLevel *prometheus.Desc - clusterSecurityLevelForStorage *prometheus.Desc - clusterSharedVolumeVssWriterOperationTimeout *prometheus.Desc - clusterShutdownTimeoutInMinutes *prometheus.Desc - clusterUseClientAccessNetworksForSharedVolumes *prometheus.Desc - clusterWitnessDatabaseWriteTimeout *prometheus.Desc - clusterWitnessDynamicWeight *prometheus.Desc - clusterWitnessRestartInterval *prometheus.Desc - - // network - networkCharacteristics *prometheus.Desc - networkFlags *prometheus.Desc - networkMetric *prometheus.Desc - networkRole *prometheus.Desc - networkState *prometheus.Desc - - // node - nodeBuildNumber *prometheus.Desc - nodeCharacteristics *prometheus.Desc - nodeDetectedCloudPlatform *prometheus.Desc - nodeDynamicWeight *prometheus.Desc - nodeFlags *prometheus.Desc - nodeMajorVersion *prometheus.Desc - nodeMinorVersion *prometheus.Desc - nodeNeedsPreventQuorum *prometheus.Desc - nodeNodeDrainStatus *prometheus.Desc - nodeNodeHighestVersion *prometheus.Desc - nodeNodeLowestVersion *prometheus.Desc - nodeNodeWeight *prometheus.Desc - nodeState *prometheus.Desc - nodeStatusInformation *prometheus.Desc - - resourceCharacteristics *prometheus.Desc - resourceDeadlockTimeout *prometheus.Desc - resourceEmbeddedFailureAction *prometheus.Desc - resourceFlags *prometheus.Desc - resourceIsAlivePollInterval *prometheus.Desc - resourceLooksAlivePollInterval *prometheus.Desc - resourceMonitorProcessId *prometheus.Desc - resourceOwnerNode *prometheus.Desc - resourcePendingTimeout *prometheus.Desc - resourceResourceClass *prometheus.Desc - resourceRestartAction *prometheus.Desc - resourceRestartDelay *prometheus.Desc - resourceRestartPeriod *prometheus.Desc - resourceRestartThreshold *prometheus.Desc - resourceRetryPeriodOnFailure *prometheus.Desc - resourceState *prometheus.Desc - resourceSubClass *prometheus.Desc - - // ResourceGroup - resourceGroupAutoFailbackType *prometheus.Desc - resourceGroupCharacteristics *prometheus.Desc - resourceGroupColdStartSetting *prometheus.Desc - resourceGroupDefaultOwner *prometheus.Desc - resourceGroupFailbackWindowEnd *prometheus.Desc - resourceGroupFailbackWindowStart *prometheus.Desc - resourceGroupFailOverPeriod *prometheus.Desc - resourceGroupFailOverThreshold *prometheus.Desc - resourceGroupFlags *prometheus.Desc - resourceGroupGroupType *prometheus.Desc - resourceGroupOwnerNode *prometheus.Desc - resourceGroupPriority *prometheus.Desc - resourceGroupResiliencyPeriod *prometheus.Desc - resourceGroupState *prometheus.Desc + collectorCluster + collectorNetwork + collectorNode + collectorResource + collectorResourceGroup } func New(config *Config) *Collector { diff --git a/internal/collector/mscluster/mscluster_cluster.go b/internal/collector/mscluster/mscluster_cluster.go index 082910886..167c985b4 100644 --- a/internal/collector/mscluster/mscluster_cluster.go +++ b/internal/collector/mscluster/mscluster_cluster.go @@ -11,6 +11,86 @@ import ( const nameCluster = Name + "_cluster" +type collectorCluster struct { + clusterAddEvictDelay *prometheus.Desc + clusterAdminAccessPoint *prometheus.Desc + clusterAutoAssignNodeSite *prometheus.Desc + clusterAutoBalancerLevel *prometheus.Desc + clusterAutoBalancerMode *prometheus.Desc + clusterBackupInProgress *prometheus.Desc + clusterBlockCacheSize *prometheus.Desc + clusterClusSvcHangTimeout *prometheus.Desc + clusterClusSvcRegroupOpeningTimeout *prometheus.Desc + clusterClusSvcRegroupPruningTimeout *prometheus.Desc + clusterClusSvcRegroupStageTimeout *prometheus.Desc + clusterClusSvcRegroupTickInMilliseconds *prometheus.Desc + clusterClusterEnforcedAntiAffinity *prometheus.Desc + clusterClusterFunctionalLevel *prometheus.Desc + clusterClusterGroupWaitDelay *prometheus.Desc + clusterClusterLogLevel *prometheus.Desc + clusterClusterLogSize *prometheus.Desc + clusterClusterUpgradeVersion *prometheus.Desc + clusterCrossSiteDelay *prometheus.Desc + clusterCrossSiteThreshold *prometheus.Desc + clusterCrossSubnetDelay *prometheus.Desc + clusterCrossSubnetThreshold *prometheus.Desc + clusterCsvBalancer *prometheus.Desc + clusterDatabaseReadWriteMode *prometheus.Desc + clusterDefaultNetworkRole *prometheus.Desc + clusterDetectedCloudPlatform *prometheus.Desc + clusterDetectManagedEvents *prometheus.Desc + clusterDetectManagedEventsThreshold *prometheus.Desc + clusterDisableGroupPreferredOwnerRandomization *prometheus.Desc + clusterDrainOnShutdown *prometheus.Desc + clusterDynamicQuorumEnabled *prometheus.Desc + clusterEnableSharedVolumes *prometheus.Desc + clusterFixQuorum *prometheus.Desc + clusterGracePeriodEnabled *prometheus.Desc + clusterGracePeriodTimeout *prometheus.Desc + clusterGroupDependencyTimeout *prometheus.Desc + clusterHangRecoveryAction *prometheus.Desc + clusterIgnorePersistentStateOnStartup *prometheus.Desc + clusterLogResourceControls *prometheus.Desc + clusterLowerQuorumPriorityNodeId *prometheus.Desc + clusterMaxNumberOfNodes *prometheus.Desc + clusterMessageBufferLength *prometheus.Desc + clusterMinimumNeverPreemptPriority *prometheus.Desc + clusterMinimumPreemptorPriority *prometheus.Desc + clusterNetftIPSecEnabled *prometheus.Desc + clusterPlacementOptions *prometheus.Desc + clusterPlumbAllCrossSubnetRoutes *prometheus.Desc + clusterPreventQuorum *prometheus.Desc + clusterQuarantineDuration *prometheus.Desc + clusterQuarantineThreshold *prometheus.Desc + clusterQuorumArbitrationTimeMax *prometheus.Desc + clusterQuorumArbitrationTimeMin *prometheus.Desc + clusterQuorumLogFileSize *prometheus.Desc + clusterQuorumTypeValue *prometheus.Desc + clusterRequestReplyTimeout *prometheus.Desc + clusterResiliencyDefaultPeriod *prometheus.Desc + clusterResiliencyLevel *prometheus.Desc + clusterResourceDllDeadlockPeriod *prometheus.Desc + clusterRootMemoryReserved *prometheus.Desc + clusterRouteHistoryLength *prometheus.Desc + clusterS2DBusTypes *prometheus.Desc + clusterS2DCacheDesiredState *prometheus.Desc + clusterS2DCacheFlashReservePercent *prometheus.Desc + clusterS2DCachePageSizeKBytes *prometheus.Desc + clusterS2DEnabled *prometheus.Desc + clusterS2DIOLatencyThreshold *prometheus.Desc + clusterS2DOptimizations *prometheus.Desc + clusterSameSubnetDelay *prometheus.Desc + clusterSameSubnetThreshold *prometheus.Desc + clusterSecurityLevel *prometheus.Desc + clusterSecurityLevelForStorage *prometheus.Desc + clusterSharedVolumeVssWriterOperationTimeout *prometheus.Desc + clusterShutdownTimeoutInMinutes *prometheus.Desc + clusterUseClientAccessNetworksForSharedVolumes *prometheus.Desc + clusterWitnessDatabaseWriteTimeout *prometheus.Desc + clusterWitnessDynamicWeight *prometheus.Desc + clusterWitnessRestartInterval *prometheus.Desc +} + // msClusterCluster represents the MSCluster_Cluster WMI class // - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-cluster type msClusterCluster struct { diff --git a/internal/collector/mscluster/mscluster_network.go b/internal/collector/mscluster/mscluster_network.go index b0ed2874c..adb067271 100644 --- a/internal/collector/mscluster/mscluster_network.go +++ b/internal/collector/mscluster/mscluster_network.go @@ -11,6 +11,14 @@ import ( const nameNetwork = Name + "_network" +type collectorNetwork struct { + networkCharacteristics *prometheus.Desc + networkFlags *prometheus.Desc + networkMetric *prometheus.Desc + networkRole *prometheus.Desc + networkState *prometheus.Desc +} + // msClusterNetwork represents the MSCluster_Network WMI class // - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network type msClusterNetwork struct { diff --git a/internal/collector/mscluster/mscluster_node.go b/internal/collector/mscluster/mscluster_node.go index f89a8bc82..e230d5a04 100644 --- a/internal/collector/mscluster/mscluster_node.go +++ b/internal/collector/mscluster/mscluster_node.go @@ -11,6 +11,23 @@ import ( const nameNode = Name + "_node" +type collectorNode struct { + nodeBuildNumber *prometheus.Desc + nodeCharacteristics *prometheus.Desc + nodeDetectedCloudPlatform *prometheus.Desc + nodeDynamicWeight *prometheus.Desc + nodeFlags *prometheus.Desc + nodeMajorVersion *prometheus.Desc + nodeMinorVersion *prometheus.Desc + nodeNeedsPreventQuorum *prometheus.Desc + nodeNodeDrainStatus *prometheus.Desc + nodeNodeHighestVersion *prometheus.Desc + nodeNodeLowestVersion *prometheus.Desc + nodeNodeWeight *prometheus.Desc + nodeState *prometheus.Desc + nodeStatusInformation *prometheus.Desc +} + // msClusterNode represents the MSCluster_Node WMI class // - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node type msClusterNode struct { diff --git a/internal/collector/mscluster/mscluster_resource.go b/internal/collector/mscluster/mscluster_resource.go index 64a231a72..22ed7ffc8 100644 --- a/internal/collector/mscluster/mscluster_resource.go +++ b/internal/collector/mscluster/mscluster_resource.go @@ -11,6 +11,26 @@ import ( const nameResource = Name + "_resource" +type collectorResource struct { + resourceCharacteristics *prometheus.Desc + resourceDeadlockTimeout *prometheus.Desc + resourceEmbeddedFailureAction *prometheus.Desc + resourceFlags *prometheus.Desc + resourceIsAlivePollInterval *prometheus.Desc + resourceLooksAlivePollInterval *prometheus.Desc + resourceMonitorProcessId *prometheus.Desc + resourceOwnerNode *prometheus.Desc + resourcePendingTimeout *prometheus.Desc + resourceResourceClass *prometheus.Desc + resourceRestartAction *prometheus.Desc + resourceRestartDelay *prometheus.Desc + resourceRestartPeriod *prometheus.Desc + resourceRestartThreshold *prometheus.Desc + resourceRetryPeriodOnFailure *prometheus.Desc + resourceState *prometheus.Desc + resourceSubClass *prometheus.Desc +} + // msClusterResource represents the MSCluster_Resource WMI class // - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource type msClusterResource struct { diff --git a/internal/collector/mscluster/mscluster_resourcegroup.go b/internal/collector/mscluster/mscluster_resourcegroup.go index 94a60481c..df8ef539f 100644 --- a/internal/collector/mscluster/mscluster_resourcegroup.go +++ b/internal/collector/mscluster/mscluster_resourcegroup.go @@ -11,6 +11,23 @@ import ( const nameResourceGroup = Name + "_resourcegroup" +type collectorResourceGroup struct { + resourceGroupAutoFailbackType *prometheus.Desc + resourceGroupCharacteristics *prometheus.Desc + resourceGroupColdStartSetting *prometheus.Desc + resourceGroupDefaultOwner *prometheus.Desc + resourceGroupFailbackWindowEnd *prometheus.Desc + resourceGroupFailbackWindowStart *prometheus.Desc + resourceGroupFailOverPeriod *prometheus.Desc + resourceGroupFailOverThreshold *prometheus.Desc + resourceGroupFlags *prometheus.Desc + resourceGroupGroupType *prometheus.Desc + resourceGroupOwnerNode *prometheus.Desc + resourceGroupPriority *prometheus.Desc + resourceGroupResiliencyPeriod *prometheus.Desc + resourceGroupState *prometheus.Desc +} + // msClusterResourceGroup represents the MSCluster_ResourceGroup WMI class // - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup type msClusterResourceGroup struct { From 6e4597aa50ae5f66390db1b34ae1e61fa30bdd98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sun, 3 Nov 2024 18:10:28 +0100 Subject: [PATCH 09/12] mi: replace all WMI calls with MI calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- docs/collector.hyperv.md | 6 +++--- .../collector/hyperv/hyperv_dynamic_memory_vm.go | 4 ++-- .../hyperv/hyperv_hypervisor_root_partition.go | 14 +++++++------- .../hyperv/hyperv_virtual_storage_device.go | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/collector.hyperv.md b/docs/collector.hyperv.md index a633c9062..ffee40179 100644 --- a/docs/collector.hyperv.md +++ b/docs/collector.hyperv.md @@ -93,7 +93,7 @@ Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavi | `windows_hyperv_root_partition_2M_gpa_pages` | The number of 2M pages present in the GPA space of the partition | gauge | None | | `windows_hyperv_root_partition_4K_device_pages` | The number of 4K pages present in the device space of the partition | gauge | None | | `windows_hyperv_root_partition_4K_gpa_pages` | The number of 4K pages present in the GPA space of the partition | gauge | None | -| `windows_hyperv_root_partition_virtual_tlb_flush_entires` | The rate of flushes of the entire virtual TLB | counter | None | +| `windows_hyperv_root_partition_virtual_tlb_flush_entries` | The rate of flushes of the entire virtual TLB | counter | None | | `windows_hyperv_root_partition_virtual_tlb_pages` | The number of pages used by the virtual TLB of the partition | gauge | None | ### Hyper-V Virtual Network Adapter @@ -140,9 +140,9 @@ Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavi | `windows_hyperv_virtual_storage_device_error_count_total` | This counter represents the total number of errors that have occurred on this virtual device. | counter | `device` | | `windows_hyperv_virtual_storage_device_queue_length` | This counter represents the average queue length on this virtual device. | gauge | `device` | | `windows_hyperv_virtual_storage_device_bytes_read` | This counter represents the total number of bytes that have been read on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_operations_read_total` | This counter represents the total number of read operations that have occured on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_operations_read_total` | This counter represents the total number of read operations that have occurred on this virtual device. | counter | `device` | | `windows_hyperv_virtual_storage_device_bytes_written` | This counter represents the total number of bytes that have been written on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_operations_written_total` | This counter represents the total number of write operations that have occured on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_operations_written_total` | This counter represents the total number of write operations that have occurred on this virtual device. | counter | `device` | | `windows_hyperv_virtual_storage_device_latency_seconds` | This counter represents the average IO transfer latency for this virtual device. | gauge | `device` | | `windows_hyperv_virtual_storage_device_throughput` | This counter represents the average number of 8KB IO transfers completed by this virtual device. | gauge | `device` | | `windows_hyperv_virtual_storage_device_normalized_throughput` | This counter represents the average number of IO transfers completed by this virtual device. | gauge | `device` | diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go index a25e0f53d..25ba69463 100644 --- a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go +++ b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go @@ -60,7 +60,7 @@ func (c *Collector) buildDynamicMemoryVM() error { c.vmMemoryAddedMemory = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_added_total"), - "This counter represents the cummulative amount of memory added to the VM.", + "This counter represents the cumulative amount of memory added to the VM.", []string{"vm"}, nil, ) @@ -114,7 +114,7 @@ func (c *Collector) buildDynamicMemoryVM() error { ) c.vmMemoryRemovedMemory = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_removed_bytes_total"), - "This counter represents the cummulative amount of memory removed from the VM.", + "This counter represents the cumulative amount of memory removed from the VM.", []string{"vm"}, nil, ) diff --git a/internal/collector/hyperv/hyperv_hypervisor_root_partition.go b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go index 98afe5024..238116970 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_root_partition.go +++ b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go @@ -31,7 +31,7 @@ type collectorHypervisorRootPartition struct { hypervisorRootPartition2MGPAPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\2M GPA pages hypervisorRootPartition4KDevicePages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\4K device pages hypervisorRootPartition4KGPAPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\4K GPA pages - hypervisorRootPartitionVirtualTLBFlushEntires *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Flush Entires/sec + hypervisorRootPartitionVirtualTLBFlushEntries *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Flush Entries/sec hypervisorRootPartitionVirtualTLBPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Pages } @@ -55,7 +55,7 @@ const ( hypervisorRootPartition2MGPAPages = "2M GPA pages" hypervisorRootPartition4KDevicePages = "4K device pages" hypervisorRootPartition4KGPAPages = "4K GPA pages" - hypervisorRootPartitionVirtualTLBFlushEntires = "Virtual TLB Flush Entires/sec" + hypervisorRootPartitionVirtualTLBFlushEntries = "Virtual TLB Flush Entires/sec" hypervisorRootPartitionVirtualTLBPages = "Virtual TLB Pages" ) @@ -82,7 +82,7 @@ func (c *Collector) buildHypervisorRootPartition() error { hypervisorRootPartition2MGPAPages, hypervisorRootPartition4KDevicePages, hypervisorRootPartition4KGPAPages, - hypervisorRootPartitionVirtualTLBFlushEntires, + hypervisorRootPartitionVirtualTLBFlushEntries, hypervisorRootPartitionVirtualTLBPages, }) @@ -204,8 +204,8 @@ func (c *Collector) buildHypervisorRootPartition() error { nil, nil, ) - c.hypervisorRootPartitionVirtualTLBFlushEntires = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_flush_entires"), + c.hypervisorRootPartitionVirtualTLBFlushEntries = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_flush_entries"), "The rate of flushes of the entire virtual TLB", nil, nil, @@ -338,9 +338,9 @@ func (c *Collector) collectHypervisorRootPartition(ch chan<- prometheus.Metric) rootData[hypervisorRootPartition4KGPAPages].FirstValue, ) ch <- prometheus.MustNewConstMetric( - c.hypervisorRootPartitionVirtualTLBFlushEntires, + c.hypervisorRootPartitionVirtualTLBFlushEntries, prometheus.CounterValue, - rootData[hypervisorRootPartitionVirtualTLBFlushEntires].FirstValue, + rootData[hypervisorRootPartitionVirtualTLBFlushEntries].FirstValue, ) ch <- prometheus.MustNewConstMetric( c.hypervisorRootPartitionVirtualTLBPages, diff --git a/internal/collector/hyperv/hyperv_virtual_storage_device.go b/internal/collector/hyperv/hyperv_virtual_storage_device.go index b68af14bf..359a19d69 100644 --- a/internal/collector/hyperv/hyperv_virtual_storage_device.go +++ b/internal/collector/hyperv/hyperv_virtual_storage_device.go @@ -82,7 +82,7 @@ func (c *Collector) buildVirtualStorageDevice() error { ) c.virtualStorageDeviceReadOperations = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_operations_read_total"), - "This counter represents the total number of read operations that have occured on this virtual device.", + "This counter represents the total number of read operations that have occurred on this virtual device.", []string{"device"}, nil, ) @@ -94,7 +94,7 @@ func (c *Collector) buildVirtualStorageDevice() error { ) c.virtualStorageDeviceWriteOperations = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_operations_written_total"), - "This counter represents the total number of write operations that have occured on this virtual device.", + "This counter represents the total number of write operations that have occurred on this virtual device.", []string{"device"}, nil, ) From 4f8240f07c5d733f729b79fcca253026f470b46b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Tue, 5 Nov 2024 00:37:32 +0100 Subject: [PATCH 10/12] Refactor HyperV collector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- .github/workflows/spelling.yml | 2 +- docs/collector.hyperv.md | 198 +++---- internal/collector/cs/cs.go | 4 +- internal/collector/hyperv/hyperv.go | 532 ++++++------------ .../hyperv/hyperv_dynamic_memory_balancer.go | 8 +- .../hyperv/hyperv_dynamic_memory_vm.go | 20 +- .../hyperv_hypervisor_logical_processor.go | 26 +- ...yperv_hypervisor_root_virtual_processor.go | 137 +++++ .../hyperv_hypervisor_virtual_processor.go | 140 +++++ .../hyperv/hyperv_legacy_network_adapter.go | 139 +++++ .../hyperv_virtual_machine_health_summary.go | 4 +- .../hyperv/hyperv_virtual_network_adapter.go | 12 +- .../hyperv/hyperv_virtual_storage_device.go | 24 +- .../collector/hyperv/hyperv_virtual_switch.go | 42 +- 14 files changed, 755 insertions(+), 533 deletions(-) create mode 100644 internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go create mode 100644 internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go create mode 100644 internal/collector/hyperv/hyperv_legacy_network_adapter.go diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index 2f0e10868..db115a87d 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -23,4 +23,4 @@ jobs: check_filenames: true # When using this Action in other repos, the --skip option below can be removed skip: ./.git,go.mod,go.sum - ignore_words_list: calle + ignore_words_list: calle,Entires diff --git a/docs/collector.hyperv.md b/docs/collector.hyperv.md index ffee40179..5b37a728a 100644 --- a/docs/collector.hyperv.md +++ b/docs/collector.hyperv.md @@ -10,57 +10,39 @@ The hyperv collector exposes metrics about the Hyper-V hypervisor ## Flags -None +### `--collectors.hyperv.enabled` +Comma-separated list of collectors to use, for example: +`--collectors.hyperv.enabled=dynamic_memory_balancer,dynamic_memory_vm,hypervisor_logical_processor,hypervisor_root_partition,hypervisor_root_virtual_processor,hypervisor_virtual_processor,legacy_network_adapter,virtual_machine_health_summary,virtual_machine_vid_partition,virtual_network_adapter,virtual_storage_device,virtual_switch`. +Matching is case-sensitive. ## Metrics -### All - -| Name | Description | Type | Labels | -|---------------------------------------------------------------------|----------------------|---------|----------------| -| `windows_hyperv_host_cpu_guest_run_time` | _Not yet documented_ | counter | `core` | -| `windows_hyperv_host_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `core` | -| `windows_hyperv_host_cpu_remote_run_time` | _Not yet documented_ | counter | `core` | -| `windows_hyperv_host_cpu_total_run_time` | _Not yet documented_ | counter | `core` | -| `windows_hyperv_host_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `core` | -| `windows_hyperv_vm_cpu_guest_run_time` | _Not yet documented_ | counter | `vm`, `core` | -| `windows_hyperv_vm_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `vm`, `core` | -| `windows_hyperv_vm_cpu_remote_run_time` | _Not yet documented_ | counter | `vm`, `core` | -| `windows_hyperv_vm_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `vm`, `core` | -| `windows_hyperv_vm_cpu_total_run_time` | _Not yet documented_ | counter | `vm`, `core` | -| `windows_hyperv_ethernet_bytes_dropped` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_ethernet_bytes_received` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_ethernet_bytes_sent` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_ethernet_frames_dropped` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_ethernet_frames_received` | _Not yet documented_ | counter | `adapter` | -| `windows_hyperv_ethernet_frames_sent` | _Not yet documented_ | counter | `adapter` | - ### Hyper-V Dynamic Memory Balancer Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012 -| Name | Description | Type | Labels | -|-------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|-------|------------| -| `windows_hyperv_dynamic_memory_balancer_available_memory_bytes` | This counter represents the amount of memory left on the node. | gauge | `balancer` | -| `windows_hyperv_dynamic_memory_balancer_available_memory_for_balancing_bytes` | This counter represents the available memory for balancing purposes. | gauge | `balancer` | -| `windows_hyperv_dynamic_memory_balancer_average_pressure_ratio` | This counter represents the average system pressure on the balancer node among all balanced objects. | gauge | `balancer` | -| `windows_hyperv_dynamic_memory_balancer_system_current_pressure_ratio` | This counter represents the current pressure in the system. | gauge | `balancer` | +| Name | Description | Type | Labels | +|-------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|-------|------------| +| `windows_hyperv_dynamic_memory_balancer_available_memory_bytes` | Represents the amount of memory left on the node. | gauge | `balancer` | +| `windows_hyperv_dynamic_memory_balancer_available_memory_for_balancing_bytes` | Represents the available memory for balancing purposes. | gauge | `balancer` | +| `windows_hyperv_dynamic_memory_balancer_average_pressure_ratio` | Represents the average system pressure on the balancer node among all balanced objects. | gauge | `balancer` | +| `windows_hyperv_dynamic_memory_balancer_system_current_pressure_ratio` | Represents the current pressure in the system. | gauge | `balancer` | ### Hyper-V Dynamic Memory VM -| Name | Description | Type | Labels | -|------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|---------|--------| -| `windows_hyperv_dynamic_memory_vm_added_bytes_total` | This counter represents the cumulative amount of memory added to the VM. | counter | `vm` | -| `windows_hyperv_dynamic_memory_vm_pressure_current_ratio` | This counter represents the current pressure in the VM. | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_guest_available_bytes` | This counter represents the current amount of available memory in the VM (reported by the VM). | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_guest_visible_physical_memory_bytes` | This counter represents the amount of memory visible in the VM | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_pressure_maximum_ratio` | This counter represents the maximum pressure band in the VM. | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_add_operations_total` | This counter represents the total number of add operations for the VM. | counter | `vm` | -| `windows_hyperv_dynamic_memory_vm_remove_operations_total` | This counter represents the total number of remove operations for the VM. | counter | `vm` | -| `windows_hyperv_dynamic_memory_vm_pressure_minimum_ratio` | This counter represents the minimum pressure band in the VM. | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_physical` | This counter represents the current amount of memory in the VM. | gauge | `vm` | -| `windows_hyperv_dynamic_memory_vm_removed_bytes_total` | This counter represents the cumulative amount of memory removed from the VM. | counter | `vm` | +| Name | Description | Type | Labels | +|------------------------------------------------------------------------|-----------------------------------------------------------------------------------|---------|--------| +| `windows_hyperv_dynamic_memory_vm_added_bytes_total` | Represents the cumulative amount of memory added to the VM. | counter | `vm` | +| `windows_hyperv_dynamic_memory_vm_pressure_current_ratio` | Represents the current pressure in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_guest_available_bytes` | Represents the current amount of available memory in the VM (reported by the VM). | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_guest_visible_physical_memory_bytes` | Represents the amount of memory visible in the VM | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_pressure_maximum_ratio` | Represents the maximum pressure band in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_add_operations_total` | Represents the total number of add operations for the VM. | counter | `vm` | +| `windows_hyperv_dynamic_memory_vm_remove_operations_total` | Represents the total number of remove operations for the VM. | counter | `vm` | +| `windows_hyperv_dynamic_memory_vm_pressure_minimum_ratio` | Represents the minimum pressure band in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_physical` | Represents the current amount of memory in the VM. | gauge | `vm` | +| `windows_hyperv_dynamic_memory_vm_removed_bytes_total` | Represents the cumulative amount of memory removed from the VM. | counter | `vm` | ### Hyper-V Hypervisor Logical Processor @@ -69,7 +51,6 @@ Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavi | `windows_hyperv_hypervisor_logical_processor_time_total` | Time that processor spent in different modes (hypervisor, guest, idle) | counter | `core`.`state` | | `windows_hyperv_hypervisor_logical_processor_context_switches_total` | The rate of virtual processor context switches on the processor. | counter | `core` | - ### Hyper-V Hypervisor Root Partition | Name | Description | Type | Labels | @@ -96,59 +77,88 @@ Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavi | `windows_hyperv_root_partition_virtual_tlb_flush_entries` | The rate of flushes of the entire virtual TLB | counter | None | | `windows_hyperv_root_partition_virtual_tlb_pages` | The number of pages used by the virtual TLB of the partition | gauge | None | + +### Hyper-V Hypervisor Root Virtual Processor + +| Name | Description | Type | Labels | +|---------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|---------|----------------| +| `windows_hyperv_hypervisor_root_virtual_processor_time_total` | Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote, total) | counter | `core`.`state` | +| `windows_hyperv_hypervisor_root_virtual_cpu_wait_time_per_dispatch_total` | The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor | counter | `core` | + + +### Hyper-V Legacy Network Adapter + +| Name | Description | Type | Labels | +|---------------------------------------------------------------|-------------------------------------------------------------------------|---------|-----------| +| `windows_hyperv_legacy_network_adapter_bytes_dropped_total` | Bytes Dropped is the number of bytes dropped on the network adapter | counter | `adapter` | +| `windows_hyperv_legacy_network_adapter_bytes_received_total` | Bytes received is the number of bytes received on the network adapter | counter | `adapter` | +| `windows_hyperv_legacy_network_adapter_bytes_sent_total` | Bytes sent is the number of bytes sent over the network adapter | counter | `adapter` | +| `windows_hyperv_legacy_network_adapter_frames_dropped_total` | Frames Dropped is the number of frames dropped on the network adapter | counter | `adapter` | +| `windows_hyperv_legacy_network_adapter_frames_received_total` | Frames received is the number of frames received on the network adapter | counter | `adapter` | +| `windows_hyperv_legacy_network_adapter_frames_sent_total` | Frames sent is the number of frames sent over the network adapter | counter | `adapter` | + + +### Hyper-V Hypervisor Virtual Processor + +| Name | Description | Type | Labels | +|--------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|---------|--------------| +| `windows_hyperv_hypervisor_virtual_processor_time_total` | Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote) | counter | `vm`, `core` | +| `windows_hyperv_hypervisor_virtual_processor_total_run_time_total` | Time that processor spent | counter | `vm`, `core` | +| `windows_hyperv_hypervisor_virtual_processor_cpu_wait_time_per_dispatch_total` | The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor. | counter | `vm`, `core` | + ### Hyper-V Virtual Network Adapter -| Name | Description | Type | Labels | -|-------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|---------|-----------| -| `windows_hyperv_virtual_network_adapter_received_bytes_total` | This counter represents the total number of bytes received per second by the network adapter | counter | `adapter` | -| `windows_hyperv_virtual_network_adapter_sent_bytes_total` | This counter represents the total number of bytes sent per second by the network adapter | counter | `adapter` | -| `windows_hyperv_virtual_network_adapter_incoming_dropped_packets_total` | This counter represents the total number of dropped packets per second in the incoming direction of the network adapter | counter | `adapter` | -| `windows_hyperv_virtual_network_adapter_outgoing_dropped_packets_total` | This counter represents the total number of dropped packets per second in the outgoing direction of the network adapter | counter | `adapter` | -| `windows_hyperv_virtual_network_adapter_received_packets_total` | This counter represents the total number of packets received per second by the network adapter | counter | `adapter` | -| `windows_hyperv_virtual_network_adapter_sent_packets_total` | This counter represents the total number of packets sent per second by the network adapter | counter | `adapter` | +| Name | Description | Type | Labels | +|-------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|---------|-----------| +| `windows_hyperv_virtual_network_adapter_received_bytes_total` | Represents the total number of bytes received per second by the network adapter | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_sent_bytes_total` | Represents the total number of bytes sent per second by the network adapter | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_incoming_dropped_packets_total` | Represents the total number of dropped packets per second in the incoming direction of the network adapter | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_outgoing_dropped_packets_total` | Represents the total number of dropped packets per second in the outgoing direction of the network adapter | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_received_packets_total` | Represents the total number of packets received per second by the network adapter | counter | `adapter` | +| `windows_hyperv_virtual_network_adapter_sent_packets_total` | Represents the total number of packets sent per second by the network adapter | counter | `adapter` | ### Hyper-V Virtual Switch -| Name | Description | Type | Labels | -|---------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|---------|-----------| -| `windows_hyperv_vswitch_broadcast_packets_received_total` | This represents the total number of broadcast packets received per second by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_broadcast_packets_sent_total` | This represents the total number of broadcast packets sent per second by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_bytes_total` | This represents the total number of bytes per second traversing the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_bytes_received_total` | This represents the total number of bytes received per second by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_bytes_sent_total` | This represents the total number of bytes sent per second by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_directed_packets_received_total` | This represents the total number of directed packets received per second by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_directed_packets_send_total` | This represents the total number of directed packets sent per second by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_dropped_packets_incoming_total` | This represents the total number of packet dropped per second by the virtual switch in the incoming direction | counter | `vswitch` | -| `windows_hyperv_vswitch_dropped_packets_outcoming_total` | This represents the total number of packet dropped per second by the virtual switch in the outgoing direction | counter | `vswitch` | -| `windows_hyperv_vswitch_extensions_dropped_packets_incoming_total` | This represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction | counter | `vswitch` | -| `windows_hyperv_vswitch_extensions_dropped_packets_outcoming_total` | This represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction | counter | `vswitch` | -| `windows_hyperv_vswitch_learned_mac_addresses_total` | This counter represents the total number of learned MAC addresses of the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_multicast_packets_received_total` | This represents the total number of multicast packets received per second by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_multicast_packets_sent_total` | This represents the total number of multicast packets sent per second by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_number_of_send_channel_moves_total` | This represents the total number of send channel moves per second on this virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_number_of_vmq_moves_total` | This represents the total number of VMQ moves per second on this virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_packets_flooded_total` | This counter represents the total number of packets flooded by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_packets_total` | This represents the total number of packets per second traversing the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_packets_received_total` | This represents the total number of packets received per second by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_packets_sent_total` | This represents the total number of packets send per second by the virtual switch | counter | `vswitch` | -| `windows_hyperv_vswitch_purged_mac_addresses_total` | This counter represents the total number of purged MAC addresses of the virtual switch | counter | `vswitch` | +| Name | Description | Type | Labels | +|---------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|---------|-----------| +| `windows_hyperv_vswitch_broadcast_packets_received_total` | Represents the total number of broadcast packets received per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_broadcast_packets_sent_total` | Represents the total number of broadcast packets sent per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_bytes_total` | Represents the total number of bytes per second traversing the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_bytes_received_total` | Represents the total number of bytes received per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_bytes_sent_total` | Represents the total number of bytes sent per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_directed_packets_received_total` | Represents the total number of directed packets received per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_directed_packets_send_total` | Represents the total number of directed packets sent per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_dropped_packets_incoming_total` | Represents the total number of packet dropped per second by the virtual switch in the incoming direction | counter | `vswitch` | +| `windows_hyperv_vswitch_dropped_packets_outcoming_total` | Represents the total number of packet dropped per second by the virtual switch in the outgoing direction | counter | `vswitch` | +| `windows_hyperv_vswitch_extensions_dropped_packets_incoming_total` | Represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction | counter | `vswitch` | +| `windows_hyperv_vswitch_extensions_dropped_packets_outcoming_total` | Represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction | counter | `vswitch` | +| `windows_hyperv_vswitch_learned_mac_addresses_total` | Represents the total number of learned MAC addresses of the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_multicast_packets_received_total` | Represents the total number of multicast packets received per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_multicast_packets_sent_total` | Represents the total number of multicast packets sent per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_number_of_send_channel_moves_total` | Represents the total number of send channel moves per second on this virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_number_of_vmq_moves_total` | Represents the total number of VMQ moves per second on this virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_flooded_total` | Represents the total number of packets flooded by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_total` | Represents the total number of packets per second traversing the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_received_total` | Represents the total number of packets received per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_packets_sent_total` | Represents the total number of packets send per second by the virtual switch | counter | `vswitch` | +| `windows_hyperv_vswitch_purged_mac_addresses_total` | Represents the total number of purged MAC addresses of the virtual switch | counter | `vswitch` | ### Hyper-V Virtual Storage Device -| Name | Description | Type | Labels | -|---------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|---------|----------| -| `windows_hyperv_virtual_storage_device_error_count_total` | This counter represents the total number of errors that have occurred on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_queue_length` | This counter represents the average queue length on this virtual device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_bytes_read` | This counter represents the total number of bytes that have been read on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_operations_read_total` | This counter represents the total number of read operations that have occurred on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_bytes_written` | This counter represents the total number of bytes that have been written on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_operations_written_total` | This counter represents the total number of write operations that have occurred on this virtual device. | counter | `device` | -| `windows_hyperv_virtual_storage_device_latency_seconds` | This counter represents the average IO transfer latency for this virtual device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_throughput` | This counter represents the average number of 8KB IO transfers completed by this virtual device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_normalized_throughput` | This counter represents the average number of IO transfers completed by this virtual device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_lower_queue_length` | This counter represents the average queue length on the underlying storage subsystem for this device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_lower_latency_seconds` | This counter represents the average IO transfer latency on the underlying storage subsystem for this virtual device. | gauge | `device` | -| `windows_hyperv_virtual_storage_device_io_quota_replenishment_rate` | This counter represents the IO quota replenishment rate for this virtual device. | gauge | `device` | +| Name | Description | Type | Labels | +|---------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|---------|----------| +| `windows_hyperv_virtual_storage_device_error_count_total` | Represents the total number of errors that have occurred on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_queue_length` | Represents the average queue length on this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_bytes_read` | Represents the total number of bytes that have been read on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_operations_read_total` | Represents the total number of read operations that have occurred on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_bytes_written` | Represents the total number of bytes that have been written on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_operations_written_total` | Represents the total number of write operations that have occurred on this virtual device. | counter | `device` | +| `windows_hyperv_virtual_storage_device_latency_seconds` | Represents the average IO transfer latency for this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_throughput` | Represents the average number of 8KB IO transfers completed by this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_normalized_throughput` | Represents the average number of IO transfers completed by this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_lower_queue_length` | Represents the average queue length on the underlying storage subsystem for this device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_lower_latency_seconds` | Represents the average IO transfer latency on the underlying storage subsystem for this virtual device. | gauge | `device` | +| `windows_hyperv_virtual_storage_device_io_quota_replenishment_rate` | Represents the IO quota replenishment rate for this virtual device. | gauge | `device` | ### Hyper-V VM Vid Partition @@ -161,10 +171,10 @@ Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavi ### Hyper-V Virtual Machine Health Summary -| Name | Description | Type | Labels | -|----------------------------------|-----------------------------------------------------------------------------|-------|--------| -| `windows_hyperv_health_critical` | This counter represents the number of virtual machines with critical health | gauge | None | -| `windows_hyperv_health_ok` | This counter represents the number of virtual machines with ok health | gauge | None | +| Name | Description | Type | Labels | +|----------------------------------|----------------------------------------------------------------|-------|--------| +| `windows_hyperv_health_critical` | Represents the number of virtual machines with critical health | gauge | None | +| `windows_hyperv_health_ok` | Represents the number of virtual machines with ok health | gauge | None | ### Example metric @@ -173,19 +183,19 @@ _This collector does not yet have explained examples, we would appreciate your h ## Useful queries Percent of physical CPU resources used per VM (on instance "localhost") ``` -(sum (rate(windows_hyperv_vm_cpu_hypervisor_run_time{instance="localhost"}[1m]))) / ignoring(vm) group_left max (windows_cs_logical_processors{instance="localhost"}) / 100000 +(sum (rate(windows_hyperv_hypervisor_virtual_processor_time_total{state="hypervisor",instance="localhost"}[1m]))) / ignoring(state,vm) group_left max (windows_cpu_logical_processor{instance="localhost"}) / 100000 ``` Percent of physical CPU resources used by all VMs (on all monitored hosts) ``` -(sum by (instance)(rate(windows_hyperv_vm_cpu_total_run_time{}[1m]))) / max by (instance)(windows_cs_logical_processors{}) / 100000 +(sum by (instance)(rate(windows_hyperv_hypervisor_virtual_processor_total_run_time_total{}[1m]))) / max by (instance)(windows_cpu_logical_processor{}) / 100000 ``` Percent of physical CPU resources by the hosts themselves (on all monitored hosts) ``` -(sum by (instance)(rate(windows_hyperv_host_cpu_total_run_time{}[1m]))) / sum by (instance)(windows_cs_logical_processors{}) / 100000 +(sum by (instance)(rate(windows_hyperv_hypervisor_root_virtual_processor_total_run_time_total{state="total"}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) / 100000 ``` Percent of physical CPU resources by the hypervisor (on all monitored hosts) ``` -(sum by (instance)(rate(windows_hyperv_host_lp_total_run_time_percent{}[1m]))) / sum by (instance)(windows_hyperv_hypervisor_logical_processors{}) / 100000 +(sum by (instance)(rate(windows_hyperv_hypervisor_logical_processor_total_run_time_total{}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) / 100000 ``` ## Alerting examples diff --git a/internal/collector/cs/cs.go b/internal/collector/cs/cs.go index b6bc1ae5d..306a3237a 100644 --- a/internal/collector/cs/cs.go +++ b/internal/collector/cs/cs.go @@ -23,10 +23,10 @@ type Collector struct { config Config // physicalMemoryBytes - // Deprecated: Use windows_cpu_logical_processor instead + // Deprecated: Use windows_physical_memory_total_bytes instead physicalMemoryBytes *prometheus.Desc // logicalProcessors - // Deprecated: Use windows_physical_memory_total_bytes instead + // Deprecated: Use windows_cpu_logical_processor instead logicalProcessors *prometheus.Desc // hostname // Deprecated: Use windows_os_hostname instead diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index aeb9949c3..8afdcf785 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -4,58 +4,59 @@ package hyperv import ( "errors" - "fmt" "log/slog" + "slices" "strings" + "sync" "github.com/alecthomas/kingpin/v2" + "github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) const Name = "hyperv" -type Config struct{} +type Config struct { + CollectorsEnabled []string `yaml:"collectors_enabled"` +} -var ConfigDefaults = Config{} +var ConfigDefaults = Config{ + CollectorsEnabled: []string{ + "dynamic_memory_balancer", + "dynamic_memory_vm", + "hypervisor_logical_processor", + "hypervisor_root_partition", + "hypervisor_root_virtual_processor", + "hypervisor_virtual_processor", + "legacy_network_adapter", + "virtual_machine_health_summary", + "virtual_machine_vid_partition", + "virtual_network_adapter", + "virtual_storage_device", + "virtual_switch", + }, +} // Collector is a Prometheus Collector for hyper-v. type Collector struct { config Config + collectorFns []func(ch chan<- prometheus.Metric) error + collectorDynamicMemoryBalancer collectorDynamicMemoryVM collectorHypervisorLogicalProcessor collectorHypervisorRootPartition + collectorHypervisorRootVirtualProcessor + collectorHypervisorVirtualProcessor + collectorLegacyNetworkAdapter collectorVirtualMachineHealthSummary collectorVirtualMachineVidPartition collectorVirtualNetworkAdapter collectorVirtualStorageDevice collectorVirtualSwitch - // Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor - hostGuestRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Run Time - hostHypervisorRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Hypervisor Run Time - hostRemoteRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Remote Run Time - hostTotalRunTime *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\% Total Run Time - hostCPUWaitTimePerDispatch *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\CPU Wait Time Per Dispatch - - // Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor - vmGuestRunTime *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Guest Run Time - vmHypervisorRunTime *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Hypervisor Run Time - vmRemoteRunTime *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Remote Run Time - vmTotalRunTime *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Total Run Time - vmCPUWaitTimePerDispatch *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per Dispatch - - // Hyper-V Legacy Network Adapter metrics - adapterBytesDropped *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Dropped - adapterBytesReceived *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Received/sec - adapterBytesSent *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Sent/sec - adapterFramesDropped *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Dropped - adapterFramesReceived *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Received/sec - adapterFramesSent *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Sent/sec - // Hyper-V DataStore metrics // TODO: \Hyper-V DataStore(*)\Fragmentation ratio // TODO: \Hyper-V DataStore(*)\Sector size @@ -216,6 +217,10 @@ func New(config *Config) *Collector { config = &ConfigDefaults } + if config.CollectorsEnabled == nil { + config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled + } + c := &Collector{ config: *config, } @@ -223,8 +228,26 @@ func New(config *Config) *Collector { return c } -func NewWithFlags(_ *kingpin.Application) *Collector { - return &Collector{} +func NewWithFlags(app *kingpin.Application) *Collector { + c := &Collector{ + config: ConfigDefaults, + } + c.config.CollectorsEnabled = make([]string, 0) + + var collectorsEnabled string + + app.Flag( + "collector.hyperv.enabled", + "Comma-separated list of collectors to use.", + ).Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringVar(&collectorsEnabled) + + app.Action(func(*kingpin.ParseContext) error { + c.config.CollectorsEnabled = strings.Split(collectorsEnabled, ",") + + return nil + }) + + return c } func (c *Collector) GetName() string { @@ -236,418 +259,185 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) { } func (c *Collector) Close(_ *slog.Logger) error { - c.perfDataCollectorDynamicMemoryBalancer.Close() - c.perfDataCollectorDynamicMemoryVM.Close() - c.perfDataCollectorHypervisorLogicalProcessor.Close() - c.perfDataCollectorHypervisorRootPartition.Close() - c.perfDataCollectorVirtualMachineHealthSummary.Close() - c.perfDataCollectorVirtualMachineVidPartition.Close() - c.perfDataCollectorVirtualNetworkAdapter.Close() - c.perfDataCollectorVirtualStorageDevice.Close() - c.perfDataCollectorVirtualSwitch.Close() + if slices.Contains(c.config.CollectorsEnabled, "dynamic_memory_balancer") { + c.perfDataCollectorDynamicMemoryBalancer.Close() + } - return nil -} + if slices.Contains(c.config.CollectorsEnabled, "dynamic_memory_vm") { + c.perfDataCollectorDynamicMemoryVM.Close() + } -func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error { - if err := c.buildDynamicMemoryBalancer(); err != nil { - return err + if slices.Contains(c.config.CollectorsEnabled, "hypervisor_logical_processor") { + c.perfDataCollectorHypervisorLogicalProcessor.Close() } - if err := c.buildDynamicMemoryVM(); err != nil { - return err + if slices.Contains(c.config.CollectorsEnabled, "hypervisor_root_partition") { + c.perfDataCollectorHypervisorRootPartition.Close() } - if err := c.buildHypervisorLogicalProcessor(); err != nil { - return err + if slices.Contains(c.config.CollectorsEnabled, "hypervisor_root_virtual_processor") { + c.perfDataCollectorHypervisorRootVirtualProcessor.Close() } - if err := c.buildHypervisorRootPartition(); err != nil { - return err + if slices.Contains(c.config.CollectorsEnabled, "hypervisor_virtual_processor") { + c.perfDataCollectorHypervisorVirtualProcessor.Close() } - if err := c.buildVirtualStorageDevice(); err != nil { - return err + if slices.Contains(c.config.CollectorsEnabled, "legacy_network_adapter") { + c.perfDataCollectorLegacyNetworkAdapter.Close() } - if err := c.buildVirtualMachineHealthSummary(); err != nil { - return err + if slices.Contains(c.config.CollectorsEnabled, "virtual_machine_health_summary") { + c.perfDataCollectorVirtualMachineHealthSummary.Close() } - if err := c.buildVirtualMachineVidPartition(); err != nil { - return err + if slices.Contains(c.config.CollectorsEnabled, "virtual_machine_vid_partition") { + c.perfDataCollectorVirtualMachineVidPartition.Close() } - if err := c.buildVirtualNetworkAdapter(); err != nil { - return err + if slices.Contains(c.config.CollectorsEnabled, "virtual_network_adapter") { + c.perfDataCollectorVirtualNetworkAdapter.Close() } - if err := c.buildVirtualSwitch(); err != nil { - return err + if slices.Contains(c.config.CollectorsEnabled, "virtual_storage_device") { + c.perfDataCollectorVirtualStorageDevice.Close() } - c.hostGuestRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "host_cpu_guest_run_time"), - "The time spent by the virtual processor in guest code", - []string{"core"}, - nil, - ) - c.hostHypervisorRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "host_cpu_hypervisor_run_time"), - "The time spent by the virtual processor in hypervisor code", - []string{"core"}, - nil, - ) - c.hostRemoteRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "host_cpu_remote_run_time"), - "The time spent by the virtual processor running on a remote node", - []string{"core"}, - nil, - ) - c.hostTotalRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "host_cpu_total_run_time"), - "The time spent by the virtual processor in guest and hypervisor code", - []string{"core"}, - nil, - ) - c.hostCPUWaitTimePerDispatch = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "host_cpu_wait_time_per_dispatch_total"), - "Time in nanoseconds waiting for a virtual processor to be dispatched onto a logical processor", - []string{"core"}, - nil, - ) - - // - - c.vmGuestRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_cpu_guest_run_time"), - "The time spent by the virtual processor in guest code", - []string{"vm", "core"}, - nil, - ) - c.vmHypervisorRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_cpu_hypervisor_run_time"), - "The time spent by the virtual processor in hypervisor code", - []string{"vm", "core"}, - nil, - ) - c.vmRemoteRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_cpu_remote_run_time"), - "The time spent by the virtual processor running on a remote node", - []string{"vm", "core"}, - nil, - ) - c.vmTotalRunTime = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_cpu_total_run_time"), - "The time spent by the virtual processor in guest and hypervisor code", - []string{"vm", "core"}, - nil, - ) - c.vmCPUWaitTimePerDispatch = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "vm_cpu_wait_time_per_dispatch_total"), - "Time in nanoseconds waiting for a virtual processor to be dispatched onto a logical processor", - []string{"vm", "core"}, - nil, - ) - - // - - c.adapterBytesDropped = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "ethernet_bytes_dropped"), - "Bytes Dropped is the number of bytes dropped on the network adapter", - []string{"adapter"}, - nil, - ) - c.adapterBytesReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "ethernet_bytes_received"), - "Bytes received is the number of bytes received on the network adapter", - []string{"adapter"}, - nil, - ) - c.adapterBytesSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "ethernet_bytes_sent"), - "Bytes sent is the number of bytes sent over the network adapter", - []string{"adapter"}, - nil, - ) - c.adapterFramesDropped = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "ethernet_frames_dropped"), - "Frames Dropped is the number of frames dropped on the network adapter", - []string{"adapter"}, - nil, - ) - c.adapterFramesReceived = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "ethernet_frames_received"), - "Frames received is the number of frames received on the network adapter", - []string{"adapter"}, - nil, - ) - c.adapterFramesSent = prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, "ethernet_frames_sent"), - "Frames sent is the number of frames sent over the network adapter", - []string{"adapter"}, - nil, - ) + if slices.Contains(c.config.CollectorsEnabled, "virtual_switch") { + c.perfDataCollectorVirtualSwitch.Close() + } return nil } -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error { - errs := make([]error, 0, 4) +func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { + c.collectorFns = make([]func(ch chan<- prometheus.Metric) error, 0, len(c.config.CollectorsEnabled)) - if err := c.collectDynamicMemoryBalancer(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting Hyper-V Dynamic Memory Balancer metrics: %w", err)) - } + if slices.Contains(c.config.CollectorsEnabled, "dynamic_memory_balancer") { + if err := c.buildDynamicMemoryBalancer(); err != nil { + return err + } - if err := c.collectDynamicMemoryVM(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting Hyper-V Dynamic Memory VM metrics: %w", err)) + c.collectorFns = append(c.collectorFns, c.collectDynamicMemoryBalancer) } - if err := c.collectHypervisorLogicalProcessor(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting Hyper-V Hypervisor Logical Processor metrics: %w", err)) - } + if slices.Contains(c.config.CollectorsEnabled, "dynamic_memory_vm") { + if err := c.buildDynamicMemoryVM(); err != nil { + return err + } - if err := c.collectHypervisorRootPartition(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting Hyper-V Hypervisor Root Partition metrics: %w", err)) + c.collectorFns = append(c.collectorFns, c.collectDynamicMemoryVM) } - if err := c.collectVirtualMachineHealthSummary(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Machine Health Summary metrics: %w", err)) - } + if slices.Contains(c.config.CollectorsEnabled, "hypervisor_logical_processor") { + if err := c.buildHypervisorLogicalProcessor(); err != nil { + return err + } - if err := c.collectVirtualMachineVidPartition(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting Hyper-V VM Vid Partition metrics: %w", err)) + c.collectorFns = append(c.collectorFns, c.collectHypervisorLogicalProcessor) } - if err := c.collectVirtualNetworkAdapter(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Network Adapter metrics: %w", err)) - } + if slices.Contains(c.config.CollectorsEnabled, "hypervisor_root_partition") { + if err := c.buildHypervisorRootPartition(); err != nil { + return err + } - if err := c.collectVirtualStorageDevice(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Storage Device metrics: %w", err)) + c.collectorFns = append(c.collectorFns, c.collectHypervisorRootPartition) } - if err := c.collectVirtualSwitch(ch); err != nil { - errs = append(errs, fmt.Errorf("failed collecting Hyper-V Virtual Switch metrics: %w", err)) - } + if slices.Contains(c.config.CollectorsEnabled, "hypervisor_root_virtual_processor") { + if err := c.buildHypervisorRootVirtualProcessor(); err != nil { + return err + } - return errors.Join(errs...) -} + c.collectorFns = append(c.collectorFns, c.collectHypervisorRootVirtualProcessor) + } -// Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor ... -type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct { - Name string - PercentGuestRunTime uint64 - PercentHypervisorRunTime uint64 - PercentRemoteRunTime uint64 - PercentTotalRunTime uint64 - CPUWaitTimePerDispatch uint64 -} + if slices.Contains(c.config.CollectorsEnabled, "hypervisor_virtual_processor") { + if err := c.buildHypervisorVirtualProcessor(); err != nil { + return err + } -func (c *Collector) collectHostCpuUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor - if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor", &dst); err != nil { - return err + c.collectorFns = append(c.collectorFns, c.collectHypervisorVirtualProcessor) } - for _, obj := range dst { - if strings.Contains(obj.Name, "*") { - continue + if slices.Contains(c.config.CollectorsEnabled, "legacy_network_adapter") { + if err := c.buildLegacyNetworkAdapter(); err != nil { + return err } - // The name format is Root VP - parts := strings.Split(obj.Name, " ") - if len(parts) != 3 { - logger.Warn("Unexpected format of Name in collectHostCpuUsage: " + obj.Name) + c.collectorFns = append(c.collectorFns, c.collectLegacyNetworkAdapter) + } - continue + if slices.Contains(c.config.CollectorsEnabled, "virtual_machine_health_summary") { + if err := c.buildVirtualMachineHealthSummary(); err != nil { + return err } - coreId := parts[2] - - ch <- prometheus.MustNewConstMetric( - c.hostGuestRunTime, - prometheus.GaugeValue, - float64(obj.PercentGuestRunTime), - coreId, - ) - - ch <- prometheus.MustNewConstMetric( - c.hostHypervisorRunTime, - prometheus.GaugeValue, - float64(obj.PercentHypervisorRunTime), - coreId, - ) - - ch <- prometheus.MustNewConstMetric( - c.hostRemoteRunTime, - prometheus.GaugeValue, - float64(obj.PercentRemoteRunTime), - coreId, - ) - - ch <- prometheus.MustNewConstMetric( - c.hostTotalRunTime, - prometheus.GaugeValue, - float64(obj.PercentTotalRunTime), - coreId, - ) - - ch <- prometheus.MustNewConstMetric( - c.hostCPUWaitTimePerDispatch, - prometheus.CounterValue, - float64(obj.CPUWaitTimePerDispatch), - coreId, - ) + c.collectorFns = append(c.collectorFns, c.collectVirtualMachineHealthSummary) } - return nil -} - -// Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor ... -type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct { - Name string - PercentGuestRunTime uint64 - PercentHypervisorRunTime uint64 - PercentRemoteRunTime uint64 - PercentTotalRunTime uint64 - CPUWaitTimePerDispatch uint64 -} + if slices.Contains(c.config.CollectorsEnabled, "virtual_machine_vid_partition") { + if err := c.buildVirtualMachineVidPartition(); err != nil { + return err + } -func (c *Collector) collectVmCpuUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor - if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor", &dst); err != nil { - return err + c.collectorFns = append(c.collectorFns, c.collectVirtualMachineVidPartition) } - for _, obj := range dst { - if strings.Contains(obj.Name, "*") { - continue + if slices.Contains(c.config.CollectorsEnabled, "virtual_network_adapter") { + if err := c.buildVirtualNetworkAdapter(); err != nil { + return err } - // The name format is :Hv VP - parts := strings.Split(obj.Name, ":") - if len(parts) != 2 { - logger.Warn(fmt.Sprintf("Unexpected format of Name in collectVmCpuUsage: %q, expected %q. Skipping.", obj.Name, ":Hv VP ")) + c.collectorFns = append(c.collectorFns, c.collectVirtualNetworkAdapter) + } - continue + if slices.Contains(c.config.CollectorsEnabled, "virtual_storage_device") { + if err := c.buildVirtualStorageDevice(); err != nil { + return err } - coreParts := strings.Split(parts[1], " ") - if len(coreParts) != 3 { - logger.Warn(fmt.Sprintf("Unexpected format of core identifier in collectVmCpuUsage: %q, expected %q. Skipping.", parts[1], "Hv VP ")) + c.collectorFns = append(c.collectorFns, c.collectVirtualStorageDevice) + } - continue + if slices.Contains(c.config.CollectorsEnabled, "virtual_switch") { + if err := c.buildVirtualSwitch(); err != nil { + return err } - vmName := parts[0] - coreId := coreParts[2] - - ch <- prometheus.MustNewConstMetric( - c.vmGuestRunTime, - prometheus.GaugeValue, - float64(obj.PercentGuestRunTime), - vmName, coreId, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmHypervisorRunTime, - prometheus.GaugeValue, - float64(obj.PercentHypervisorRunTime), - vmName, coreId, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmRemoteRunTime, - prometheus.GaugeValue, - float64(obj.PercentRemoteRunTime), - vmName, coreId, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmTotalRunTime, - prometheus.GaugeValue, - float64(obj.PercentTotalRunTime), - vmName, coreId, - ) - - ch <- prometheus.MustNewConstMetric( - c.vmCPUWaitTimePerDispatch, - prometheus.CounterValue, - float64(obj.CPUWaitTimePerDispatch), - vmName, coreId, - ) + c.collectorFns = append(c.collectorFns, c.collectVirtualSwitch) } return nil } -// Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter ... -type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct { - Name string - BytesDropped uint64 - BytesReceivedPersec uint64 - BytesSentPersec uint64 - FramesDropped uint64 - FramesReceivedPersec uint64 - FramesSentPersec uint64 -} +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error { + errCh := make(chan error, len(c.collectorFns)) + errs := make([]error, 0, len(c.collectorFns)) -func (c *Collector) collectVmEthernet(ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter - if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter", &dst); err != nil { - return err + wg := sync.WaitGroup{} + + for _, fn := range c.collectorFns { + wg.Add(1) + go func(fn func(ch chan<- prometheus.Metric) error) { + defer wg.Done() + + if err := fn(ch); err != nil { + errCh <- err + } + }(fn) } - for _, obj := range dst { - if strings.Contains(obj.Name, "*") { - continue - } + wg.Wait() - ch <- prometheus.MustNewConstMetric( - c.adapterBytesDropped, - prometheus.GaugeValue, - float64(obj.BytesDropped), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.adapterBytesReceived, - prometheus.CounterValue, - float64(obj.BytesReceivedPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.adapterBytesSent, - prometheus.CounterValue, - float64(obj.BytesSentPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.adapterFramesReceived, - prometheus.CounterValue, - float64(obj.FramesReceivedPersec), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.adapterFramesDropped, - prometheus.CounterValue, - float64(obj.FramesDropped), - obj.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.adapterFramesSent, - prometheus.CounterValue, - float64(obj.FramesSentPersec), - obj.Name, - ) + close(errCh) + + for err := range errCh { + errs = append(errs, err) } - return nil + return errors.Join(errs...) } diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go index 4d84bc77c..cefab9bd0 100644 --- a/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go +++ b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go @@ -44,25 +44,25 @@ func (c *Collector) buildDynamicMemoryBalancer() error { c.vmDynamicMemoryBalancerAvailableMemory = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_available_memory_bytes"), - "This counter represents the amount of memory left on the node.", + "Represents the amount of memory left on the node.", []string{"balancer"}, nil, ) c.vmDynamicMemoryBalancerAvailableMemoryForBalancing = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_available_memory_for_balancing_bytes"), - "This counter represents the available memory for balancing purposes.", + "Represents the available memory for balancing purposes.", []string{"balancer"}, nil, ) c.vmDynamicMemoryBalancerAveragePressure = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_average_pressure_ratio"), - "This counter represents the average system pressure on the balancer node among all balanced objects.", + "Represents the average system pressure on the balancer node among all balanced objects.", []string{"balancer"}, nil, ) c.vmDynamicMemoryBalancerSystemCurrentPressure = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_system_current_pressure_ratio"), - "This counter represents the current pressure in the system.", + "Represents the current pressure in the system.", []string{"balancer"}, nil, ) diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go index 25ba69463..28e8e3d1e 100644 --- a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go +++ b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go @@ -60,61 +60,61 @@ func (c *Collector) buildDynamicMemoryVM() error { c.vmMemoryAddedMemory = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_added_total"), - "This counter represents the cumulative amount of memory added to the VM.", + "Represents the cumulative amount of memory added to the VM.", []string{"vm"}, nil, ) c.vmMemoryCurrentPressure = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_pressure_current_ratio"), - "This counter represents the current pressure in the VM.", + "Represents the current pressure in the VM.", []string{"vm"}, nil, ) c.vmMemoryGuestAvailableMemory = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_guest_available_bytes"), - "This counter represents the current amount of available memory in the VM (reported by the VM).", + "Represents the current amount of available memory in the VM (reported by the VM).", []string{"vm"}, nil, ) c.vmMemoryGuestVisiblePhysicalMemory = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_guest_visible_physical_memory_bytes"), - "This counter represents the amount of memory visible in the VM.'", + "Represents the amount of memory visible in the VM.'", []string{"vm"}, nil, ) c.vmMemoryMaximumPressure = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_pressure_maximum_ratio"), - "This counter represents the maximum pressure band in the VM.", + "Represents the maximum pressure band in the VM.", []string{"vm"}, nil, ) c.vmMemoryMemoryAddOperations = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_add_operations_total"), - "This counter represents the total number of add operations for the VM.", + "Represents the total number of add operations for the VM.", []string{"vm"}, nil, ) c.vmMemoryMemoryRemoveOperations = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_remove_operations_total"), - "This counter represents the total number of remove operations for the VM.", + "Represents the total number of remove operations for the VM.", []string{"vm"}, nil, ) c.vmMemoryMinimumPressure = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_pressure_minimum_ratio"), - "This counter represents the minimum pressure band in the VM.", + "Represents the minimum pressure band in the VM.", []string{"vm"}, nil, ) c.vmMemoryPhysicalMemory = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_physical_bytes"), - "This counter represents the current amount of memory in the VM.", + "Represents the current amount of memory in the VM.", []string{"vm"}, nil, ) c.vmMemoryRemovedMemory = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_removed_bytes_total"), - "This counter represents the cumulative amount of memory removed from the VM.", + "Represents the cumulative amount of memory removed from the VM.", []string{"vm"}, nil, ) diff --git a/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go index 9f433b981..bfbab4906 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go +++ b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go @@ -15,11 +15,11 @@ type collectorHypervisorLogicalProcessor struct { perfDataCollectorHypervisorLogicalProcessor perfdata.Collector // \Hyper-V Hypervisor Logical Processor(*)\% Guest Run Time - // \Hyper-V Hypervisor Logical Processor(*)\% Total Run Time // \Hyper-V Hypervisor Logical Processor(*)\% Hypervisor Run Time // \Hyper-V Hypervisor Logical Processor(*)\% Idle Time - hypervisorLogicalProcessorRunTimeTotal *prometheus.Desc - hypervisorLogicalProcessorContextSwitches *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\Context Switches/sec + hypervisorLogicalProcessorTimeTotal *prometheus.Desc + hypervisorLogicalProcessorTotalRunTimeTotal *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Total Run Time + hypervisorLogicalProcessorContextSwitches *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\Context Switches/sec } const ( @@ -45,12 +45,18 @@ func (c *Collector) buildHypervisorLogicalProcessor() error { return fmt.Errorf("failed to create Hyper-V Hypervisor Logical Processor collector: %w", err) } - c.hypervisorLogicalProcessorRunTimeTotal = prometheus.NewDesc( + c.hypervisorLogicalProcessorTimeTotal = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "hypervisor_logical_processor_time_total"), "Time that processor spent in different modes (hypervisor, guest, idle)", []string{"core", "state"}, nil, ) + c.hypervisorLogicalProcessorTotalRunTimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_logical_processor_total_run_time_total"), + "Time that processor spent", + []string{"core"}, + nil, + ) c.hypervisorLogicalProcessorContextSwitches = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "hypervisor_logical_processor_context_switches_total"), @@ -67,7 +73,7 @@ func (c *Collector) collectHypervisorLogicalProcessor(ch chan<- prometheus.Metri if err != nil { return fmt.Errorf("failed to collect Hyper-V Hypervisor Logical Processor metrics: %w", err) } else if len(data) == 0 { - return errors.New("no data returned from Hyper-V Hypervisor Root Partition") + return errors.New("no data returned from Hyper-V Hypervisor Logical Processor") } for coreName, coreData := range data { @@ -80,31 +86,31 @@ func (c *Collector) collectHypervisorLogicalProcessor(ch chan<- prometheus.Metri coreId := parts[2] ch <- prometheus.MustNewConstMetric( - c.hypervisorLogicalProcessorRunTimeTotal, + c.hypervisorLogicalProcessorTimeTotal, prometheus.CounterValue, coreData[hypervisorLogicalProcessorGuestRunTimePercent].FirstValue, coreId, "guest", ) ch <- prometheus.MustNewConstMetric( - c.hypervisorLogicalProcessorRunTimeTotal, + c.hypervisorLogicalProcessorTimeTotal, prometheus.CounterValue, coreData[hypervisorLogicalProcessorHypervisorRunTimePercent].FirstValue, coreId, "hypervisor", ) ch <- prometheus.MustNewConstMetric( - c.hypervisorLogicalProcessorRunTimeTotal, + c.hypervisorLogicalProcessorTimeTotal, prometheus.CounterValue, coreData[hypervisorLogicalProcessorIdleRunTimePercent].FirstValue, coreId, "idle", ) ch <- prometheus.MustNewConstMetric( - c.hypervisorLogicalProcessorRunTimeTotal, + c.hypervisorLogicalProcessorTotalRunTimeTotal, prometheus.CounterValue, coreData[hypervisorLogicalProcessorTotalRunTimePercent].FirstValue, - coreId, "total", + coreId, ) ch <- prometheus.MustNewConstMetric( diff --git a/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go b/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go new file mode 100644 index 000000000..1e2b4dff6 --- /dev/null +++ b/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go @@ -0,0 +1,137 @@ +package hyperv + +import ( + "errors" + "fmt" + "strings" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorHypervisorRootVirtualProcessor Hyper-V Hypervisor Root Virtual Processor metrics +type collectorHypervisorRootVirtualProcessor struct { + perfDataCollectorHypervisorRootVirtualProcessor perfdata.Collector + + // \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Idle Time + // \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Run Time + // \Hyper-V Hypervisor Root Virtual Processor(*)\% Hypervisor Run Time + // \Hyper-V Hypervisor Root Virtual Processor(*)\% Remote Run Time + // \Hyper-V Hypervisor Root Virtual Processor(*)\% Total Run Time + hypervisorRootVirtualProcessorTimeTotal *prometheus.Desc + hypervisorRootVirtualProcessorTotalRunTimeTotal *prometheus.Desc + hypervisorRootVirtualProcessorCPUWaitTimePerDispatch *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\CPU Wait Time Per Dispatch +} + +const ( + hypervisorRootVirtualProcessorGuestIdleTimePercent = "% Guest Idle Time" + hypervisorRootVirtualProcessorGuestRunTimePercent = "% Guest Run Time" + hypervisorRootVirtualProcessorHypervisorRunTimePercent = "% Hypervisor Run Time" + hypervisorRootVirtualProcessorTotalRunTimePercent = "% Total Run Time" + hypervisorRootVirtualProcessorRemoteRunTimePercent = "% Remote Run Time" + hypervisorRootVirtualProcessorCPUWaitTimePerDispatch = "CPU Wait Time Per Dispatch" +) + +func (c *Collector) buildHypervisorRootVirtualProcessor() error { + var err error + + c.perfDataCollectorHypervisorRootVirtualProcessor, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Hypervisor Root Virtual Processor", perfdata.AllInstances, []string{ + hypervisorRootVirtualProcessorGuestIdleTimePercent, + hypervisorRootVirtualProcessorGuestRunTimePercent, + hypervisorRootVirtualProcessorHypervisorRunTimePercent, + hypervisorRootVirtualProcessorTotalRunTimePercent, + hypervisorRootVirtualProcessorRemoteRunTimePercent, + hypervisorRootVirtualProcessorCPUWaitTimePerDispatch, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Hypervisor Root Virtual Processor collector: %w", err) + } + + c.hypervisorRootVirtualProcessorTimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_root_virtual_processor_time_total"), + "Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote)", + []string{"core", "state"}, + nil, + ) + + c.hypervisorRootVirtualProcessorTotalRunTimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_root_virtual_processor_total_run_time_total"), + "Time that processor spent", + []string{"core"}, + nil, + ) + + c.hypervisorRootVirtualProcessorCPUWaitTimePerDispatch = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_root_virtual_cpu_wait_time_per_dispatch_total"), + "The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor.", + []string{"core"}, + nil, + ) + + return nil +} + +func (c *Collector) collectHypervisorRootVirtualProcessor(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorHypervisorRootVirtualProcessor.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Hypervisor Root Virtual Processor metrics: %w", err) + } else if len(data) == 0 { + return errors.New("no data returned from Hyper-V Hypervisor Root Virtual Processor") + } + + for coreName, coreData := range data { + // The name format is Hv LP + parts := strings.Split(coreName, " ") + if len(parts) != 3 { + return fmt.Errorf("unexpected Hyper-V Hypervisor Root Virtual Processor name format: %s", coreName) + } + + coreId := parts[2] + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootVirtualProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorRootVirtualProcessorGuestRunTimePercent].FirstValue, + coreId, "guest_run", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootVirtualProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorRootVirtualProcessorHypervisorRunTimePercent].FirstValue, + coreId, "hypervisor", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootVirtualProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorRootVirtualProcessorGuestIdleTimePercent].FirstValue, + coreId, "guest_idle", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootVirtualProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorRootVirtualProcessorRemoteRunTimePercent].FirstValue, + coreId, "remote", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootVirtualProcessorTotalRunTimeTotal, + prometheus.CounterValue, + coreData[hypervisorRootVirtualProcessorTotalRunTimePercent].FirstValue, + coreId, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootVirtualProcessorCPUWaitTimePerDispatch, + prometheus.CounterValue, + coreData[hypervisorRootVirtualProcessorCPUWaitTimePerDispatch].FirstValue, + coreId, + ) + } + + return nil +} diff --git a/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go b/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go new file mode 100644 index 000000000..565168ecc --- /dev/null +++ b/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go @@ -0,0 +1,140 @@ +package hyperv + +import ( + "errors" + "fmt" + "strings" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorHypervisorVirtualProcessor Hyper-V Hypervisor Virtual Processor metrics +type collectorHypervisorVirtualProcessor struct { + perfDataCollectorHypervisorVirtualProcessor perfdata.Collector + + // \Hyper-V Hypervisor Virtual Processor(*)\% Guest Idle Time + // \Hyper-V Hypervisor Virtual Processor(*)\% Guest Run Time + // \Hyper-V Hypervisor Virtual Processor(*)\% Hypervisor Run Time + // \Hyper-V Hypervisor Virtual Processor(*)\% Remote Run Time + hypervisorVirtualProcessorTimeTotal *prometheus.Desc + hypervisorVirtualProcessorTotalRunTimeTotal *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Total Run Time + hypervisorVirtualProcessorContextSwitches *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per Dispatch +} + +const ( + hypervisorVirtualProcessorGuestRunTimePercent = "% Guest Run Time" + hypervisorVirtualProcessorGuestIdleTimePercent = "% Guest Idle Time" + hypervisorVirtualProcessorHypervisorRunTimePercent = "% Hypervisor Run Time" + hypervisorVirtualProcessorTotalRunTimePercent = "% Total Run Time" + hypervisorVirtualProcessorRemoteRunTimePercent = "% Remote Run Time" + hypervisorVirtualProcessorCPUWaitTimePerDispatch = "CPU Wait Time Per Dispatch" +) + +func (c *Collector) buildHypervisorVirtualProcessor() error { + var err error + + c.perfDataCollectorHypervisorVirtualProcessor, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Hypervisor Virtual Processor", perfdata.AllInstances, []string{ + hypervisorVirtualProcessorGuestRunTimePercent, + hypervisorVirtualProcessorGuestIdleTimePercent, + hypervisorVirtualProcessorHypervisorRunTimePercent, + hypervisorVirtualProcessorTotalRunTimePercent, + hypervisorVirtualProcessorRemoteRunTimePercent, + hypervisorVirtualProcessorCPUWaitTimePerDispatch, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Hypervisor Virtual Processor collector: %w", err) + } + + c.hypervisorVirtualProcessorTimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_time_total"), + "Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote)", + []string{"vm", "core", "state"}, + nil, + ) + c.hypervisorVirtualProcessorTotalRunTimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_total_run_time_total"), + "Time that processor spent", + []string{"vm", "core"}, + nil, + ) + c.hypervisorVirtualProcessorContextSwitches = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_cpu_wait_time_per_dispatch_total"), + "The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor.", + []string{"vm", "core"}, + nil, + ) + + return nil +} + +func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorHypervisorVirtualProcessor.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Hypervisor Virtual Processor metrics: %w", err) + } else if len(data) == 0 { + return errors.New("no data returned from Hyper-V Hypervisor Virtual Processor") + } + + for coreName, coreData := range data { + // The name format is :Hv VP + parts := strings.Split(coreName, ":") + if len(parts) != 2 { + return fmt.Errorf("unexpected format of Name in Hyper-V Hypervisor Virtual Processor: %q, expected %q", coreName, ":Hv VP ") + } + + coreParts := strings.Split(parts[1], " ") + if len(coreParts) != 3 { + return fmt.Errorf("unexpected format of core identifier in Hyper-V Hypervisor Virtual Processor: %q, expected %q", parts[1], "Hv VP ") + } + + vmName := parts[0] + coreId := coreParts[2] + + ch <- prometheus.MustNewConstMetric( + c.hypervisorVirtualProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorVirtualProcessorGuestRunTimePercent].FirstValue, + vmName, coreId, "guest_run", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorVirtualProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorVirtualProcessorHypervisorRunTimePercent].FirstValue, + vmName, coreId, "hypervisor", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorVirtualProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorVirtualProcessorGuestIdleTimePercent].FirstValue, + vmName, coreId, "guest_idle", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorVirtualProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorVirtualProcessorGuestIdleTimePercent].FirstValue, + vmName, coreId, "guest_idle", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorVirtualProcessorTotalRunTimeTotal, + prometheus.CounterValue, + coreData[hypervisorVirtualProcessorTotalRunTimePercent].FirstValue, + vmName, coreId, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorVirtualProcessorContextSwitches, + prometheus.CounterValue, + coreData[hypervisorVirtualProcessorCPUWaitTimePerDispatch].FirstValue, + vmName, coreId, + ) + } + + return nil +} diff --git a/internal/collector/hyperv/hyperv_legacy_network_adapter.go b/internal/collector/hyperv/hyperv_legacy_network_adapter.go new file mode 100644 index 000000000..757193330 --- /dev/null +++ b/internal/collector/hyperv/hyperv_legacy_network_adapter.go @@ -0,0 +1,139 @@ +package hyperv + +import ( + "fmt" + + "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" + "github.com/prometheus/client_golang/prometheus" +) + +// collectorLegacyNetworkAdapter Hyper-V Legacy Network Adapter metrics +type collectorLegacyNetworkAdapter struct { + perfDataCollectorLegacyNetworkAdapter perfdata.Collector + + legacyNetworkAdapterBytesDropped *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Dropped + legacyNetworkAdapterBytesReceived *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Received/sec + legacyNetworkAdapterBytesSent *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Sent/sec + legacyNetworkAdapterFramesDropped *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Dropped + legacyNetworkAdapterFramesReceived *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Received/sec + legacyNetworkAdapterFramesSent *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Sent/sec +} + +const ( + legacyNetworkAdapterBytesDropped = "Bytes Dropped" + legacyNetworkAdapterBytesReceived = "Bytes Received/sec" + legacyNetworkAdapterBytesSent = "Bytes Sent/sec" + legacyNetworkAdapterFramesDropped = "Frames Dropped" + legacyNetworkAdapterFramesReceived = "Frames Received/sec" + legacyNetworkAdapterFramesSent = "Frames Sent/sec" +) + +func (c *Collector) buildLegacyNetworkAdapter() error { + var err error + + c.perfDataCollectorLegacyNetworkAdapter, err = perfdata.NewCollector(perfdata.V2, "Hyper-V Legacy Network Adapter", perfdata.AllInstances, []string{ + legacyNetworkAdapterBytesDropped, + legacyNetworkAdapterBytesReceived, + legacyNetworkAdapterBytesSent, + legacyNetworkAdapterFramesDropped, + legacyNetworkAdapterFramesReceived, + legacyNetworkAdapterFramesSent, + }) + + if err != nil { + return fmt.Errorf("failed to create Hyper-V Legacy Network Adapter collector: %w", err) + } + + c.legacyNetworkAdapterBytesDropped = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_bytes_dropped_total"), + "Bytes Dropped is the number of bytes dropped on the network adapter", + []string{"adapter"}, + nil, + ) + c.legacyNetworkAdapterBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_bytes_received_total"), + "Bytes received is the number of bytes received on the network adapter", + []string{"adapter"}, + nil, + ) + c.legacyNetworkAdapterBytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_bytes_sent_total"), + "Bytes sent is the number of bytes sent over the network adapter", + []string{"adapter"}, + nil, + ) + c.legacyNetworkAdapterFramesDropped = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_frames_dropped_total"), + "Frames Dropped is the number of frames dropped on the network adapter", + []string{"adapter"}, + nil, + ) + c.legacyNetworkAdapterFramesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_frames_received_total"), + "Frames received is the number of frames received on the network adapter", + []string{"adapter"}, + nil, + ) + c.legacyNetworkAdapterFramesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_frames_sent_total"), + "Frames sent is the number of frames sent over the network adapter", + []string{"adapter"}, + nil, + ) + + return nil +} + +func (c *Collector) collectLegacyNetworkAdapter(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorLegacyNetworkAdapter.Collect() + if err != nil { + return fmt.Errorf("failed to collect Hyper-V Legacy Network Adapter metrics: %w", err) + } + + for name, adapter := range data { + ch <- prometheus.MustNewConstMetric( + c.legacyNetworkAdapterBytesDropped, + prometheus.GaugeValue, + adapter[legacyNetworkAdapterBytesDropped].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.legacyNetworkAdapterBytesReceived, + prometheus.CounterValue, + adapter[legacyNetworkAdapterBytesReceived].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.legacyNetworkAdapterBytesSent, + prometheus.CounterValue, + adapter[legacyNetworkAdapterBytesSent].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.legacyNetworkAdapterFramesReceived, + prometheus.CounterValue, + adapter[legacyNetworkAdapterFramesReceived].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.legacyNetworkAdapterFramesDropped, + prometheus.CounterValue, + adapter[legacyNetworkAdapterFramesDropped].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.legacyNetworkAdapterFramesSent, + prometheus.CounterValue, + adapter[legacyNetworkAdapterFramesSent].FirstValue, + name, + ) + } + + return nil +} diff --git a/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go index 2419b3161..1d95ff533 100644 --- a/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go +++ b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go @@ -37,13 +37,13 @@ func (c *Collector) buildVirtualMachineHealthSummary() error { c.healthCritical = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "health_critical"), - "This counter represents the number of virtual machines with critical health", + "Represents the number of virtual machines with critical health", nil, nil, ) c.healthOk = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "health_ok"), - "This counter represents the number of virtual machines with ok health", + "Represents the number of virtual machines with ok health", nil, nil, ) diff --git a/internal/collector/hyperv/hyperv_virtual_network_adapter.go b/internal/collector/hyperv/hyperv_virtual_network_adapter.go index ca67ae64f..d20964598 100644 --- a/internal/collector/hyperv/hyperv_virtual_network_adapter.go +++ b/internal/collector/hyperv/hyperv_virtual_network_adapter.go @@ -47,37 +47,37 @@ func (c *Collector) buildVirtualNetworkAdapter() error { c.virtualNetworkAdapterBytesReceived = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_received_bytes_total"), - "This counter represents the total number of bytes received per second by the network adapter", + "Represents the total number of bytes received per second by the network adapter", []string{"adapter"}, nil, ) c.virtualNetworkAdapterBytesSent = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_sent_bytes_total"), - "This counter represents the total number of bytes sent per second by the network adapter", + "Represents the total number of bytes sent per second by the network adapter", []string{"adapter"}, nil, ) c.virtualNetworkAdapterDroppedPacketsIncoming = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_incoming_dropped_packets_total"), - "This counter represents the total number of dropped packets per second in the incoming direction of the network adapter", + "Represents the total number of dropped packets per second in the incoming direction of the network adapter", []string{"adapter"}, nil, ) c.virtualNetworkAdapterDroppedPacketsOutgoing = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_outgoing_dropped_packets_total"), - "This counter represents the total number of dropped packets per second in the outgoing direction of the network adapter", + "Represents the total number of dropped packets per second in the outgoing direction of the network adapter", []string{"adapter"}, nil, ) c.virtualNetworkAdapterPacketsReceived = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_received_packets_total"), - "This counter represents the total number of packets received per second by the network adapter", + "Represents the total number of packets received per second by the network adapter", []string{"adapter"}, nil, ) c.virtualNetworkAdapterPacketsSent = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_sent_packets_total"), - "This counter represents the total number of packets sent per second by the network adapter", + "Represents the total number of packets sent per second by the network adapter", []string{"adapter"}, nil, ) diff --git a/internal/collector/hyperv/hyperv_virtual_storage_device.go b/internal/collector/hyperv/hyperv_virtual_storage_device.go index 359a19d69..f52039e1c 100644 --- a/internal/collector/hyperv/hyperv_virtual_storage_device.go +++ b/internal/collector/hyperv/hyperv_virtual_storage_device.go @@ -64,73 +64,73 @@ func (c *Collector) buildVirtualStorageDevice() error { c.virtualStorageDeviceErrorCount = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_error_count_total"), - "This counter represents the total number of errors that have occurred on this virtual device.", + "Represents the total number of errors that have occurred on this virtual device.", []string{"device"}, nil, ) c.virtualStorageDeviceQueueLength = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_queue_length"), - "This counter represents the average queue length on this virtual device.", + "Represents the average queue length on this virtual device.", []string{"device"}, nil, ) c.virtualStorageDeviceReadBytes = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_bytes_read"), - "This counter represents the total number of bytes that have been read on this virtual device.", + "Represents the total number of bytes that have been read on this virtual device.", []string{"device"}, nil, ) c.virtualStorageDeviceReadOperations = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_operations_read_total"), - "This counter represents the total number of read operations that have occurred on this virtual device.", + "Represents the total number of read operations that have occurred on this virtual device.", []string{"device"}, nil, ) c.virtualStorageDeviceWriteBytes = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_bytes_written"), - "This counter represents the total number of bytes that have been written on this virtual device.", + "Represents the total number of bytes that have been written on this virtual device.", []string{"device"}, nil, ) c.virtualStorageDeviceWriteOperations = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_operations_written_total"), - "This counter represents the total number of write operations that have occurred on this virtual device.", + "Represents the total number of write operations that have occurred on this virtual device.", []string{"device"}, nil, ) c.virtualStorageDeviceLatency = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_latency_seconds"), - "This counter represents the average IO transfer latency for this virtual device.", + "Represents the average IO transfer latency for this virtual device.", []string{"device"}, nil, ) c.virtualStorageDeviceThroughput = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_throughput"), - "This counter represents the average number of 8KB IO transfers completed by this virtual device.", + "Represents the average number of 8KB IO transfers completed by this virtual device.", []string{"device"}, nil, ) c.virtualStorageDeviceNormalizedThroughput = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_normalized_throughput"), - "This counter represents the average number of IO transfers completed by this virtual device.", + "Represents the average number of IO transfers completed by this virtual device.", []string{"device"}, nil, ) c.virtualStorageDeviceLowerQueueLength = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_lower_queue_length"), - "This counter represents the average queue length on the underlying storage subsystem for this device.", + "Represents the average queue length on the underlying storage subsystem for this device.", []string{"device"}, nil, ) c.virtualStorageDeviceLowerLatency = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_lower_latency_seconds"), - "This counter represents the average IO transfer latency on the underlying storage subsystem for this virtual device.", + "Represents the average IO transfer latency on the underlying storage subsystem for this virtual device.", []string{"device"}, nil, ) c.virtualStorageDeviceIOQuotaReplenishmentRate = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "io_quota_replenishment_rate"), - "This counter represents the IO quota replenishment rate for this virtual device.", + "Represents the IO quota replenishment rate for this virtual device.", []string{"device"}, nil, ) diff --git a/internal/collector/hyperv/hyperv_virtual_switch.go b/internal/collector/hyperv/hyperv_virtual_switch.go index 200077c18..525c28801 100644 --- a/internal/collector/hyperv/hyperv_virtual_switch.go +++ b/internal/collector/hyperv/hyperv_virtual_switch.go @@ -91,127 +91,127 @@ func (c *Collector) buildVirtualSwitch() error { c.virtualSwitchBroadcastPacketsReceived = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_broadcast_packets_received_total"), - "This represents the total number of broadcast packets received per second by the virtual switch", + "Represents the total number of broadcast packets received per second by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchBroadcastPacketsSent = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_broadcast_packets_sent_total"), - "This represents the total number of broadcast packets sent per second by the virtual switch", + "Represents the total number of broadcast packets sent per second by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchBytes = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_total"), - "This represents the total number of bytes per second traversing the virtual switch", + "Represents the total number of bytes per second traversing the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchBytesReceived = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_received_total"), - "This represents the total number of bytes received per second by the virtual switch", + "Represents the total number of bytes received per second by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchBytesSent = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_sent_total"), - "This represents the total number of bytes sent per second by the virtual switch", + "Represents the total number of bytes sent per second by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchDirectedPacketsReceived = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_directed_packets_received_total"), - "This represents the total number of directed packets received per second by the virtual switch", + "Represents the total number of directed packets received per second by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchDirectedPacketsSent = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_directed_packets_send_total"), - "This represents the total number of directed packets sent per second by the virtual switch", + "Represents the total number of directed packets sent per second by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchDroppedPacketsIncoming = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_dropped_packets_incoming_total"), - "This represents the total number of packet dropped per second by the virtual switch in the incoming direction", + "Represents the total number of packet dropped per second by the virtual switch in the incoming direction", []string{"vswitch"}, nil, ) c.virtualSwitchDroppedPacketsOutgoing = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_dropped_packets_outcoming_total"), - "This represents the total number of packet dropped per second by the virtual switch in the outgoing direction", + "Represents the total number of packet dropped per second by the virtual switch in the outgoing direction", []string{"vswitch"}, nil, ) c.virtualSwitchExtensionsDroppedPacketsIncoming = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_extensions_dropped_packets_incoming_total"), - "This represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction", + "Represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction", []string{"vswitch"}, nil, ) c.virtualSwitchExtensionsDroppedPacketsOutgoing = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_extensions_dropped_packets_outcoming_total"), - "This represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction", + "Represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction", []string{"vswitch"}, nil, ) c.virtualSwitchLearnedMacAddresses = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_learned_mac_addresses_total"), - "This counter represents the total number of learned MAC addresses of the virtual switch", + "Represents the total number of learned MAC addresses of the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchMulticastPacketsReceived = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_multicast_packets_received_total"), - "This represents the total number of multicast packets received per second by the virtual switch", + "Represents the total number of multicast packets received per second by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchMulticastPacketsSent = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_multicast_packets_sent_total"), - "This represents the total number of multicast packets sent per second by the virtual switch", + "Represents the total number of multicast packets sent per second by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchNumberOfSendChannelMoves = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_number_of_send_channel_moves_total"), - "This represents the total number of send channel moves per second on this virtual switch", + "Represents the total number of send channel moves per second on this virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchNumberOfVMQMoves = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_number_of_vmq_moves_total"), - "This represents the total number of VMQ moves per second on this virtual switch", + "Represents the total number of VMQ moves per second on this virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchPacketsFlooded = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_flooded_total"), - "This counter represents the total number of packets flooded by the virtual switch", + "Represents the total number of packets flooded by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchPackets = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_total"), - "This represents the total number of packets per second traversing the virtual switch", + "Represents the total number of packets per second traversing the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchPacketsReceived = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_received_total"), - "This represents the total number of packets received per second by the virtual switch", + "Represents the total number of packets received per second by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchPacketsSent = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_sent_total"), - "This represents the total number of packets send per second by the virtual switch", + "Represents the total number of packets send per second by the virtual switch", []string{"vswitch"}, nil, ) c.virtualSwitchPurgedMacAddresses = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "vswitch_purged_mac_addresses_total"), - "This counter represents the total number of purged MAC addresses of the virtual switch", + "Represents the total number of purged MAC addresses of the virtual switch", []string{"vswitch"}, nil, ) From b4c56864e0f3c7e66d567a2a4417a03d9e4f921f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Tue, 5 Nov 2024 00:58:52 +0100 Subject: [PATCH 11/12] Refactor HyperV collector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- internal/collector/hyperv/hyperv.go | 1 - internal/collector/hyperv/hyperv_dynamic_memory_balancer.go | 1 - internal/collector/hyperv/hyperv_dynamic_memory_vm.go | 1 - internal/collector/hyperv/hyperv_hypervisor_logical_processor.go | 1 - internal/collector/hyperv/hyperv_hypervisor_root_partition.go | 1 - .../collector/hyperv/hyperv_hypervisor_root_virtual_processor.go | 1 - internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go | 1 - internal/collector/hyperv/hyperv_legacy_network_adapter.go | 1 - .../collector/hyperv/hyperv_virtual_machine_health_summary.go | 1 - .../collector/hyperv/hyperv_virtual_machine_vid_partition.go | 1 - internal/collector/hyperv/hyperv_virtual_network_adapter.go | 1 - internal/collector/hyperv/hyperv_virtual_switch.go | 1 - 12 files changed, 12 deletions(-) diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index 8afdcf785..66e1ee65b 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -209,7 +209,6 @@ type Collector struct { // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidData // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Unknown // TODO: \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Unknown - } func New(config *Config) *Collector { diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go index cefab9bd0..03d1b1229 100644 --- a/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go +++ b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go @@ -37,7 +37,6 @@ func (c *Collector) buildDynamicMemoryBalancer() error { vmDynamicMemoryBalancerAveragePressure, vmDynamicMemoryBalancerSystemCurrentPressure, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go index 28e8e3d1e..c244c7989 100644 --- a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go +++ b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go @@ -53,7 +53,6 @@ func (c *Collector) buildDynamicMemoryVM() error { vmMemoryRemovedMemory, vmMemoryGuestAvailableMemory, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V Dynamic Memory VM collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go index bfbab4906..981f7b380 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go +++ b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go @@ -40,7 +40,6 @@ func (c *Collector) buildHypervisorLogicalProcessor() error { hypervisorLogicalProcessorIdleRunTimePercent, hypervisorLogicalProcessorContextSwitches, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V Hypervisor Logical Processor collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_hypervisor_root_partition.go b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go index 238116970..1609d5f1b 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_root_partition.go +++ b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go @@ -85,7 +85,6 @@ func (c *Collector) buildHypervisorRootPartition() error { hypervisorRootPartitionVirtualTLBFlushEntries, hypervisorRootPartitionVirtualTLBPages, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V Hypervisor Root Partition collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go b/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go index 1e2b4dff6..46590b578 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go +++ b/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go @@ -44,7 +44,6 @@ func (c *Collector) buildHypervisorRootVirtualProcessor() error { hypervisorRootVirtualProcessorRemoteRunTimePercent, hypervisorRootVirtualProcessorCPUWaitTimePerDispatch, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V Hypervisor Root Virtual Processor collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go b/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go index 565168ecc..940e6a505 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go +++ b/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go @@ -43,7 +43,6 @@ func (c *Collector) buildHypervisorVirtualProcessor() error { hypervisorVirtualProcessorRemoteRunTimePercent, hypervisorVirtualProcessorCPUWaitTimePerDispatch, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V Hypervisor Virtual Processor collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_legacy_network_adapter.go b/internal/collector/hyperv/hyperv_legacy_network_adapter.go index 757193330..aa2bc451e 100644 --- a/internal/collector/hyperv/hyperv_legacy_network_adapter.go +++ b/internal/collector/hyperv/hyperv_legacy_network_adapter.go @@ -40,7 +40,6 @@ func (c *Collector) buildLegacyNetworkAdapter() error { legacyNetworkAdapterFramesReceived, legacyNetworkAdapterFramesSent, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V Legacy Network Adapter collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go index 1d95ff533..40c5cb8c3 100644 --- a/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go +++ b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go @@ -30,7 +30,6 @@ func (c *Collector) buildVirtualMachineHealthSummary() error { healthCritical, healthOk, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go index 22c1c9ab4..f61462a79 100644 --- a/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go +++ b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go @@ -30,7 +30,6 @@ func (c *Collector) buildVirtualMachineVidPartition() error { preferredNUMANodeIndex, remotePhysicalPages, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V VM Vid Partition collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_network_adapter.go b/internal/collector/hyperv/hyperv_virtual_network_adapter.go index d20964598..6ad68be2d 100644 --- a/internal/collector/hyperv/hyperv_virtual_network_adapter.go +++ b/internal/collector/hyperv/hyperv_virtual_network_adapter.go @@ -40,7 +40,6 @@ func (c *Collector) buildVirtualNetworkAdapter() error { virtualNetworkAdapterPacketsReceived, virtualNetworkAdapterPacketsSent, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_switch.go b/internal/collector/hyperv/hyperv_virtual_switch.go index 525c28801..4b5cae529 100644 --- a/internal/collector/hyperv/hyperv_virtual_switch.go +++ b/internal/collector/hyperv/hyperv_virtual_switch.go @@ -84,7 +84,6 @@ func (c *Collector) buildVirtualSwitch() error { virtualSwitchPacketsSent, virtualSwitchPurgedMacAddresses, }) - if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Switch collector: %w", err) } From 844434377f2bf756e12a17d4c4bf0536dfff27e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Tue, 5 Nov 2024 01:00:09 +0100 Subject: [PATCH 12/12] Refactor HyperV collector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- internal/collector/hyperv/hyperv.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index 66e1ee65b..431ce4016 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -421,6 +421,7 @@ func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- pr for _, fn := range c.collectorFns { wg.Add(1) + go func(fn func(ch chan<- prometheus.Metric) error) { defer wg.Done()