mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-10-17 01:59:04 +02:00
hyperv: fix misnamed root partition metrics, counter types and units (#2720)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
+11
@@ -213,6 +213,17 @@ Renamed:
|
||||
| 0.31 | 0.32 | Note |
|
||||
|------------------------------------------------------|----------------------------------------------------------------|------------------------------------|
|
||||
| `windows_hyperv_virtual_storage_device_throughput` | `windows_hyperv_virtual_storage_device_throughput_total` | Now a counter, use `rate()` |
|
||||
| `windows_hyperv_virtual_storage_device_normalized_throughput` | `windows_hyperv_virtual_storage_device_normalized_throughput_total` | Now a counter, use `rate()` |
|
||||
| `windows_hyperv_io_quota_replenishment_rate` | `windows_hyperv_virtual_storage_device_io_quota_replenishment_total` | Now a counter, use `rate()` |
|
||||
| `windows_hyperv_root_partition_preferred_numa_node_index` | `windows_hyperv_root_partition_gpa_pages` | Same value; the old name was wrong |
|
||||
| `windows_hyperv_root_partition_physical_pages_allocated` | `windows_hyperv_root_partition_skipped_timer_ticks_total` | Same value; the old name was wrong, now a counter |
|
||||
| `windows_hyperv_root_partition_device_interrupt_throttle_events` | `windows_hyperv_root_partition_device_interrupt_throttle_events_total` | Now a counter |
|
||||
| `windows_hyperv_root_partition_io_tlb_flush_cost` | `windows_hyperv_root_partition_io_tlb_flush_seconds_total` | Same value, cumulative seconds, now a counter. Divide its rate by `rate(windows_hyperv_root_partition_io_tlb_flushes_total)` for the average time per flush |
|
||||
| `windows_hyperv_root_partition_io_tlb_flush` | `windows_hyperv_root_partition_io_tlb_flushes_total` | Same value |
|
||||
| `windows_hyperv_root_partition_gpa_space_modifications` | `windows_hyperv_root_partition_gpa_space_modifications_total` | Same value |
|
||||
| `windows_hyperv_root_partition_virtual_tlb_flush_entries` | `windows_hyperv_root_partition_virtual_tlb_flush_entries_total` | Same value |
|
||||
| `windows_hyperv_hypervisor_virtual_processor_cpu_wait_time_per_dispatch_total` | `windows_hyperv_hypervisor_virtual_processor_cpu_wait_seconds_total` | Same value, cumulative seconds. Divide its rate by `rate(windows_hyperv_hypervisor_virtual_processor_dispatches_total)` for the average wait per dispatch |
|
||||
| `windows_hyperv_hypervisor_root_virtual_cpu_wait_time_per_dispatch_total` | `windows_hyperv_hypervisor_root_virtual_processor_cpu_wait_seconds_total` | Same value, cumulative seconds. Divide its rate by `rate(windows_hyperv_hypervisor_root_virtual_processor_dispatches_total)` for the average wait per dispatch |
|
||||
| `windows_filetime_mtime_timestamp_seconds` | `windows_file_mtime_timestamp_seconds` | See [filetime](#filetime-collector-removed) |
|
||||
| `windows_memory_commit_limit` | `windows_memory_commit_limit_bytes` | Unit suffix added, same value |
|
||||
| `windows_memory_pool_paged_allocs_total` | `windows_memory_pool_paged_allocs` | Now a gauge, query it without `rate()` |
|
||||
|
||||
+24
-22
@@ -157,20 +157,20 @@ Multiply by the number of threads per core to get the ratio per **physical** cor
|
||||
| `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_device_interrupt_throttle_events_total` | The number of times an interrupt from a device assigned to the partition was temporarily throttled because the device was generating too many interrupts | counter | None |
|
||||
| `windows_hyperv_root_partition_gpa_pages` | 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_total` | The number of modifications to the GPA space of the partition | counter | None |
|
||||
| `windows_hyperv_root_partition_io_tlb_flush_seconds_total` | The time spent processing I/O TLB flushes. Divide its rate by the rate of `windows_hyperv_root_partition_io_tlb_flushes_total` for the average time per flush | counter | None |
|
||||
| `windows_hyperv_root_partition_io_tlb_flushes_total` | The number 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_skipped_timer_ticks_total` | The number of timer interrupts skipped for the partition | counter | 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_entries` | The rate of flushes of the entire virtual TLB | counter | None |
|
||||
| `windows_hyperv_root_partition_virtual_tlb_flush_entries_total` | The number 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 |
|
||||
|
||||
|
||||
@@ -178,9 +178,10 @@ Multiply by the number of threads per core to get the ratio per **physical** cor
|
||||
|
||||
| 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) | counter | `core`,`state` |
|
||||
| `windows_hyperv_hypervisor_root_virtual_processor_total_run_time_total` | Time that processor spent | counter | `core` |
|
||||
| `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` |
|
||||
| `windows_hyperv_hypervisor_root_virtual_processor_time_total` | Time in seconds that processor spent in different modes (`state`: `guest_run`, `hypervisor`, `remote`) | counter | `core`,`state` |
|
||||
| `windows_hyperv_hypervisor_root_virtual_processor_total_run_time_total` | Time in seconds that processor spent running | counter | `core` |
|
||||
| `windows_hyperv_hypervisor_root_virtual_processor_cpu_wait_seconds_total` | The time spent waiting for a virtual processor to be dispatched onto a logical processor. Divide its rate by the rate of `windows_hyperv_hypervisor_root_virtual_processor_dispatches_total` for the average wait per dispatch | counter | `core` |
|
||||
| `windows_hyperv_hypervisor_root_virtual_processor_dispatches_total` | The number of times the virtual processor was dispatched onto a logical processor | counter | `core` |
|
||||
|
||||
|
||||
### Hyper-V Legacy Network Adapter
|
||||
@@ -271,11 +272,12 @@ Example alert:
|
||||
|
||||
| Name | Description | Type | Labels |
|
||||
|--------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|---------|-----------------------|
|
||||
| `windows_hyperv_hypervisor_virtual_processor_mode_time_total` | Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote) | counter | `vm`, `core`, `state` |
|
||||
| `windows_hyperv_hypervisor_virtual_processor_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` |
|
||||
| `windows_hyperv_hypervisor_virtual_processor_time_total` | **Deprecated:** use `windows_hyperv_hypervisor_virtual_processor_mode_time_total`. Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote) | counter | `vm`, `core`, `state` |
|
||||
| `windows_hyperv_hypervisor_virtual_processor_total_run_time_total` | **Deprecated:** use `windows_hyperv_hypervisor_virtual_processor_run_time_total`. Time that processor spent | counter | `vm`, `core` |
|
||||
| `windows_hyperv_hypervisor_virtual_processor_mode_time_total` | Time in seconds that processor spent in different modes (`state`: `hypervisor`, `guest`, `remote`) | counter | `vm`, `core`, `state` |
|
||||
| `windows_hyperv_hypervisor_virtual_processor_run_time_total` | Time in seconds that processor spent running | counter | `vm`, `core` |
|
||||
| `windows_hyperv_hypervisor_virtual_processor_cpu_wait_seconds_total` | The time spent waiting for a virtual processor to be dispatched onto a logical processor. Divide its rate by the rate of `windows_hyperv_hypervisor_virtual_processor_dispatches_total` for the average wait per dispatch | counter | `vm`, `core` |
|
||||
| `windows_hyperv_hypervisor_virtual_processor_dispatches_total` | The number of times the virtual processor was dispatched onto a logical processor | counter | `vm`, `core` |
|
||||
| `windows_hyperv_hypervisor_virtual_processor_time_total` | **Deprecated:** use `windows_hyperv_hypervisor_virtual_processor_mode_time_total`. Time in seconds that processor spent in different modes (`state`: `hypervisor`, `guest`, `remote`) | counter | `vm`, `core`, `state` |
|
||||
| `windows_hyperv_hypervisor_virtual_processor_total_run_time_total` | **Deprecated:** use `windows_hyperv_hypervisor_virtual_processor_run_time_total`. Time in seconds that processor spent running | counter | `vm`, `core` |
|
||||
|
||||
### Hyper-V Virtual Network Adapter
|
||||
|
||||
@@ -355,12 +357,12 @@ Example alert:
|
||||
| `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_io_latency_seconds_total` | Represents the total IO transfer latency for this virtual device. | counter | `device` |
|
||||
| `windows_hyperv_virtual_storage_device_latency_seconds` | **Deprecated:** use `windows_hyperv_virtual_storage_device_io_latency_seconds_total`. Cumulative IO transfer latency in 100ns ticks, see below. | gauge | `device` |
|
||||
| `windows_hyperv_virtual_storage_device_throughput_total` | Represents the total number of 8KB IO transfers completed by this virtual device. | counter | `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_throughput_total` | Represents the total number of IO transfers completed by this virtual device. | counter | `device` |
|
||||
| `windows_hyperv_virtual_storage_device_normalized_throughput_total` | Represents the total number of IO transfers completed by this virtual device, normalized to 8KB transfers. | counter | `device` |
|
||||
| `windows_hyperv_virtual_storage_device_lower_io_latency_seconds_total` | Represents the total IO transfer latency on the underlying storage subsystem for this virtual device. | counter | `device` |
|
||||
| `windows_hyperv_virtual_storage_device_lower_queue_length` | **Deprecated:** use `rate(windows_hyperv_virtual_storage_device_lower_io_latency_seconds_total)`. Cumulative queue length in 100ns ticks, see below. | gauge | `device` |
|
||||
| `windows_hyperv_virtual_storage_device_lower_latency_seconds` | **Deprecated:** use `windows_hyperv_virtual_storage_device_lower_io_latency_seconds_total`. Cumulative IO transfer latency in 100ns ticks, see below. | gauge | `device` |
|
||||
| `windows_hyperv_io_quota_replenishment_rate` | Represents the IO quota replenishment rate for this virtual device. | gauge | `device` |
|
||||
| `windows_hyperv_virtual_storage_device_io_quota_replenishment_total` | Represents the IO quota replenishment counter for this virtual device. Use `rate()` for the replenishment rate. | counter | `device` |
|
||||
|
||||
#### Deprecated latency and queue length metrics
|
||||
|
||||
@@ -493,19 +495,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_hypervisor_virtual_processor_mode_time_total{state="hypervisor",instance="localhost"}[1m]))) / ignoring(state,vm) group_left max (windows_cpu_logical_processor{instance="localhost"}) / 100000
|
||||
sum by (vm) (rate(windows_hyperv_hypervisor_virtual_processor_run_time_total{instance="localhost"}[1m])) / ignoring(vm) group_left max (windows_cpu_logical_processor{instance="localhost"}) * 100
|
||||
```
|
||||
Percent of physical CPU resources used by all VMs (on all monitored hosts)
|
||||
```
|
||||
(sum by (instance)(rate(windows_hyperv_hypervisor_virtual_processor_run_time_total{}[1m]))) / max by (instance)(windows_cpu_logical_processor{}) / 100000
|
||||
(sum by (instance)(rate(windows_hyperv_hypervisor_virtual_processor_run_time_total{}[1m]))) / max by (instance)(windows_cpu_logical_processor{}) * 100
|
||||
```
|
||||
Percent of physical CPU resources by the hosts themselves (on all monitored hosts)
|
||||
```
|
||||
(sum by (instance)(rate(windows_hyperv_hypervisor_root_virtual_processor_total_run_time_total{}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) / 100000
|
||||
(sum by (instance)(rate(windows_hyperv_hypervisor_root_virtual_processor_total_run_time_total{}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) * 100
|
||||
```
|
||||
Percent of physical CPU resources by the hypervisor (on all monitored hosts)
|
||||
```
|
||||
(sum by (instance)(rate(windows_hyperv_hypervisor_logical_processor_time_total{}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) / 100000
|
||||
(sum by (instance)(rate(windows_hyperv_hypervisor_logical_processor_time_total{state="hypervisor"}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) * 100
|
||||
```
|
||||
|
||||
## Alerting examples
|
||||
|
||||
@@ -19,11 +19,17 @@ memory) on a host with 12 logical processors.
|
||||
`% Total Run Time` is about `% Guest Run Time` + `% Hypervisor Run Time`.
|
||||
The help text of `CPU Wait Time Per Dispatch` and `I/O TLB Flush Cost` says
|
||||
"average time (in nanoseconds)", but the raw value is cumulative 100 ns
|
||||
ticks.
|
||||
ticks. `internal/pdh` already scales `PERF_PRECISION_100NS_TIMER` to
|
||||
seconds, so do not scale again. Publish both as `_seconds_total` counters
|
||||
next to their operation count (`Logical Processor Dispatches/sec`,
|
||||
`I/O TLB Flushes/sec`), so the average is a ratio of the two rates.
|
||||
- The virtual processor `state` label is `hypervisor`, `guest`, `remote` for
|
||||
VMs and `guest_run`, `hypervisor`, `remote` for root VPs. There is no idle
|
||||
state.
|
||||
- `Hyper-V Hypervisor Root Partition` is read for the instance `Root` only.
|
||||
All its non-`/sec` counters are `PERF_COUNTER_LARGE_RAWCOUNT`. Page counts
|
||||
and sizes are gauges; by the help text `Skipped Timer Ticks` and
|
||||
`Device Interrupt Throttle Events` count events.
|
||||
`Device Interrupt Throttle Events` count events, so they are counters.
|
||||
- Dynamic Memory: memory counters are in MB (`Physical Memory` and
|
||||
`Guest Visible Physical Memory` are 2048 for the 2 GiB VM). `Added Memory`
|
||||
and `Removed Memory` are cumulative MB, `Memory Add/Remove Operations` are
|
||||
@@ -52,7 +58,9 @@ memory) on a host with 12 logical processors.
|
||||
`Read Count` + `Write Count` (6 + 4).
|
||||
- `Throughput` (`PERF_COUNTER_COUNTER`) counts IO transfers.
|
||||
`Normalized Throughput` (`PERF_COUNTER_BULK_COUNT`) counts 8 KB IO
|
||||
transfers by its help text. Both raw values are cumulative.
|
||||
transfers by its help text. Both raw values are cumulative, as is
|
||||
`Io Quota Replenishment Rate` (`PERF_COUNTER_BULK_COUNT`); publish them
|
||||
as counters.
|
||||
- `Read Count`, `Write Count` and `Error Count` are
|
||||
`PERF_COUNTER_RAWCOUNT` but cumulative ("total number of ...").
|
||||
- `Hyper-V Virtual Switch` and `Hyper-V Virtual Network Adapter`: all
|
||||
@@ -81,6 +89,10 @@ memory) on a host with 12 logical processors.
|
||||
the one VM.
|
||||
- The `wmi_health`, `virtual_hard_disk` and host VM processor metrics do not
|
||||
come from PDH, so the table below does not cover them.
|
||||
- To test emitted metrics without Hyper-V, build the descriptors with the
|
||||
`build...Descriptors` helpers, fill the `perfDataObject...` slice (or a
|
||||
`pdhtypes.Collector` fixture) and gather through a registry, as in
|
||||
`hyperv_metric_types_internal_test.go`.
|
||||
|
||||
## Counter reference
|
||||
|
||||
@@ -252,10 +264,11 @@ Counters the collector reads:
|
||||
| `% Remote Run Time` | `PERF_PRECISION_100NS_TIMER` | 0 | |
|
||||
| `% Total Run Time` | `PERF_PRECISION_100NS_TIMER` | 10411471300 | |
|
||||
| `CPU Wait Time Per Dispatch` | `PERF_PRECISION_100NS_TIMER` | 290865977 | |
|
||||
| `Logical Processor Dispatches/sec` | `PERF_COUNTER_BULK_COUNT` | 3171435 | |
|
||||
|
||||
Not read by the collector:
|
||||
|
||||
- `PERF_COUNTER_BULK_COUNT`: `Address Domain Flushes/sec`, `Address Space Evictions/sec`, `Address Space Flushes/sec`, `Address Space Switches/sec`, `APIC EOI Accesses/sec`, `APIC IPIs Sent/sec`, `APIC MMIO Accesses/sec`, `APIC Self IPIs Sent/sec`, `APIC TPR Accesses/sec`, `Bus Lock Acquisitions/sec`, `Control Register Accesses Forwarded/sec`, `Control Register Accesses/sec`, `CPPC Request Context Switches/sec`, `CPU Group Hypercalls/sec`, `CPUID Instructions Forwarded/sec`, `CPUID Instructions/sec`, `Debug Register Accesses Forwarded/sec`, `Debug Register Accesses/sec`, `Deposit Hypercalls/sec`, `Device Domain Hypercalls/sec`, `Emulated Instructions Forwarded/sec`, `Emulated Instructions/sec`, `Event Log Hypercalls/sec`, `Extended Hypercall Intercept Messages/sec`, `Extended Hypercalls/sec`, `External Interrupts Forwarded/sec`, `External Interrupts/sec`, `Flush Physical Address List Hypercalls/sec`, `Flush Physical Address Space Hypercalls/sec`, `GIF Instruction Emulation Intercepts/sec`, `Global GVA Range Flushes/sec`, `Global I/O TLB Flushes/sec`, `GPA Space Hypercalls/sec`, `Guest Page Table Maps/sec`, `Hardware Interrupts/sec`, `HLT Instructions Forwarded/sec`, `HLT Instructions/sec`, `Hypercalls Forwarded/sec`, `Hypercalls/sec`, `InvEpt All Context Emulation Intercepts/sec`, `InvEpt Single Context Emulation Intercepts/sec`, `InvVpid All Context Emulation Intercepts/sec`, `InvVpid Single Address Emulation Intercepts/sec`, `InvVpid Single Context Emulation Intercepts/sec`, `IO Instructions Forwarded/sec`, `IO Instructions/sec`, `IO Intercept Messages/sec`, `IOMMU Hypercalls/sec`, `Large Page TLB Fills/sec`, `Local Flushed GVA Ranges/sec`, `Local I/O TLB Flushes/sec`, `Logical Processor Dispatches/sec`, `Logical Processor Hypercalls/sec`, `Logical Processor Migrations/sec`, `Long Spin Wait Hypercalls/sec`, `MBEC Nested Page Table Switches/sec`, `Memory Intercept Messages/sec`, `MSR Accesses Forwarded/sec`, `MSR Accesses/sec`, `MWAIT Instructions Forwarded/sec`, `MWAIT Instructions/sec`, `Nested Page Fault Intercepts/sec`, `Nested SLAT Hard Page Faults/sec`, `Nested SLAT Soft Page Faults/sec`, `Nested TLB Page Table Evictions/sec`, `Nested TLB Page Table Reclamations/sec`, `Nested VM Entries/sec`, `Other Hypercalls/sec`, `Other Intercepts Forwarded/sec`, `Other Intercepts/sec`, `Other Messages/sec`, `Other Reflected Guest Exceptions/sec`, `Page Fault Intercepts Forwarded/sec`, `Page Fault Intercepts/sec`, `Page Invalidations Forwarded/sec`, `Page Invalidations/sec`, `Page Scans/sec`, `Page Table Allocations/sec`, `Page Table Evictions/sec`, `Page Table Reclamations/sec`, `Page Table Resets/sec`, `Page Table Validations/sec`, `Page Table Write Intercepts/sec`, `Pending Interrupts Forwarded/sec`, `Pending Interrupts/sec`, `Performance Monitoring Interrupts/sec`, `Performance Monitoring IPT MSR Accesses/sec`, `Performance Monitoring LBR MSR Accesses/sec`, `Performance Monitoring vPMU MSR Accesses/sec`, `Posted Interrupt Notifications/sec`, `Posted Interrupt Scans/sec`, `RDPMC Instructions/sec`, `Reflected Guest Page Faults/sec`, `Small Page TLB Fills/sec`, `SVM Hypercalls/sec`, `Synthetic Interrupt Hypercalls/sec`, `Synthetic Interrupts/sec`, `Total Intercepts/sec`, `Total Messages/sec`, `Total Virtualization Instructions Emulated/sec`, `Virtual Interrupt Hypercalls/sec`, `Virtual Interrupts/sec`, `Virtual MMU Hypercalls/sec`, `Virtual Processor Hypercalls/sec`, `VMCLEAR Emulation Intercepts/sec`, `VMLOAD Emulation Intercepts/sec`, `VMPTRLD Emulation Intercepts/sec`, `VMPTRST Emulation Intercepts/sec`, `VMREAD Emulation Intercepts/sec`, `VMSAVE Emulation Intercepts/sec`, `VMWRITE Emulation Intercepts/sec`, `VMXOFF Emulation Intercepts/sec`, `VMXON Emulation Intercepts/sec`, `VSM Hypercalls/sec`, `VTL1 Dispatches/sec`, `VTL2 Dispatches/sec`
|
||||
- `PERF_COUNTER_BULK_COUNT`: `Address Domain Flushes/sec`, `Address Space Evictions/sec`, `Address Space Flushes/sec`, `Address Space Switches/sec`, `APIC EOI Accesses/sec`, `APIC IPIs Sent/sec`, `APIC MMIO Accesses/sec`, `APIC Self IPIs Sent/sec`, `APIC TPR Accesses/sec`, `Bus Lock Acquisitions/sec`, `Control Register Accesses Forwarded/sec`, `Control Register Accesses/sec`, `CPPC Request Context Switches/sec`, `CPU Group Hypercalls/sec`, `CPUID Instructions Forwarded/sec`, `CPUID Instructions/sec`, `Debug Register Accesses Forwarded/sec`, `Debug Register Accesses/sec`, `Deposit Hypercalls/sec`, `Device Domain Hypercalls/sec`, `Emulated Instructions Forwarded/sec`, `Emulated Instructions/sec`, `Event Log Hypercalls/sec`, `Extended Hypercall Intercept Messages/sec`, `Extended Hypercalls/sec`, `External Interrupts Forwarded/sec`, `External Interrupts/sec`, `Flush Physical Address List Hypercalls/sec`, `Flush Physical Address Space Hypercalls/sec`, `GIF Instruction Emulation Intercepts/sec`, `Global GVA Range Flushes/sec`, `Global I/O TLB Flushes/sec`, `GPA Space Hypercalls/sec`, `Guest Page Table Maps/sec`, `Hardware Interrupts/sec`, `HLT Instructions Forwarded/sec`, `HLT Instructions/sec`, `Hypercalls Forwarded/sec`, `Hypercalls/sec`, `InvEpt All Context Emulation Intercepts/sec`, `InvEpt Single Context Emulation Intercepts/sec`, `InvVpid All Context Emulation Intercepts/sec`, `InvVpid Single Address Emulation Intercepts/sec`, `InvVpid Single Context Emulation Intercepts/sec`, `IO Instructions Forwarded/sec`, `IO Instructions/sec`, `IO Intercept Messages/sec`, `IOMMU Hypercalls/sec`, `Large Page TLB Fills/sec`, `Local Flushed GVA Ranges/sec`, `Local I/O TLB Flushes/sec`, `Logical Processor Hypercalls/sec`, `Logical Processor Migrations/sec`, `Long Spin Wait Hypercalls/sec`, `MBEC Nested Page Table Switches/sec`, `Memory Intercept Messages/sec`, `MSR Accesses Forwarded/sec`, `MSR Accesses/sec`, `MWAIT Instructions Forwarded/sec`, `MWAIT Instructions/sec`, `Nested Page Fault Intercepts/sec`, `Nested SLAT Hard Page Faults/sec`, `Nested SLAT Soft Page Faults/sec`, `Nested TLB Page Table Evictions/sec`, `Nested TLB Page Table Reclamations/sec`, `Nested VM Entries/sec`, `Other Hypercalls/sec`, `Other Intercepts Forwarded/sec`, `Other Intercepts/sec`, `Other Messages/sec`, `Other Reflected Guest Exceptions/sec`, `Page Fault Intercepts Forwarded/sec`, `Page Fault Intercepts/sec`, `Page Invalidations Forwarded/sec`, `Page Invalidations/sec`, `Page Scans/sec`, `Page Table Allocations/sec`, `Page Table Evictions/sec`, `Page Table Reclamations/sec`, `Page Table Resets/sec`, `Page Table Validations/sec`, `Page Table Write Intercepts/sec`, `Pending Interrupts Forwarded/sec`, `Pending Interrupts/sec`, `Performance Monitoring Interrupts/sec`, `Performance Monitoring IPT MSR Accesses/sec`, `Performance Monitoring LBR MSR Accesses/sec`, `Performance Monitoring vPMU MSR Accesses/sec`, `Posted Interrupt Notifications/sec`, `Posted Interrupt Scans/sec`, `RDPMC Instructions/sec`, `Reflected Guest Page Faults/sec`, `Small Page TLB Fills/sec`, `SVM Hypercalls/sec`, `Synthetic Interrupt Hypercalls/sec`, `Synthetic Interrupts/sec`, `Total Intercepts/sec`, `Total Messages/sec`, `Total Virtualization Instructions Emulated/sec`, `Virtual Interrupt Hypercalls/sec`, `Virtual Interrupts/sec`, `Virtual MMU Hypercalls/sec`, `Virtual Processor Hypercalls/sec`, `VMCLEAR Emulation Intercepts/sec`, `VMLOAD Emulation Intercepts/sec`, `VMPTRLD Emulation Intercepts/sec`, `VMPTRST Emulation Intercepts/sec`, `VMREAD Emulation Intercepts/sec`, `VMSAVE Emulation Intercepts/sec`, `VMWRITE Emulation Intercepts/sec`, `VMXOFF Emulation Intercepts/sec`, `VMXON Emulation Intercepts/sec`, `VSM Hypercalls/sec`, `VTL1 Dispatches/sec`, `VTL2 Dispatches/sec`
|
||||
- `PERF_COUNTER_LARGE_RAWCOUNT`: `Scheduling Priority`
|
||||
- `PERF_PRECISION_100NS_TIMER`: `% Guest-Relative Utilization`, `% Total Core Run Time`, `% VTL1 Run Time`, `% VTL2 Run Time`, `Control Register Accesses Cost`, `Control Register Accesses Forwarding Cost`, `CPU Contention Time Per Dispatch`, `CPU Wake Up Time Per Dispatch`, `CPUID Instructions Cost`, `CPUID Instructions Forwarding Cost`, `Debug Register Accesses Cost`, `Debug Register Accesses Forwarding Cost`, `Emulated Instructions Cost`, `Emulated Instructions Forwarding Cost`, `External Interrupts Cost`, `GIF Instruction Emulation Cost`, `Global I/O TLB Flush Cost`, `HLT Instructions Cost`, `HLT Instructions Forwarding Cost`, `Hypercalls Cost`, `Hypercalls Forwarding Cost`, `InvEpt All Context Instruction Emulation Cost`, `InvEpt Single Context Instruction Emulation Cost`, `InvVpid All Context Instruction Emulation Cost`, `InvVpid Single Address Instruction Emulation Cost`, `InvVpid Single Context Instruction Emulation Cost`, `IO Instructions Cost`, `IO Instructions Forwarding Cost`, `Local I/O TLB Flush Cost`, `MSR Accesses Cost`, `MSR Accesses Forwarding Cost`, `MWAIT Instructions Cost`, `MWAIT Instructions Forwarding Cost`, `Nested Page Fault Intercepts Cost`, `Nested SLAT Hard Page Faults Cost`, `Nested SLAT Soft Page Faults Cost`, `Nested VM Entries Cost`, `Other Intercepts Cost`, `Other Intercepts Forwarding Cost`, `Page Fault Intercepts Cost`, `Page Fault Intercepts Forwarding Cost`, `Page Invalidations Cost`, `Page Invalidations Forwarding Cost`, `Pending Interrupts Cost`, `Pending Interrupts Forwarding Cost`, `RDPMC Instructions Cost`, `Total Intercepts Cost`, `Total Virtualization Instructions Emulation Cost`, `VMCLEAR Instruction Emulation Cost`, `VMLOAD Instruction Emulation Cost`, `VMPTRLD Instruction Emulation Cost`, `VMPTRST Instruction Emulation Cost`, `VMREAD Instruction Emulation Cost`, `VMSAVE Instruction Emulation Cost`, `VMWRITE Instruction Emulation Cost`, `VMXOFF Instruction Emulation Cost`, `VMXON Instruction Emulation Cost`, `VTL1 Average Run Time`, `VTL2 Average Run Time`
|
||||
|
||||
@@ -272,10 +285,11 @@ Counters the collector reads:
|
||||
| `% Remote Run Time` | `PERF_PRECISION_100NS_TIMER` | 0 | |
|
||||
| `% Total Run Time` | `PERF_PRECISION_100NS_TIMER` | 3180787877 | |
|
||||
| `CPU Wait Time Per Dispatch` | `PERF_PRECISION_100NS_TIMER` | 1217187193 | |
|
||||
| `Logical Processor Dispatches/sec` | `PERF_COUNTER_BULK_COUNT` | 2007559 | |
|
||||
|
||||
Not read by the collector:
|
||||
|
||||
- `PERF_COUNTER_BULK_COUNT`: `Address Domain Flushes/sec`, `Address Space Evictions/sec`, `Address Space Flushes/sec`, `Address Space Switches/sec`, `APIC EOI Accesses/sec`, `APIC IPIs Sent/sec`, `APIC MMIO Accesses/sec`, `APIC Self IPIs Sent/sec`, `APIC TPR Accesses/sec`, `Bus Lock Acquisitions/sec`, `Control Register Accesses Forwarded/sec`, `Control Register Accesses/sec`, `CPPC Request Context Switches/sec`, `CPU Group Hypercalls/sec`, `CPUID Instructions Forwarded/sec`, `CPUID Instructions/sec`, `Debug Register Accesses Forwarded/sec`, `Debug Register Accesses/sec`, `Deposit Hypercalls/sec`, `Device Domain Hypercalls/sec`, `Emulated Instructions Forwarded/sec`, `Emulated Instructions/sec`, `Event Log Hypercalls/sec`, `Extended Hypercall Intercept Messages/sec`, `Extended Hypercalls/sec`, `External Interrupts Forwarded/sec`, `External Interrupts/sec`, `Flush Physical Address List Hypercalls/sec`, `Flush Physical Address Space Hypercalls/sec`, `GIF Instruction Emulation Intercepts/sec`, `Global GVA Range Flushes/sec`, `Global I/O TLB Flushes/sec`, `GPA Space Hypercalls/sec`, `Guest Page Table Maps/sec`, `Hardware Interrupts/sec`, `HLT Instructions Forwarded/sec`, `HLT Instructions/sec`, `Hypercalls Forwarded/sec`, `Hypercalls/sec`, `InvEpt All Context Emulation Intercepts/sec`, `InvEpt Single Context Emulation Intercepts/sec`, `InvVpid All Context Emulation Intercepts/sec`, `InvVpid Single Address Emulation Intercepts/sec`, `InvVpid Single Context Emulation Intercepts/sec`, `IO Instructions Forwarded/sec`, `IO Instructions/sec`, `IO Intercept Messages/sec`, `IOMMU Hypercalls/sec`, `Large Page TLB Fills/sec`, `Local Flushed GVA Ranges/sec`, `Local I/O TLB Flushes/sec`, `Logical Processor Dispatches/sec`, `Logical Processor Hypercalls/sec`, `Logical Processor Migrations/sec`, `Long Spin Wait Hypercalls/sec`, `MBEC Nested Page Table Switches/sec`, `Memory Intercept Messages/sec`, `MSR Accesses Forwarded/sec`, `MSR Accesses/sec`, `MWAIT Instructions Forwarded/sec`, `MWAIT Instructions/sec`, `Nested Page Fault Intercepts/sec`, `Nested SLAT Hard Page Faults/sec`, `Nested SLAT Soft Page Faults/sec`, `Nested TLB Page Table Evictions/sec`, `Nested TLB Page Table Reclamations/sec`, `Nested VM Entries/sec`, `Other Hypercalls/sec`, `Other Intercepts Forwarded/sec`, `Other Intercepts/sec`, `Other Messages/sec`, `Other Reflected Guest Exceptions/sec`, `Page Fault Intercepts Forwarded/sec`, `Page Fault Intercepts/sec`, `Page Invalidations Forwarded/sec`, `Page Invalidations/sec`, `Page Scans/sec`, `Page Table Allocations/sec`, `Page Table Evictions/sec`, `Page Table Reclamations/sec`, `Page Table Resets/sec`, `Page Table Validations/sec`, `Page Table Write Intercepts/sec`, `Pending Interrupts Forwarded/sec`, `Pending Interrupts/sec`, `Performance Monitoring Interrupts/sec`, `Performance Monitoring IPT MSR Accesses/sec`, `Performance Monitoring LBR MSR Accesses/sec`, `Performance Monitoring vPMU MSR Accesses/sec`, `Posted Interrupt Notifications/sec`, `Posted Interrupt Scans/sec`, `RDPMC Instructions/sec`, `Reflected Guest Page Faults/sec`, `Small Page TLB Fills/sec`, `SVM Hypercalls/sec`, `Synthetic Interrupt Hypercalls/sec`, `Synthetic Interrupts/sec`, `Total Intercepts/sec`, `Total Messages/sec`, `Total Virtualization Instructions Emulated/sec`, `Virtual Interrupt Hypercalls/sec`, `Virtual Interrupts/sec`, `Virtual MMU Hypercalls/sec`, `Virtual Processor Hypercalls/sec`, `VMCLEAR Emulation Intercepts/sec`, `VMLOAD Emulation Intercepts/sec`, `VMPTRLD Emulation Intercepts/sec`, `VMPTRST Emulation Intercepts/sec`, `VMREAD Emulation Intercepts/sec`, `VMSAVE Emulation Intercepts/sec`, `VMWRITE Emulation Intercepts/sec`, `VMXOFF Emulation Intercepts/sec`, `VMXON Emulation Intercepts/sec`, `VSM Hypercalls/sec`, `VTL1 Dispatches/sec`, `VTL2 Dispatches/sec`
|
||||
- `PERF_COUNTER_BULK_COUNT`: `Address Domain Flushes/sec`, `Address Space Evictions/sec`, `Address Space Flushes/sec`, `Address Space Switches/sec`, `APIC EOI Accesses/sec`, `APIC IPIs Sent/sec`, `APIC MMIO Accesses/sec`, `APIC Self IPIs Sent/sec`, `APIC TPR Accesses/sec`, `Bus Lock Acquisitions/sec`, `Control Register Accesses Forwarded/sec`, `Control Register Accesses/sec`, `CPPC Request Context Switches/sec`, `CPU Group Hypercalls/sec`, `CPUID Instructions Forwarded/sec`, `CPUID Instructions/sec`, `Debug Register Accesses Forwarded/sec`, `Debug Register Accesses/sec`, `Deposit Hypercalls/sec`, `Device Domain Hypercalls/sec`, `Emulated Instructions Forwarded/sec`, `Emulated Instructions/sec`, `Event Log Hypercalls/sec`, `Extended Hypercall Intercept Messages/sec`, `Extended Hypercalls/sec`, `External Interrupts Forwarded/sec`, `External Interrupts/sec`, `Flush Physical Address List Hypercalls/sec`, `Flush Physical Address Space Hypercalls/sec`, `GIF Instruction Emulation Intercepts/sec`, `Global GVA Range Flushes/sec`, `Global I/O TLB Flushes/sec`, `GPA Space Hypercalls/sec`, `Guest Page Table Maps/sec`, `Hardware Interrupts/sec`, `HLT Instructions Forwarded/sec`, `HLT Instructions/sec`, `Hypercalls Forwarded/sec`, `Hypercalls/sec`, `InvEpt All Context Emulation Intercepts/sec`, `InvEpt Single Context Emulation Intercepts/sec`, `InvVpid All Context Emulation Intercepts/sec`, `InvVpid Single Address Emulation Intercepts/sec`, `InvVpid Single Context Emulation Intercepts/sec`, `IO Instructions Forwarded/sec`, `IO Instructions/sec`, `IO Intercept Messages/sec`, `IOMMU Hypercalls/sec`, `Large Page TLB Fills/sec`, `Local Flushed GVA Ranges/sec`, `Local I/O TLB Flushes/sec`, `Logical Processor Hypercalls/sec`, `Logical Processor Migrations/sec`, `Long Spin Wait Hypercalls/sec`, `MBEC Nested Page Table Switches/sec`, `Memory Intercept Messages/sec`, `MSR Accesses Forwarded/sec`, `MSR Accesses/sec`, `MWAIT Instructions Forwarded/sec`, `MWAIT Instructions/sec`, `Nested Page Fault Intercepts/sec`, `Nested SLAT Hard Page Faults/sec`, `Nested SLAT Soft Page Faults/sec`, `Nested TLB Page Table Evictions/sec`, `Nested TLB Page Table Reclamations/sec`, `Nested VM Entries/sec`, `Other Hypercalls/sec`, `Other Intercepts Forwarded/sec`, `Other Intercepts/sec`, `Other Messages/sec`, `Other Reflected Guest Exceptions/sec`, `Page Fault Intercepts Forwarded/sec`, `Page Fault Intercepts/sec`, `Page Invalidations Forwarded/sec`, `Page Invalidations/sec`, `Page Scans/sec`, `Page Table Allocations/sec`, `Page Table Evictions/sec`, `Page Table Reclamations/sec`, `Page Table Resets/sec`, `Page Table Validations/sec`, `Page Table Write Intercepts/sec`, `Pending Interrupts Forwarded/sec`, `Pending Interrupts/sec`, `Performance Monitoring Interrupts/sec`, `Performance Monitoring IPT MSR Accesses/sec`, `Performance Monitoring LBR MSR Accesses/sec`, `Performance Monitoring vPMU MSR Accesses/sec`, `Posted Interrupt Notifications/sec`, `Posted Interrupt Scans/sec`, `RDPMC Instructions/sec`, `Reflected Guest Page Faults/sec`, `Small Page TLB Fills/sec`, `SVM Hypercalls/sec`, `Synthetic Interrupt Hypercalls/sec`, `Synthetic Interrupts/sec`, `Total Intercepts/sec`, `Total Messages/sec`, `Total Virtualization Instructions Emulated/sec`, `Virtual Interrupt Hypercalls/sec`, `Virtual Interrupts/sec`, `Virtual MMU Hypercalls/sec`, `Virtual Processor Hypercalls/sec`, `VMCLEAR Emulation Intercepts/sec`, `VMLOAD Emulation Intercepts/sec`, `VMPTRLD Emulation Intercepts/sec`, `VMPTRST Emulation Intercepts/sec`, `VMREAD Emulation Intercepts/sec`, `VMSAVE Emulation Intercepts/sec`, `VMWRITE Emulation Intercepts/sec`, `VMXOFF Emulation Intercepts/sec`, `VMXON Emulation Intercepts/sec`, `VSM Hypercalls/sec`, `VTL1 Dispatches/sec`, `VTL2 Dispatches/sec`
|
||||
- `PERF_COUNTER_LARGE_RAWCOUNT`: `Scheduling Priority`
|
||||
- `PERF_PRECISION_100NS_TIMER`: `% Guest-Relative Utilization`, `% Total Core Run Time`, `% VTL1 Run Time`, `% VTL2 Run Time`, `Control Register Accesses Cost`, `Control Register Accesses Forwarding Cost`, `CPU Contention Time Per Dispatch`, `CPU Wake Up Time Per Dispatch`, `CPUID Instructions Cost`, `CPUID Instructions Forwarding Cost`, `Debug Register Accesses Cost`, `Debug Register Accesses Forwarding Cost`, `Emulated Instructions Cost`, `Emulated Instructions Forwarding Cost`, `External Interrupts Cost`, `GIF Instruction Emulation Cost`, `Global I/O TLB Flush Cost`, `HLT Instructions Cost`, `HLT Instructions Forwarding Cost`, `Hypercalls Cost`, `Hypercalls Forwarding Cost`, `InvEpt All Context Instruction Emulation Cost`, `InvEpt Single Context Instruction Emulation Cost`, `InvVpid All Context Instruction Emulation Cost`, `InvVpid Single Address Instruction Emulation Cost`, `InvVpid Single Context Instruction Emulation Cost`, `IO Instructions Cost`, `IO Instructions Forwarding Cost`, `Local I/O TLB Flush Cost`, `MSR Accesses Cost`, `MSR Accesses Forwarding Cost`, `MWAIT Instructions Cost`, `MWAIT Instructions Forwarding Cost`, `Nested Page Fault Intercepts Cost`, `Nested SLAT Hard Page Faults Cost`, `Nested SLAT Soft Page Faults Cost`, `Nested VM Entries Cost`, `Other Intercepts Cost`, `Other Intercepts Forwarding Cost`, `Page Fault Intercepts Cost`, `Page Fault Intercepts Forwarding Cost`, `Page Invalidations Cost`, `Page Invalidations Forwarding Cost`, `Pending Interrupts Cost`, `Pending Interrupts Forwarding Cost`, `RDPMC Instructions Cost`, `Total Intercepts Cost`, `Total Virtualization Instructions Emulation Cost`, `VMCLEAR Instruction Emulation Cost`, `VMLOAD Instruction Emulation Cost`, `VMPTRLD Instruction Emulation Cost`, `VMPTRST Instruction Emulation Cost`, `VMREAD Instruction Emulation Cost`, `VMSAVE Instruction Emulation Cost`, `VMWRITE Instruction Emulation Cost`, `VMXOFF Instruction Emulation Cost`, `VMXON Instruction Emulation Cost`, `VTL1 Average Run Time`, `VTL2 Average Run Time`
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ func (c *Collector) buildDynamicMemoryBalancer() error {
|
||||
// https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012
|
||||
c.perfDataCollectorDynamicMemoryBalancer, err = pdh.NewCollector[perfDataCounterValuesDynamicMemoryBalancer](c.logger, pdh.CounterTypeRaw, "Hyper-V Dynamic Memory Balancer", pdh.InstancesAll)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err)
|
||||
return fmt.Errorf("failed to create Hyper-V Dynamic Memory Balancer collector: %w", err)
|
||||
}
|
||||
|
||||
c.vmDynamicMemoryBalancerAvailableMemory = prometheus.NewDesc(
|
||||
|
||||
@@ -65,18 +65,20 @@ type perfDataCounterValuesHypervisorRootPartition struct {
|
||||
HypervisorRootPartitionDeviceInterruptThrottleEvents float64 `perfdata:"Device Interrupt Throttle Events"`
|
||||
HypervisorRootPartitionGPAPages float64 `perfdata:"GPA Pages"`
|
||||
HypervisorRootPartitionGPASpaceModifications float64 `perfdata:"GPA Space Modifications/sec"`
|
||||
HypervisorRootPartitionIOTLBFlushCost float64 `perfdata:"I/O TLB Flush Cost"`
|
||||
HypervisorRootPartitionIOTLBFlushes float64 `perfdata:"I/O TLB Flushes/sec"`
|
||||
HypervisorRootPartitionRecommendedVirtualTLBSize float64 `perfdata:"Recommended Virtual TLB Size"`
|
||||
HypervisorRootPartitionSkippedTimerTicks float64 `perfdata:"Skipped Timer Ticks"`
|
||||
HypervisorRootPartition1GDevicePages float64 `perfdata:"1G device pages"`
|
||||
HypervisorRootPartition1GGPAPages float64 `perfdata:"1G GPA pages"`
|
||||
HypervisorRootPartition2MDevicePages float64 `perfdata:"2M device pages"`
|
||||
HypervisorRootPartition2MGPAPages float64 `perfdata:"2M GPA pages"`
|
||||
HypervisorRootPartition4KDevicePages float64 `perfdata:"4K device pages"`
|
||||
HypervisorRootPartition4KGPAPages float64 `perfdata:"4K GPA pages"`
|
||||
HypervisorRootPartitionVirtualTLBFlushEntries float64 `perfdata:"Virtual TLB Flush Entires/sec"`
|
||||
HypervisorRootPartitionVirtualTLBPages float64 `perfdata:"Virtual TLB Pages"`
|
||||
// PERF_PRECISION_100NS_TIMER: the raw value is the cumulative flush time, which pdh
|
||||
// scales to seconds. The Windows help text calls it an average in nanoseconds.
|
||||
HypervisorRootPartitionIOTLBFlushCost float64 `perfdata:"I/O TLB Flush Cost"`
|
||||
HypervisorRootPartitionIOTLBFlushes float64 `perfdata:"I/O TLB Flushes/sec"`
|
||||
HypervisorRootPartitionRecommendedVirtualTLBSize float64 `perfdata:"Recommended Virtual TLB Size"`
|
||||
HypervisorRootPartitionSkippedTimerTicks float64 `perfdata:"Skipped Timer Ticks"`
|
||||
HypervisorRootPartition1GDevicePages float64 `perfdata:"1G device pages"`
|
||||
HypervisorRootPartition1GGPAPages float64 `perfdata:"1G GPA pages"`
|
||||
HypervisorRootPartition2MDevicePages float64 `perfdata:"2M device pages"`
|
||||
HypervisorRootPartition2MGPAPages float64 `perfdata:"2M GPA pages"`
|
||||
HypervisorRootPartition4KDevicePages float64 `perfdata:"4K device pages"`
|
||||
HypervisorRootPartition4KGPAPages float64 `perfdata:"4K GPA pages"`
|
||||
HypervisorRootPartitionVirtualTLBFlushEntries float64 `perfdata:"Virtual TLB Flush Entires/sec"`
|
||||
HypervisorRootPartitionVirtualTLBPages float64 `perfdata:"Virtual TLB Pages"`
|
||||
}
|
||||
|
||||
func (c *Collector) buildHypervisorRootPartition() error {
|
||||
@@ -130,32 +132,32 @@ func (c *Collector) buildHypervisorRootPartitionDescriptors() {
|
||||
nil,
|
||||
)
|
||||
c.hypervisorRootPartitionDeviceInterruptThrottleEvents = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_throttle_events"),
|
||||
prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_throttle_events_total"),
|
||||
"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"),
|
||||
prometheus.BuildFQName(types.Namespace, Name, "root_partition_gpa_pages"),
|
||||
"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",
|
||||
prometheus.BuildFQName(types.Namespace, Name, "root_partition_gpa_space_modifications_total"),
|
||||
"The number 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",
|
||||
prometheus.BuildFQName(types.Namespace, Name, "root_partition_io_tlb_flush_seconds_total"),
|
||||
"The time spent processing I/O TLB flushes. Divide its rate by the rate of windows_hyperv_root_partition_io_tlb_flushes_total for the average time per 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",
|
||||
prometheus.BuildFQName(types.Namespace, Name, "root_partition_io_tlb_flushes_total"),
|
||||
"The number of flushes of I/O TLBs of the partition",
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
@@ -166,7 +168,7 @@ func (c *Collector) buildHypervisorRootPartitionDescriptors() {
|
||||
nil,
|
||||
)
|
||||
c.hypervisorRootPartitionSkippedTimerTicks = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "root_partition_physical_pages_allocated"),
|
||||
prometheus.BuildFQName(types.Namespace, Name, "root_partition_skipped_timer_ticks_total"),
|
||||
"The number of timer interrupts skipped for the partition",
|
||||
nil,
|
||||
nil,
|
||||
@@ -208,8 +210,8 @@ func (c *Collector) buildHypervisorRootPartitionDescriptors() {
|
||||
nil,
|
||||
)
|
||||
c.hypervisorRootPartitionVirtualTLBFlushEntries = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_flush_entries"),
|
||||
"The rate of flushes of the entire virtual TLB",
|
||||
prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_flush_entries_total"),
|
||||
"The number of flushes of the entire virtual TLB",
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
@@ -265,7 +267,7 @@ func (c *Collector) collectHypervisorRootPartition(ch chan<- prometheus.Metric,
|
||||
|
||||
ch <- scrape.MustNewConstMetric(
|
||||
c.hypervisorRootPartitionDeviceInterruptThrottleEvents,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionDeviceInterruptThrottleEvents,
|
||||
)
|
||||
|
||||
@@ -283,7 +285,7 @@ func (c *Collector) collectHypervisorRootPartition(ch chan<- prometheus.Metric,
|
||||
|
||||
ch <- scrape.MustNewConstMetric(
|
||||
c.hypervisorRootPartitionIOTLBFlushCost,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionIOTLBFlushCost,
|
||||
)
|
||||
|
||||
@@ -301,7 +303,7 @@ func (c *Collector) collectHypervisorRootPartition(ch chan<- prometheus.Metric,
|
||||
|
||||
ch <- scrape.MustNewConstMetric(
|
||||
c.hypervisorRootPartitionSkippedTimerTicks,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionSkippedTimerTicks,
|
||||
)
|
||||
|
||||
|
||||
@@ -36,19 +36,24 @@ type collectorHypervisorRootVirtualProcessor struct {
|
||||
// \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
|
||||
hypervisorRootVirtualProcessorTimeTotal *prometheus.Desc
|
||||
hypervisorRootVirtualProcessorTotalRunTimeTotal *prometheus.Desc
|
||||
hypervisorRootVirtualProcessorCPUWaitSeconds *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\CPU Wait Time Per Dispatch
|
||||
hypervisorRootVirtualProcessorDispatches *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\Logical Processor Dispatches/sec
|
||||
}
|
||||
|
||||
type perfDataCounterValuesHypervisorRootVirtualProcessor struct {
|
||||
Name string
|
||||
|
||||
// The run time counters and CPU Wait Time Per Dispatch are PERF_PRECISION_100NS_TIMER.
|
||||
// Their raw values are cumulative times, which pdh scales to seconds. Despite its name
|
||||
// and help text, CPU Wait Time Per Dispatch is the total wait time, not an average.
|
||||
HypervisorRootVirtualProcessorGuestRunTimePercent float64 `perfdata:"% Guest Run Time"`
|
||||
HypervisorRootVirtualProcessorHypervisorRunTimePercent float64 `perfdata:"% Hypervisor Run Time"`
|
||||
HypervisorRootVirtualProcessorTotalRunTimePercent float64 `perfdata:"% Total Run Time"`
|
||||
HypervisorRootVirtualProcessorRemoteRunTimePercent float64 `perfdata:"% Remote Run Time"`
|
||||
HypervisorRootVirtualProcessorCPUWaitTimePerDispatch float64 `perfdata:"CPU Wait Time Per Dispatch"`
|
||||
HypervisorRootVirtualProcessorDispatches float64 `perfdata:"Logical Processor Dispatches/sec"`
|
||||
}
|
||||
|
||||
func (c *Collector) buildHypervisorRootVirtualProcessor() error {
|
||||
@@ -59,28 +64,40 @@ func (c *Collector) buildHypervisorRootVirtualProcessor() error {
|
||||
return fmt.Errorf("failed to create Hyper-V Hypervisor Root Virtual Processor collector: %w", err)
|
||||
}
|
||||
|
||||
c.buildHypervisorRootVirtualProcessorDescriptors()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) buildHypervisorRootVirtualProcessorDescriptors() {
|
||||
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)",
|
||||
"Time in seconds that processor spent in different modes (guest_run, hypervisor, 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",
|
||||
"Time in seconds that processor spent running",
|
||||
[]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.",
|
||||
c.hypervisorRootVirtualProcessorCPUWaitSeconds = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_root_virtual_processor_cpu_wait_seconds_total"),
|
||||
"The time spent waiting for a virtual processor to be dispatched onto a logical processor. "+
|
||||
"Divide its rate by the rate of windows_hyperv_hypervisor_root_virtual_processor_dispatches_total for the average wait per dispatch.",
|
||||
[]string{"core"},
|
||||
nil,
|
||||
)
|
||||
|
||||
return nil
|
||||
c.hypervisorRootVirtualProcessorDispatches = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_root_virtual_processor_dispatches_total"),
|
||||
"The number of times the virtual processor was dispatched onto a logical processor.",
|
||||
[]string{"core"},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Collector) collectHypervisorRootVirtualProcessor(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
|
||||
@@ -89,8 +106,12 @@ func (c *Collector) collectHypervisorRootVirtualProcessor(ch chan<- prometheus.M
|
||||
return fmt.Errorf("failed to collect Hyper-V Hypervisor Root Virtual Processor metrics: %w", err)
|
||||
}
|
||||
|
||||
return c.publishHypervisorRootVirtualProcessor(ch, scrape)
|
||||
}
|
||||
|
||||
func (c *Collector) publishHypervisorRootVirtualProcessor(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
|
||||
for _, data := range c.perfDataObjectHypervisorRootVirtualProcessor {
|
||||
// The name format is Hv LP <core id>
|
||||
// The name format is Root VP <core id>
|
||||
parts := strings.Split(data.Name, " ")
|
||||
if len(parts) != 3 {
|
||||
return fmt.Errorf("unexpected Hyper-V Hypervisor Root Virtual Processor name format: %s", data.Name)
|
||||
@@ -127,11 +148,18 @@ func (c *Collector) collectHypervisorRootVirtualProcessor(ch chan<- prometheus.M
|
||||
)
|
||||
|
||||
ch <- scrape.MustNewConstMetric(
|
||||
c.hypervisorRootVirtualProcessorCPUWaitTimePerDispatch,
|
||||
c.hypervisorRootVirtualProcessorCPUWaitSeconds,
|
||||
prometheus.CounterValue,
|
||||
data.HypervisorRootVirtualProcessorCPUWaitTimePerDispatch,
|
||||
coreID,
|
||||
)
|
||||
|
||||
ch <- scrape.MustNewConstMetric(
|
||||
c.hypervisorRootVirtualProcessorDispatches,
|
||||
prometheus.CounterValue,
|
||||
data.HypervisorRootVirtualProcessorDispatches,
|
||||
coreID,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -39,17 +39,22 @@ type collectorHypervisorVirtualProcessor struct {
|
||||
hypervisorVirtualProcessorModeTimeTotal *prometheus.Desc // New name for better clarity
|
||||
hypervisorVirtualProcessorTotalRunTimeTotal *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Total Run Time
|
||||
hypervisorVirtualProcessorRunTimeTotal *prometheus.Desc // New name for better clarity
|
||||
hypervisorVirtualProcessorContextSwitches *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per Dispatch
|
||||
hypervisorVirtualProcessorCPUWaitSeconds *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per Dispatch
|
||||
hypervisorVirtualProcessorDispatches *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\Logical Processor Dispatches/sec
|
||||
}
|
||||
|
||||
type perfDataCounterValuesHypervisorVirtualProcessor struct {
|
||||
Name string
|
||||
|
||||
// The run time counters and CPU Wait Time Per Dispatch are PERF_PRECISION_100NS_TIMER.
|
||||
// Their raw values are cumulative times, which pdh scales to seconds. Despite its name
|
||||
// and help text, CPU Wait Time Per Dispatch is the total wait time, not an average.
|
||||
HypervisorVirtualProcessorGuestRunTimePercent float64 `perfdata:"% Guest Run Time"`
|
||||
HypervisorVirtualProcessorHypervisorRunTimePercent float64 `perfdata:"% Hypervisor Run Time"`
|
||||
HypervisorVirtualProcessorTotalRunTimePercent float64 `perfdata:"% Total Run Time"`
|
||||
HypervisorVirtualProcessorRemoteRunTimePercent float64 `perfdata:"% Remote Run Time"`
|
||||
HypervisorVirtualProcessorCPUWaitTimePerDispatch float64 `perfdata:"CPU Wait Time Per Dispatch"`
|
||||
HypervisorVirtualProcessorDispatches float64 `perfdata:"Logical Processor Dispatches/sec"`
|
||||
}
|
||||
|
||||
func (c *Collector) buildHypervisorVirtualProcessor() error {
|
||||
@@ -60,42 +65,53 @@ func (c *Collector) buildHypervisorVirtualProcessor() error {
|
||||
return fmt.Errorf("failed to create Hyper-V Hypervisor Virtual Processor collector: %w", err)
|
||||
}
|
||||
|
||||
c.buildHypervisorVirtualProcessorDescriptors()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) buildHypervisorVirtualProcessorDescriptors() {
|
||||
c.hypervisorVirtualProcessorTimeTotal = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_time_total"),
|
||||
"DEPRECATED: use hypervisor_virtual_processor_mode_time_total. Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote)",
|
||||
"DEPRECATED: use hypervisor_virtual_processor_mode_time_total. Time in seconds that processor spent in different modes (hypervisor, guest, remote)",
|
||||
[]string{"vm", "core", "state"},
|
||||
nil,
|
||||
)
|
||||
// New metric with better name for clarity, old one is kept for backward compatibility
|
||||
c.hypervisorVirtualProcessorModeTimeTotal = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_mode_time_total"),
|
||||
"Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote)",
|
||||
"Time in seconds that processor spent in different modes (hypervisor, guest, remote)",
|
||||
[]string{"vm", "core", "state"},
|
||||
nil,
|
||||
)
|
||||
// end same metric
|
||||
c.hypervisorVirtualProcessorTotalRunTimeTotal = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_total_run_time_total"),
|
||||
"DEPRECATED: use hypervisor_virtual_processor_run_time_total. Time that processor spent",
|
||||
"DEPRECATED: use hypervisor_virtual_processor_run_time_total. Time in seconds that processor spent running",
|
||||
[]string{"vm", "core"},
|
||||
nil,
|
||||
)
|
||||
// New metric with better name for clarity, old one is kept for backward compatibility
|
||||
c.hypervisorVirtualProcessorRunTimeTotal = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_run_time_total"),
|
||||
"Time that processor spent",
|
||||
"Time in seconds that processor spent running",
|
||||
[]string{"vm", "core"},
|
||||
nil,
|
||||
)
|
||||
// end same metric
|
||||
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.",
|
||||
c.hypervisorVirtualProcessorCPUWaitSeconds = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_cpu_wait_seconds_total"),
|
||||
"The time spent waiting for a virtual processor to be dispatched onto a logical processor. "+
|
||||
"Divide its rate by the rate of windows_hyperv_hypervisor_virtual_processor_dispatches_total for the average wait per dispatch.",
|
||||
[]string{"vm", "core"},
|
||||
nil,
|
||||
)
|
||||
c.hypervisorVirtualProcessorDispatches = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_dispatches_total"),
|
||||
"The number of times the virtual processor was dispatched onto a logical processor.",
|
||||
[]string{"vm", "core"},
|
||||
nil,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
|
||||
@@ -104,6 +120,10 @@ func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metri
|
||||
return fmt.Errorf("failed to collect Hyper-V Hypervisor Virtual Processor metrics: %w", err)
|
||||
}
|
||||
|
||||
return c.publishHypervisorVirtualProcessor(ch, scrape)
|
||||
}
|
||||
|
||||
func (c *Collector) publishHypervisorVirtualProcessor(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
|
||||
for _, data := range c.perfDataObjectHypervisorVirtualProcessor {
|
||||
// The name format is <VM Name>:Hv VP <vcore id>
|
||||
parts := strings.Split(data.Name, ":")
|
||||
@@ -176,11 +196,18 @@ func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metri
|
||||
)
|
||||
// end same metric
|
||||
ch <- scrape.MustNewConstMetric(
|
||||
c.hypervisorVirtualProcessorContextSwitches,
|
||||
c.hypervisorVirtualProcessorCPUWaitSeconds,
|
||||
prometheus.CounterValue,
|
||||
data.HypervisorVirtualProcessorCPUWaitTimePerDispatch,
|
||||
vmName, coreID,
|
||||
)
|
||||
|
||||
ch <- scrape.MustNewConstMetric(
|
||||
c.hypervisorVirtualProcessorDispatches,
|
||||
prometheus.CounterValue,
|
||||
data.HypervisorVirtualProcessorDispatches,
|
||||
vmName, coreID,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Copyright The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build windows
|
||||
|
||||
package hyperv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// publishCollector adapts a publish function to prometheus.Collector, so the test
|
||||
// checks the metrics as a registry gathers them.
|
||||
type publishCollector func(ch chan<- prometheus.Metric) error
|
||||
|
||||
func (publishCollector) Describe(chan<- *prometheus.Desc) {}
|
||||
|
||||
func (p publishCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
if err := p(ch); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type gatheredSample struct {
|
||||
metricType dto.MetricType
|
||||
value float64
|
||||
}
|
||||
|
||||
func gatherSamples(t *testing.T, publish publishCollector) map[string]gatheredSample {
|
||||
t.Helper()
|
||||
|
||||
registry := prometheus.NewPedanticRegistry()
|
||||
require.NoError(t, registry.Register(publish))
|
||||
|
||||
families, err := registry.Gather()
|
||||
require.NoError(t, err)
|
||||
|
||||
samples := make(map[string]gatheredSample, len(families))
|
||||
|
||||
for _, family := range families {
|
||||
metric := family.GetMetric()[0]
|
||||
|
||||
sample := gatheredSample{metricType: family.GetType()}
|
||||
|
||||
switch family.GetType() {
|
||||
case dto.MetricType_COUNTER:
|
||||
sample.value = metric.GetCounter().GetValue()
|
||||
case dto.MetricType_GAUGE:
|
||||
sample.value = metric.GetGauge().GetValue()
|
||||
default:
|
||||
t.Fatalf("unexpected metric type %s for %s", family.GetType(), family.GetName())
|
||||
}
|
||||
|
||||
samples[family.GetName()] = sample
|
||||
}
|
||||
|
||||
return samples
|
||||
}
|
||||
|
||||
func requireSample(t *testing.T, samples map[string]gatheredSample, name string, metricType dto.MetricType, value float64) {
|
||||
t.Helper()
|
||||
|
||||
sample, ok := samples[name]
|
||||
require.Truef(t, ok, "metric %s not published", name)
|
||||
require.Equalf(t, metricType, sample.metricType, "type of %s", name)
|
||||
require.InDeltaf(t, value, sample.value, 1e-9, "value of %s", name)
|
||||
}
|
||||
|
||||
type rootPartitionFixture struct{}
|
||||
|
||||
func (rootPartitionFixture) Collect(dst *[]perfDataCounterValuesHypervisorRootPartition) error {
|
||||
*dst = []perfDataCounterValuesHypervisorRootPartition{{
|
||||
HypervisorRootPartitionGPAPages: 11,
|
||||
HypervisorRootPartitionSkippedTimerTicks: 22,
|
||||
HypervisorRootPartitionDeviceInterruptThrottleEvents: 33,
|
||||
HypervisorRootPartitionIOTLBFlushCost: 0.5,
|
||||
HypervisorRootPartitionIOTLBFlushes: 44,
|
||||
HypervisorRootPartitionGPASpaceModifications: 55,
|
||||
HypervisorRootPartitionVirtualTLBFlushEntries: 66,
|
||||
}}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rootPartitionFixture) Close() {}
|
||||
|
||||
func TestRootPartitionMetricNamesAndTypes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
c := New(nil)
|
||||
c.buildHypervisorRootPartitionDescriptors()
|
||||
c.perfDataCollectorHypervisorRootPartition = rootPartitionFixture{}
|
||||
|
||||
samples := gatherSamples(t, func(ch chan<- prometheus.Metric) error {
|
||||
return c.collectHypervisorRootPartition(ch, nil)
|
||||
})
|
||||
|
||||
requireSample(t, samples, "windows_hyperv_root_partition_gpa_pages", dto.MetricType_GAUGE, 11)
|
||||
requireSample(t, samples, "windows_hyperv_root_partition_skipped_timer_ticks_total", dto.MetricType_COUNTER, 22)
|
||||
requireSample(t, samples, "windows_hyperv_root_partition_device_interrupt_throttle_events_total", dto.MetricType_COUNTER, 33)
|
||||
requireSample(t, samples, "windows_hyperv_root_partition_io_tlb_flush_seconds_total", dto.MetricType_COUNTER, 0.5)
|
||||
requireSample(t, samples, "windows_hyperv_root_partition_io_tlb_flushes_total", dto.MetricType_COUNTER, 44)
|
||||
requireSample(t, samples, "windows_hyperv_root_partition_gpa_space_modifications_total", dto.MetricType_COUNTER, 55)
|
||||
requireSample(t, samples, "windows_hyperv_root_partition_virtual_tlb_flush_entries_total", dto.MetricType_COUNTER, 66)
|
||||
|
||||
for _, removed := range []string{
|
||||
"windows_hyperv_root_partition_preferred_numa_node_index",
|
||||
"windows_hyperv_root_partition_physical_pages_allocated",
|
||||
"windows_hyperv_root_partition_io_tlb_flush_cost",
|
||||
} {
|
||||
require.NotContains(t, samples, removed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVirtualProcessorCPUWaitMetrics(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
c := New(nil)
|
||||
c.buildHypervisorVirtualProcessorDescriptors()
|
||||
c.buildHypervisorRootVirtualProcessorDescriptors()
|
||||
|
||||
// pdh has already scaled the 100ns timers to seconds.
|
||||
c.perfDataObjectHypervisorVirtualProcessor = []perfDataCounterValuesHypervisorVirtualProcessor{{
|
||||
Name: "vm1:Hv VP 0",
|
||||
HypervisorVirtualProcessorCPUWaitTimePerDispatch: 39.13,
|
||||
HypervisorVirtualProcessorDispatches: 1086776,
|
||||
}}
|
||||
c.perfDataObjectHypervisorRootVirtualProcessor = []perfDataCounterValuesHypervisorRootVirtualProcessor{{
|
||||
Name: "Root VP 0",
|
||||
HypervisorRootVirtualProcessorCPUWaitTimePerDispatch: 9.98,
|
||||
HypervisorRootVirtualProcessorDispatches: 1082841,
|
||||
}}
|
||||
|
||||
samples := gatherSamples(t, func(ch chan<- prometheus.Metric) error {
|
||||
if err := c.publishHypervisorVirtualProcessor(ch, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.publishHypervisorRootVirtualProcessor(ch, nil)
|
||||
})
|
||||
|
||||
requireSample(t, samples, "windows_hyperv_hypervisor_virtual_processor_cpu_wait_seconds_total", dto.MetricType_COUNTER, 39.13)
|
||||
requireSample(t, samples, "windows_hyperv_hypervisor_virtual_processor_dispatches_total", dto.MetricType_COUNTER, 1086776)
|
||||
requireSample(t, samples, "windows_hyperv_hypervisor_root_virtual_processor_cpu_wait_seconds_total", dto.MetricType_COUNTER, 9.98)
|
||||
requireSample(t, samples, "windows_hyperv_hypervisor_root_virtual_processor_dispatches_total", dto.MetricType_COUNTER, 1082841)
|
||||
require.NotContains(t, samples, "windows_hyperv_hypervisor_virtual_processor_cpu_wait_time_per_dispatch_total")
|
||||
require.NotContains(t, samples, "windows_hyperv_hypervisor_root_virtual_cpu_wait_time_per_dispatch_total")
|
||||
}
|
||||
|
||||
func TestVirtualStorageDeviceCounterTypes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
c := New(nil)
|
||||
c.buildVirtualStorageDeviceDescriptors()
|
||||
c.perfDataObjectVirtualStorageDevice = []perfDataCounterValuesVirtualStorageDevice{{
|
||||
Name: "ubuntu.vhdx",
|
||||
VirtualStorageDeviceThroughput: 22336,
|
||||
VirtualStorageDeviceNormalizedThroughput: 36413,
|
||||
VirtualStorageDeviceIOQuotaReplenishmentRate: 7,
|
||||
}}
|
||||
|
||||
samples := gatherSamples(t, func(ch chan<- prometheus.Metric) error {
|
||||
c.publishVirtualStorageDevice(ch, nil)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
requireSample(t, samples, "windows_hyperv_virtual_storage_device_throughput_total", dto.MetricType_COUNTER, 22336)
|
||||
requireSample(t, samples, "windows_hyperv_virtual_storage_device_normalized_throughput_total", dto.MetricType_COUNTER, 36413)
|
||||
requireSample(t, samples, "windows_hyperv_virtual_storage_device_io_quota_replenishment_total", dto.MetricType_COUNTER, 7)
|
||||
require.NotContains(t, samples, "windows_hyperv_virtual_storage_device_normalized_throughput")
|
||||
require.NotContains(t, samples, "windows_hyperv_io_quota_replenishment_rate")
|
||||
}
|
||||
@@ -72,6 +72,12 @@ func (c *Collector) buildVirtualStorageDevice() error {
|
||||
return fmt.Errorf("failed to create Hyper-V Virtual Storage Device collector: %w", err)
|
||||
}
|
||||
|
||||
c.buildVirtualStorageDeviceDescriptors()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) buildVirtualStorageDeviceDescriptors() {
|
||||
c.virtualStorageDeviceErrorCount = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_error_count_total"),
|
||||
"Represents the total number of errors that have occurred on this virtual device.",
|
||||
@@ -118,13 +124,13 @@ func (c *Collector) buildVirtualStorageDevice() error {
|
||||
)
|
||||
c.virtualStorageDeviceThroughput = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_throughput_total"),
|
||||
"Represents the total number of 8KB IO transfers completed by this virtual device.",
|
||||
"Represents the total number of IO transfers completed by this virtual device.",
|
||||
[]string{"device"},
|
||||
nil,
|
||||
)
|
||||
c.virtualStorageDeviceNormalizedThroughput = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_normalized_throughput"),
|
||||
"Represents the average number of IO transfers completed by this virtual device.",
|
||||
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_normalized_throughput_total"),
|
||||
"Represents the total number of IO transfers completed by this virtual device, normalized to 8KB transfers.",
|
||||
[]string{"device"},
|
||||
nil,
|
||||
)
|
||||
@@ -157,13 +163,11 @@ func (c *Collector) buildVirtualStorageDevice() error {
|
||||
nil,
|
||||
)
|
||||
c.virtualStorageDeviceIOQuotaReplenishmentRate = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "io_quota_replenishment_rate"),
|
||||
"Represents the IO quota replenishment rate for this virtual device.",
|
||||
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_io_quota_replenishment_total"),
|
||||
"Represents the IO quota replenishment counter for this virtual device. Use rate() for the replenishment rate.",
|
||||
[]string{"device"},
|
||||
nil,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
|
||||
@@ -172,6 +176,12 @@ func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric, scr
|
||||
return fmt.Errorf("failed to collect Hyper-V Virtual Storage Device metrics: %w", err)
|
||||
}
|
||||
|
||||
c.publishVirtualStorageDevice(ch, scrape)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) publishVirtualStorageDevice(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) {
|
||||
for _, data := range c.perfDataObjectVirtualStorageDevice {
|
||||
ch <- scrape.MustNewConstMetric(
|
||||
c.virtualStorageDeviceErrorCount,
|
||||
@@ -231,7 +241,7 @@ func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric, scr
|
||||
|
||||
ch <- scrape.MustNewConstMetric(
|
||||
c.virtualStorageDeviceNormalizedThroughput,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
data.VirtualStorageDeviceNormalizedThroughput,
|
||||
data.Name,
|
||||
)
|
||||
@@ -252,7 +262,7 @@ func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric, scr
|
||||
|
||||
ch <- scrape.MustNewConstMetric(
|
||||
c.virtualStorageDeviceIOQuotaReplenishmentRate,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
data.VirtualStorageDeviceIOQuotaReplenishmentRate,
|
||||
data.Name,
|
||||
)
|
||||
@@ -273,6 +283,4 @@ func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric, scr
|
||||
data.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user