From fdee2d8613cf6359b83490d3b68f6880ed944821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Tue, 19 Nov 2024 23:36:37 +0100 Subject: [PATCH] hyperv: Refactor collector, added DataStore, Virtual SMB and Dynamic Memory Balancer metrics (click PR number for more information) (#1712) 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 | 356 +++- internal/collector/cpu/cpu.go | 25 - internal/collector/cs/cs.go | 4 +- internal/collector/hyperv/hyperv.go | 1896 ++--------------- internal/collector/hyperv/hyperv_datastore.go | 780 +++++++ .../hyperv/hyperv_dynamic_memory_balancer.go | 108 + .../hyperv/hyperv_dynamic_memory_vm.go | 204 ++ .../hyperv_hypervisor_logical_processor.go | 121 ++ .../hyperv_hypervisor_root_partition.go | 349 +++ ...yperv_hypervisor_root_virtual_processor.go | 133 ++ .../hyperv_hypervisor_virtual_processor.go | 137 ++ .../hyperv/hyperv_legacy_network_adapter.go | 139 ++ .../hyperv_virtual_machine_health_summary.go | 74 + .../hyperv_virtual_machine_vid_partition.go | 90 + .../hyperv/hyperv_virtual_network_adapter.go | 139 ++ ...rv_virtual_network_adapter_drop_reasons.go | 527 +++++ .../collector/hyperv/hyperv_virtual_smb.go | 315 +++ .../hyperv/hyperv_virtual_storage_device.go | 235 ++ .../collector/hyperv/hyperv_virtual_switch.go | 368 ++++ 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 + internal/perfdata/collector.go | 2 +- internal/perfdata/error.go | 2 + internal/utils/utils.go | 4 + 29 files changed, 4340 insertions(+), 1952 deletions(-) create mode 100644 internal/collector/hyperv/hyperv_datastore.go create mode 100644 internal/collector/hyperv/hyperv_dynamic_memory_balancer.go create mode 100644 internal/collector/hyperv/hyperv_dynamic_memory_vm.go create mode 100644 internal/collector/hyperv/hyperv_hypervisor_logical_processor.go create mode 100644 internal/collector/hyperv/hyperv_hypervisor_root_partition.go 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 create mode 100644 internal/collector/hyperv/hyperv_virtual_machine_health_summary.go create mode 100644 internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go create mode 100644 internal/collector/hyperv/hyperv_virtual_network_adapter.go create mode 100644 internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go create mode 100644 internal/collector/hyperv/hyperv_virtual_smb.go create mode 100644 internal/collector/hyperv/hyperv_virtual_storage_device.go create mode 100644 internal/collector/hyperv/hyperv_virtual_switch.go diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index 2f0e1086..db115a87 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 0b799e6b..23c8e204 100644 --- a/docs/collector.hyperv.md +++ b/docs/collector.hyperv.md @@ -2,110 +2,262 @@ 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 -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 -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` +### Hyper-V Datastore +### Hyper-V Datastore Metrics Documentation + +This documentation outlines the available metrics for monitoring Hyper-V Datastore performance and resource usage using Prometheus. All metrics are prefixed with `windows_hyperv_datastore`. + +| Metric Name | Description | Type | Labels | +|------------------------------------------------------------------------|---------------------------------------------------------------------------------|---------|-----------| +| `windows_hyperv_datastore_fragmentation_ratio` | Represents the fragmentation ratio of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_sector_size_bytes` | Represents the sector size of the DataStore in bytes. | gauge | datastore | +| `windows_hyperv_datastore_data_alignment_bytes` | Represents the data alignment of the DataStore in bytes. | gauge | datastore | +| `windows_hyperv_datastore_current_replay_log_size_bytes` | Represents the current replay log size of the DataStore in bytes. | gauge | datastore | +| `windows_hyperv_datastore_available_entries` | Represents the number of available entries inside object tables. | gauge | datastore | +| `windows_hyperv_datastore_empty_entries` | Represents the number of empty entries inside object tables. | gauge | datastore | +| `windows_hyperv_datastore_free_bytes` | Represents the number of free bytes inside key tables. | gauge | datastore | +| `windows_hyperv_datastore_data_end_bytes` | Represents the data end of the DataStore in bytes. | gauge | datastore | +| `windows_hyperv_datastore_file_objects` | Represents the number of file objects in the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_object_tables` | Represents the number of object tables in the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_key_tables` | Represents the number of key tables in the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_file_data_size_bytes` | Represents the file data size in bytes of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_table_data_size_bytes` | Represents the table data size in bytes of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_names_size_bytes` | Represents the names size in bytes of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_number_of_keys` | Represents the number of keys in the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_reconnect_latency_microseconds` | Represents the reconnect latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_disconnect_count` | Represents the disconnect count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_write_to_file_byte_latency_microseconds` | Represents the write-to-file byte latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_write_to_file_byte_count` | Represents the write-to-file byte count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_write_to_file_count` | Represents the write-to-file count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_read_from_file_byte_latency_microseconds` | Represents the read-from-file byte latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_read_from_file_byte_count` | Represents the read-from-file byte count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_read_from_file_count` | Represents the read-from-file count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_write_to_storage_byte_latency_microseconds` | Represents the write-to-storage byte latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_write_to_storage_byte_count` | Represents the write-to-storage byte count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_write_to_storage_count` | Represents the write-to-storage count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_read_from_storage_byte_latency_microseconds` | Represents the read-from-storage byte latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_read_from_storage_byte_count` | Represents the read-from-storage byte count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_read_from_storage_count` | Represents the read-from-storage count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_commit_byte_latency_microseconds` | Represents the commit byte latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_commit_byte_count` | Represents the commit byte count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_commit_count` | Represents the commit count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_cache_update_operation_latency_microseconds` | Represents the cache update operation latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_cache_update_operation_count` | Represents the cache update operation count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_commit_operation_latency_microseconds` | Represents the commit operation latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_commit_operation_count` | Represents the commit operation count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_compact_operation_latency_microseconds` | Represents the compact operation latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_compact_operation_count` | Represents the compact operation count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_load_file_operation_latency_microseconds` | Represents the load file operation latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_load_file_operation_count` | Represents the load file operation count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_remove_operation_latency_microseconds` | Represents the remove operation latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_remove_operation_count` | Represents the remove operation count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_query_size_operation_latency_microseconds` | Represents the query size operation latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_query_size_operation_count` | Represents the query size operation count of the DataStore. | counter | datastore | +| `windows_hyperv_datastore_set_operation_latency_microseconds` | Represents the set operation latency in microseconds of the DataStore. | gauge | datastore | +| `windows_hyperv_datastore_set_operation_count` | Represents the set operation count of the DataStore. | counter | datastore | + +### 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` | 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` | 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 + +| 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 | +|------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------| +| `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_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` | 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 Network Adapter Drop Reasons + +| Name | Description | Type | Labels | +|-------------------------------------------------------|----------------------------------------------|---------|--------------------------------| +| `windows_hyperv_virtual_network_adapter_drop_reasons` | Hyper-V Virtual Network Adapter Drop Reasons | counter | `adapter`,`direction`,`reason` | + +### Hyper-V Virtual SMB + +| Name | Description | Type | Labels | +|-------------------------------------------------------|-----------------------------------------------------------------------------------|---------|------------| +| `windows_hyperv_virtual_smb_direct_mapped_sections` | Represents the number of direct-mapped sections in the virtual SMB` | gauge | `instance` | +| `windows_hyperv_virtual_smb_direct_mapped_pages` | Represents the number of direct-mapped pages in the virtual SMB` | gauge | `instance` | +| `windows_hyperv_virtual_smb_write_bytes_rdma` | Represents the number of bytes written per second using RDMA in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_write_bytes` | Represents the number of bytes written per second in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_read_bytes_rdma` | Represents the number of bytes read per second using RDMA in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_read_bytes` | Represents the number of bytes read per second in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_flush_requests` | Represents the number of flush requests per second in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_write_requests_rdma` | Represents the number of write requests per second using RDMA in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_write_requests` | Represents the number of write requests per second in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_read_requests_rdma` | Represents the number of read requests per second using RDMA in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_read_requests` | Represents the number of read requests per second in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_current_pending_requests` | Represents the current number of pending requests in the virtual SMB` | gauge | `instance` | +| `windows_hyperv_virtual_smb_current_open_file_count` | Represents the current number of open files in the virtual SMB` | gauge | `instance` | +| `windows_hyperv_virtual_smb_tree_connect_count` | Represents the number of tree connects in the virtual SMB` | gauge | `instance` | +| `windows_hyperv_virtual_smb_requests` | Represents the number of requests per second in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_sent_bytes` | Represents the number of bytes sent per second in the virtual SMB` | counter | `instance` | +| `windows_hyperv_virtual_smb_received_bytes` | Represents the number of bytes received per second in the virtual SMB` | counter | `instance` | + + +### Hyper-V Virtual Switch + +| 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` | 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 + +| 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` | + + +### Hyper-V Virtual Machine Health Summary + +| Name | Description | Type | Labels | +|------------------------------------------------------|-------------------------------------------------------|-------|--------| +| `windows_hyperv_virtual_machine_health_total_count` | Represents the number of virtual machines with health | gauge | None | + ### Example metric _This collector does not yet have explained examples, we would appreciate your help adding them!_ @@ -113,19 +265,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/cpu/cpu.go b/internal/collector/cpu/cpu.go index 1aa0ab4f..30e43bee 100644 --- a/internal/collector/cpu/cpu.go +++ b/internal/collector/cpu/cpu.go @@ -113,31 +113,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/cs/cs.go b/internal/collector/cs/cs.go index c4e98350..a77c814f 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 a2e6b7da..11ebadbc 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -6,138 +6,81 @@ import ( "errors" "fmt" "log/slog" + "sort" "strings" + "sync" "github.com/alecthomas/kingpin/v2" "github.com/prometheus-community/windows_exporter/internal/mi" - "github.com/prometheus-community/windows_exporter/internal/utils" "github.com/prometheus/client_golang/prometheus" ) -const Name = "hyperv" +const ( + Name = "hyperv" -type Config struct{} + subCollectorDataStore = "datastore" + subCollectorDynamicMemoryBalancer = "dynamic_memory_balancer" + subCollectorDynamicMemoryVM = "dynamic_memory_vm" + subCollectorHypervisorLogicalProcessor = "hypervisor_logical_processor" + subCollectorHypervisorRootPartition = "hypervisor_root_partition" + subCollectorHypervisorRootVirtualProcessor = "hypervisor_root_virtual_processor" + subCollectorHypervisorVirtualProcessor = "hypervisor_virtual_processor" + subCollectorLegacyNetworkAdapter = "legacy_network_adapter" + subCollectorVirtualMachineHealthSummary = "virtual_machine_health_summary" + subCollectorVirtualMachineVidPartition = "virtual_machine_vid_partition" + subCollectorVirtualNetworkAdapter = "virtual_network_adapter" + subCollectorVirtualNetworkAdapterDropReasons = "virtual_network_adapter_drop_reasons" + subCollectorVirtualSMB = "virtual_smb" + subCollectorVirtualStorageDevice = "virtual_storage_device" + subCollectorVirtualSwitch = "virtual_switch" +) -var ConfigDefaults = Config{} +type Config struct { + CollectorsEnabled []string `yaml:"collectors_enabled"` +} + +var ConfigDefaults = Config{ + CollectorsEnabled: []string{ + subCollectorDataStore, + subCollectorDynamicMemoryBalancer, + subCollectorDynamicMemoryVM, + subCollectorHypervisorLogicalProcessor, + subCollectorHypervisorRootPartition, + subCollectorHypervisorRootVirtualProcessor, + subCollectorHypervisorVirtualProcessor, + subCollectorLegacyNetworkAdapter, + subCollectorVirtualMachineHealthSummary, + subCollectorVirtualMachineVidPartition, + subCollectorVirtualNetworkAdapter, + subCollectorVirtualNetworkAdapterDropReasons, + subCollectorVirtualSMB, + subCollectorVirtualStorageDevice, + subCollectorVirtualSwitch, + }, +} // Collector is a Prometheus Collector for hyper-v. type Collector struct { - config Config - miSession *mi.Session + config Config - // Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary - healthCritical *prometheus.Desc - healthOk *prometheus.Desc + collectorFns []func(ch chan<- prometheus.Metric) error + closeFns []func() - // 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 - - // Win32_PerfRawData_HvStats_HyperVHypervisor - logicalProcessors *prometheus.Desc - virtualProcessors *prometheus.Desc - - // Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor - hostLPGuestRunTimePercent *prometheus.Desc - hostLPHypervisorRunTimePercent *prometheus.Desc - hostLPTotalRunTimePercent *prometheus.Desc - - // Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor - hostGuestRunTime *prometheus.Desc - hostHypervisorRunTime *prometheus.Desc - hostRemoteRunTime *prometheus.Desc - hostTotalRunTime *prometheus.Desc - hostCPUWaitTimePerDispatch *prometheus.Desc - - // 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 + collectorDataStore + collectorDynamicMemoryBalancer + collectorDynamicMemoryVM + collectorHypervisorLogicalProcessor + collectorHypervisorRootPartition + collectorHypervisorRootVirtualProcessor + collectorHypervisorVirtualProcessor + collectorLegacyNetworkAdapter + collectorVirtualMachineHealthSummary + collectorVirtualMachineVidPartition + collectorVirtualNetworkAdapter + collectorVirtualNetworkAdapterDropReasons + collectorVirtualSMB + collectorVirtualStorageDevice + collectorVirtualSwitch } func New(config *Config) *Collector { @@ -145,6 +88,10 @@ func New(config *Config) *Collector { config = &ConfigDefaults } + if config.CollectorsEnabled == nil { + config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled + } + c := &Collector{ config: *config, } @@ -152,8 +99,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 { @@ -161,590 +126,118 @@ func (c *Collector) GetName() string { } func (c *Collector) Close() error { + for _, fn := range c.closeFns { + fn() + } + 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, _ *mi.Session) error { + c.collectorFns = make([]func(ch chan<- prometheus.Metric) error, 0, len(c.config.CollectorsEnabled)) + c.closeFns = make([]func(), 0, len(c.config.CollectorsEnabled)) + + if len(c.config.CollectorsEnabled) == 0 { + return nil } - c.miSession = miSession + subCollectors := map[string]struct { + build func() error + collect func(ch chan<- prometheus.Metric) error + close func() + }{ + subCollectorDataStore: { + build: c.buildDataStore, + collect: c.collectDataStore, + close: c.perfDataCollectorDataStore.Close, + }, + subCollectorDynamicMemoryBalancer: { + build: c.buildDynamicMemoryBalancer, + collect: c.collectDynamicMemoryBalancer, + close: c.perfDataCollectorDynamicMemoryBalancer.Close, + }, + subCollectorDynamicMemoryVM: { + build: c.buildDynamicMemoryVM, + collect: c.collectDynamicMemoryVM, + close: c.perfDataCollectorDynamicMemoryVM.Close, + }, + subCollectorHypervisorLogicalProcessor: { + build: c.buildHypervisorLogicalProcessor, + collect: c.collectHypervisorLogicalProcessor, + close: c.perfDataCollectorHypervisorLogicalProcessor.Close, + }, + subCollectorHypervisorRootPartition: { + build: c.buildHypervisorRootPartition, + collect: c.collectHypervisorRootPartition, + close: c.perfDataCollectorHypervisorRootPartition.Close, + }, + subCollectorHypervisorRootVirtualProcessor: { + build: c.buildHypervisorRootVirtualProcessor, + collect: c.collectHypervisorRootVirtualProcessor, + close: c.perfDataCollectorHypervisorRootVirtualProcessor.Close, + }, + subCollectorHypervisorVirtualProcessor: { + build: c.buildHypervisorVirtualProcessor, + collect: c.collectHypervisorVirtualProcessor, + close: c.perfDataCollectorHypervisorVirtualProcessor.Close, + }, + subCollectorLegacyNetworkAdapter: { + build: c.buildLegacyNetworkAdapter, + collect: c.collectLegacyNetworkAdapter, + close: c.perfDataCollectorLegacyNetworkAdapter.Close, + }, + subCollectorVirtualMachineHealthSummary: { + build: c.buildVirtualMachineHealthSummary, + collect: c.collectVirtualMachineHealthSummary, + close: c.perfDataCollectorVirtualMachineHealthSummary.Close, + }, + subCollectorVirtualMachineVidPartition: { + build: c.buildVirtualMachineVidPartition, + collect: c.collectVirtualMachineVidPartition, + close: c.perfDataCollectorVirtualMachineVidPartition.Close, + }, + subCollectorVirtualNetworkAdapter: { + build: c.buildVirtualNetworkAdapter, + collect: c.collectVirtualNetworkAdapter, + close: c.perfDataCollectorVirtualNetworkAdapter.Close, + }, + subCollectorVirtualNetworkAdapterDropReasons: { + build: c.buildVirtualNetworkAdapterDropReasons, + collect: c.collectVirtualNetworkAdapterDropReasons, + close: c.perfDataCollectorVirtualNetworkAdapterDropReasons.Close, + }, + subCollectorVirtualSMB: { + build: c.buildVirtualSMB, + collect: c.collectVirtualSMB, + close: c.perfDataCollectorVirtualSMB.Close, + }, + subCollectorVirtualStorageDevice: { + build: c.buildVirtualStorageDevice, + collect: c.collectVirtualStorageDevice, + close: c.perfDataCollectorVirtualStorageDevice.Close, + }, + subCollectorVirtualSwitch: { + build: c.buildVirtualSwitch, + collect: c.collectVirtualSwitch, + close: c.perfDataCollectorVirtualSwitch.Close, + }, + } - buildSubsystemName := func(component string) string { return "hyperv_" + component } + // Result must order, to prevent test failures. + sort.Strings(c.config.CollectorsEnabled) - c.healthCritical = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("health"), "critical"), - "This counter represents the number of virtual machines with critical health", - nil, - nil, - ) - c.healthOk = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("health"), "ok"), - "This counter represents the number of virtual machines with ok health", - nil, - nil, - ) + for _, name := range c.config.CollectorsEnabled { + if _, ok := subCollectors[name]; !ok { + return fmt.Errorf("unknown collector: %s", name) + } - // + if err := subCollectors[name].build(); err != nil { + return fmt.Errorf("failed to build %s collector: %w", name, err) + } - c.physicalPagesAllocated = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("vid"), "physical_pages_allocated"), - "The number of physical pages allocated", - []string{"vm"}, - nil, - ) - c.preferredNUMANodeIndex = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("vid"), "preferred_numa_node_index"), - "The preferred NUMA node index associated with this partition", - []string{"vm"}, - nil, - ) - c.remotePhysicalPages = prometheus.NewDesc( - prometheus.BuildFQName("windows", 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("windows", buildSubsystemName("root_partition"), "address_spaces"), - "The number of address spaces in the virtual TLB of the partition", - nil, - nil, - ) - c.attachedDevices = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("root_partition"), "attached_devices"), - "The number of devices attached to the partition", - nil, - nil, - ) - c.depositedPages = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("root_partition"), "deposited_pages"), - "The number of pages deposited into the partition", - nil, - nil, - ) - c.deviceDMAErrors = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("root_partition"), "device_interrupt_mappings"), - "The number of device interrupt mappings used by the partition", - nil, - nil, - ) - c.deviceInterruptThrottleEvents = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("root_partition"), "gpa_space_modifications"), - "The rate of modifications to the GPA space of the partition", - nil, - nil, - ) - c.ioTLBFlushCost = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("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("windows", buildSubsystemName("root_partition"), "io_tlb_flush"), - "The rate of flushes of I/O TLBs of the partition", - nil, - nil, - ) - c.recommendedVirtualTLBSize = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("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("windows", buildSubsystemName("root_partition"), "physical_pages_allocated"), - "The number of timer interrupts skipped for the partition", - nil, - nil, - ) - c.value1Gdevicepages = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("root_partition"), "virtual_tlb_flush_entires"), - "The rate of flushes of the entire virtual TLB", - nil, - nil, - ) - c.virtualTLBPages = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("root_partition"), "virtual_tlb_pages"), - "The number of pages used by the virtual TLB of the partition", - nil, - nil, - ) - - // - - c.virtualProcessors = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("hypervisor"), "virtual_processors"), - "The number of virtual processors present in the system", - nil, - nil, - ) - c.logicalProcessors = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("hypervisor"), "logical_processors"), - "The number of logical processors present in the system", - nil, - nil, - ) - - // - - c.hostLPGuestRunTimePercent = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("host_cpu"), "guest_run_time"), - "The time spent by the virtual processor in guest code", - []string{"core"}, - nil, - ) - c.hostHypervisorRunTime = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("host_cpu"), "hypervisor_run_time"), - "The time spent by the virtual processor in hypervisor code", - []string{"core"}, - nil, - ) - c.hostRemoteRunTime = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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.broadcastPacketsReceived = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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( - prometheus.BuildFQName("windows", buildSubsystemName("ethernet"), "bytes_dropped"), - "Bytes Dropped is the number of bytes dropped on the network adapter", - []string{"adapter"}, - nil, - ) - c.adapterBytesReceived = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("ethernet"), "bytes_received"), - "Bytes received is the number of bytes received on the network adapter", - []string{"adapter"}, - nil, - ) - c.adapterBytesSent = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("ethernet"), "bytes_sent"), - "Bytes sent is the number of bytes sent over the network adapter", - []string{"adapter"}, - nil, - ) - c.adapterFramesDropped = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("ethernet"), "frames_dropped"), - "Frames Dropped is the number of frames dropped on the network adapter", - []string{"adapter"}, - nil, - ) - c.adapterFramesReceived = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("ethernet"), "frames_received"), - "Frames received is the number of frames received on the network adapter", - []string{"adapter"}, - nil, - ) - c.adapterFramesSent = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("ethernet"), "frames_sent"), - "Frames sent is the number of frames sent over the network adapter", - []string{"adapter"}, - nil, - ) - - // - - c.vmStorageErrorCount = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("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("windows", buildSubsystemName("vm_memory"), "added_total"), - "This counter represents memory in MB added to the VM", - []string{"vm"}, - nil, - ) - c.vmMemoryAveragePressure = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("vm_memory"), "pressure_average"), - "This gauge represents the average pressure in the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryCurrentPressure = prometheus.NewDesc( - prometheus.BuildFQName("windows", buildSubsystemName("vm_memory"), "pressure_current"), - "This gauge represents the current pressure in the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryGuestVisiblePhysicalMemory = prometheus.NewDesc( - prometheus.BuildFQName("windows", 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("windows", buildSubsystemName("vm_memory"), "pressure_maximum"), - "This gauge represents the maximum pressure band in the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryMemoryAddOperations = prometheus.NewDesc( - prometheus.BuildFQName("windows", 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("windows", 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("windows", buildSubsystemName("vm_memory"), "pressure_minimum"), - "This gauge represents the minimum pressure band in the VM.", - []string{"vm"}, - nil, - ) - c.vmMemoryPhysicalMemory = prometheus.NewDesc( - prometheus.BuildFQName("windows", 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("windows", buildSubsystemName("vm_memory"), "removed_total"), - "This counter represents memory in MB removed from the VM", - []string{"vm"}, - nil, - ) + c.collectorFns = append(c.collectorFns, subCollectors[name].collect) + c.closeFns = append(c.closeFns, subCollectors[name].close) + } return nil } @@ -752,999 +245,30 @@ 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(ch chan<- prometheus.Metric) error { - if err := c.collectVmHealth(ch); err != nil { - return err + errCh := make(chan error, len(c.collectorFns)) + errs := make([]error, 0, len(c.collectorFns)) + + 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) } - if err := c.collectVmVid(ch); err != nil { - return err + wg.Wait() + + close(errCh) + + for err := range errCh { + errs = append(errs, err) } - if err := c.collectVmHv(ch); err != nil { - return err - } - - if err := c.collectVmProcessor(ch); err != nil { - return err - } - - if err := c.collectHostLPUsage(nil, ch); err != nil { - return err - } - - if err := c.collectHostCpuUsage(nil, ch); err != nil { - return err - } - - if err := c.collectVmCpuUsage(nil, ch); err != nil { - return err - } - - if err := c.collectVmSwitch(ch); err != nil { - return err - } - - if err := c.collectVmEthernet(ch); err != nil { - return err - } - - if err := c.collectVmStorage(ch); err != nil { - return err - } - - if err := c.collectVmNetwork(ch); err != nil { - return err - } - - if err := c.collectVmMemory(ch); err != nil { - 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 -} - -// 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"` -} - -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) - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { - 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 `mi:"LogicalProcessors"` - VirtualProcessors uint64 `mi:"VirtualProcessors"` -} - -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) - } - - 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 `mi:"Name"` - PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"` - PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"` - PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"` -} - -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) - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { - 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 `mi:"Name"` - PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"` - PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"` - PercentRemoteRunTime uint64 `mi:"PercentRemoteRunTime"` - PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"` - CPUWaitTimePerDispatch uint64 `mi:"CPUWaitTimePerDispatch"` -} - -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) - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { - continue - } - - // 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) - - continue - } - - 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, - ) - } - - return nil -} - -// 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"` -} - -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) - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { - continue - } - - // 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 ")) - - continue - } - - 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 ")) - - continue - } - - 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, - ) - } - - return nil -} - -// 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"` -} - -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) - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { - 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 `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"` -} - -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) - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { - continue - } - - 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, - ) - } - - return nil -} - -// 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"` -} - -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) - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { - 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 -} - -// 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"` -} - -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) - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { - 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 -} - -// 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"` -} - -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) - } - - for _, obj := range dst { - if strings.Contains(obj.Name, "_Total") { - 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 + return errors.Join(errs...) } diff --git a/internal/collector/hyperv/hyperv_datastore.go b/internal/collector/hyperv/hyperv_datastore.go new file mode 100644 index 00000000..4349e6d3 --- /dev/null +++ b/internal/collector/hyperv/hyperv_datastore.go @@ -0,0 +1,780 @@ +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" +) + +// collectorDataStore Hyper-V DataStore metrics +type collectorDataStore struct { + perfDataCollectorDataStore *perfdata.Collector + + dataStoreFragmentationRatio *prometheus.Desc // \Hyper-V DataStore(*)\Fragmentation ratio + dataStoreSectorSize *prometheus.Desc // \Hyper-V DataStore(*)\Sector size + dataStoreDataAlignment *prometheus.Desc // \Hyper-V DataStore(*)\Data alignment + dataStoreCurrentReplayLogSize *prometheus.Desc // \Hyper-V DataStore(*)\Current replay logSize + dataStoreAvailableEntries *prometheus.Desc // \Hyper-V DataStore(*)\Number of available entries inside object tables + dataStoreEmptyEntries *prometheus.Desc // \Hyper-V DataStore(*)\Number of empty entries inside object tables + dataStoreFreeBytes *prometheus.Desc // \Hyper-V DataStore(*)\Number of free bytes inside key tables + dataStoreDataEnd *prometheus.Desc // \Hyper-V DataStore(*)\Data end + dataStoreFileObjects *prometheus.Desc // \Hyper-V DataStore(*)\Number of file objects + dataStoreObjectTables *prometheus.Desc // \Hyper-V DataStore(*)\Number of object tables + dataStoreKeyTables *prometheus.Desc // \Hyper-V DataStore(*)\Number of key tables + dataStoreFileDataSize *prometheus.Desc // \Hyper-V DataStore(*)\File data size in bytes + dataStoreTableDataSize *prometheus.Desc // \Hyper-V DataStore(*)\Table data size in bytes + dataStoreNamesSize *prometheus.Desc // \Hyper-V DataStore(*)\Names size in bytes + dataStoreNumberOfKeys *prometheus.Desc // \Hyper-V DataStore(*)\Number of keys + dataStoreReconnectLatencyMicro *prometheus.Desc // \Hyper-V DataStore(*)\Reconnect latency microseconds + dataStoreDisconnectCount *prometheus.Desc // \Hyper-V DataStore(*)\Disconnect count + dataStoreWriteToFileByteLatency *prometheus.Desc // \Hyper-V DataStore(*)\Write to file byte latency microseconds + dataStoreWriteToFileByteCount *prometheus.Desc // \Hyper-V DataStore(*)\Write to file byte count + dataStoreWriteToFileCount *prometheus.Desc // \Hyper-V DataStore(*)\Write to file count + dataStoreReadFromFileByteLatency *prometheus.Desc // \Hyper-V DataStore(*)\Read from file byte latency microseconds + dataStoreReadFromFileByteCount *prometheus.Desc // \Hyper-V DataStore(*)\Read from file byte count + dataStoreReadFromFileCount *prometheus.Desc // \Hyper-V DataStore(*)\Read from file count + dataStoreWriteToStorageByteLatency *prometheus.Desc // \Hyper-V DataStore(*)\Write to storage byte latency microseconds + dataStoreWriteToStorageByteCount *prometheus.Desc // \Hyper-V DataStore(*)\Write to storage byte count + dataStoreWriteToStorageCount *prometheus.Desc // \Hyper-V DataStore(*)\Write to storage count + dataStoreReadFromStorageByteLatency *prometheus.Desc // \Hyper-V DataStore(*)\Read from storage byte latency microseconds + dataStoreReadFromStorageByteCount *prometheus.Desc // \Hyper-V DataStore(*)\Read from storage byte count + dataStoreReadFromStorageCount *prometheus.Desc // \Hyper-V DataStore(*)\Read from storage count + dataStoreCommitByteLatency *prometheus.Desc // \Hyper-V DataStore(*)\Commit byte latency microseconds + dataStoreCommitByteCount *prometheus.Desc // \Hyper-V DataStore(*)\Commit byte count + dataStoreCommitCount *prometheus.Desc // \Hyper-V DataStore(*)\Commit count + dataStoreCacheUpdateOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Cache update operation latency microseconds + dataStoreCacheUpdateOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Cache update operation count + dataStoreCommitOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Commit operation latency microseconds + dataStoreCommitOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Commit operation count + dataStoreCompactOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Compact operation latency microseconds + dataStoreCompactOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Compact operation count + dataStoreLoadFileOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Load file operation latency microseconds + dataStoreLoadFileOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Load file operation count + dataStoreRemoveOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Remove operation latency microseconds + dataStoreRemoveOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Remove operation count + dataStoreQuerySizeOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Query size operation latency microseconds + dataStoreQuerySizeOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Query size operation count + dataStoreSetOperationLatencyMicro *prometheus.Desc // \Hyper-V DataStore(*)\Set operation latency microseconds + dataStoreSetOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Set operation count +} + +const ( + // Hyper-V DataStore metrics + dataStoreFragmentationRatio = "Fragmentation ratio" + dataStoreSectorSize = "Sector size" + dataStoreDataAlignment = "Data alignment" + dataStoreCurrentReplayLogSize = "Current replay logSize" + dataStoreAvailableEntries = "Number of available entries inside object tables" + dataStoreEmptyEntries = "Number of empty entries inside object tables" + dataStoreFreeBytes = "Number of free bytes inside key tables" + dataStoreDataEnd = "Data end" + dataStoreFileObjects = "Number of file objects" + dataStoreObjectTables = "Number of object tables" + dataStoreKeyTables = "Number of key tables" + dataStoreFileDataSize = "File data size in bytes" + dataStoreTableDataSize = "Table data size in bytes" + dataStoreNamesSize = "Names size in bytes" + dataStoreNumberOfKeys = "Number of keys" + dataStoreReconnectLatencyMicro = "Reconnect latency microseconds" + dataStoreDisconnectCount = "Disconnect count" + dataStoreWriteToFileByteLatency = "Write to file byte latency microseconds" + dataStoreWriteToFileByteCount = "Write to file byte count" + dataStoreWriteToFileCount = "Write to file count" + dataStoreReadFromFileByteLatency = "Read from file byte latency microseconds" + dataStoreReadFromFileByteCount = "Read from file byte count" + dataStoreReadFromFileCount = "Read from file count" + dataStoreWriteToStorageByteLatency = "Write to storage byte latency microseconds" + dataStoreWriteToStorageByteCount = "Write to storage byte count" + dataStoreWriteToStorageCount = "Write to storage count" + dataStoreReadFromStorageByteLatency = "Read from storage byte latency microseconds" + dataStoreReadFromStorageByteCount = "Read from storage byte count" + dataStoreReadFromStorageCount = "Read from storage count" + dataStoreCommitByteLatency = "Commit byte latency microseconds" + dataStoreCommitByteCount = "Commit byte count" + dataStoreCommitCount = "Commit count" + dataStoreCacheUpdateOperationLatency = "Cache update operation latency microseconds" + dataStoreCacheUpdateOperationCount = "Cache update operation count" + dataStoreCommitOperationLatency = "Commit operation latency microseconds" + dataStoreCommitOperationCount = "Commit operation count" + dataStoreCompactOperationLatency = "Compact operation latency microseconds" + dataStoreCompactOperationCount = "Compact operation count" + dataStoreLoadFileOperationLatency = "Load file operation latency microseconds" + dataStoreLoadFileOperationCount = "Load file operation count" + dataStoreRemoveOperationLatency = "Remove operation latency microseconds" + dataStoreRemoveOperationCount = "Remove operation count" + dataStoreQuerySizeOperationLatency = "Query size operation latency microseconds" + dataStoreQuerySizeOperationCount = "Query size operation count" + dataStoreSetOperationLatencyMicro = "Set operation latency microseconds" + dataStoreSetOperationCount = "Set operation count" +) + +func (c *Collector) buildDataStore() error { + var err error + + c.perfDataCollectorDataStore, err = perfdata.NewCollector("Hyper-V DataStore", perfdata.InstanceAll, []string{ + dataStoreFragmentationRatio, + dataStoreSectorSize, + dataStoreDataAlignment, + dataStoreCurrentReplayLogSize, + dataStoreAvailableEntries, + dataStoreEmptyEntries, + dataStoreFreeBytes, + dataStoreDataEnd, + dataStoreFileObjects, + dataStoreObjectTables, + dataStoreKeyTables, + dataStoreFileDataSize, + dataStoreTableDataSize, + dataStoreNamesSize, + dataStoreNumberOfKeys, + dataStoreReconnectLatencyMicro, + dataStoreDisconnectCount, + dataStoreWriteToFileByteLatency, + dataStoreWriteToFileByteCount, + dataStoreWriteToFileCount, + dataStoreReadFromFileByteLatency, + dataStoreReadFromFileByteCount, + dataStoreReadFromFileCount, + dataStoreWriteToStorageByteLatency, + dataStoreWriteToStorageByteCount, + dataStoreWriteToStorageCount, + dataStoreReadFromStorageByteLatency, + dataStoreReadFromStorageByteCount, + dataStoreReadFromStorageCount, + dataStoreCommitByteLatency, + dataStoreCommitByteCount, + dataStoreCommitCount, + dataStoreCacheUpdateOperationLatency, + dataStoreCacheUpdateOperationCount, + dataStoreCommitOperationLatency, + dataStoreCommitOperationCount, + dataStoreCompactOperationLatency, + dataStoreCompactOperationCount, + dataStoreLoadFileOperationLatency, + dataStoreLoadFileOperationCount, + dataStoreRemoveOperationLatency, + dataStoreRemoveOperationCount, + dataStoreQuerySizeOperationLatency, + dataStoreQuerySizeOperationCount, + dataStoreSetOperationLatencyMicro, + dataStoreSetOperationCount, + }) + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + return fmt.Errorf("failed to create Hyper-V DataStore collector: %w", err) + } + + c.dataStoreFragmentationRatio = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_fragmentation_ratio"), + "Represents the fragmentation ratio of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreSectorSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_sector_size_bytes"), + "Represents the sector size of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreDataAlignment = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_data_alignment_bytes"), + "Represents the data alignment of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreCurrentReplayLogSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_current_replay_log_size_bytes"), + "Represents the current replay log size of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreAvailableEntries = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_available_entries"), + "Represents the number of available entries inside object tables.", + []string{"datastore"}, + nil, + ) + c.dataStoreEmptyEntries = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_empty_entries"), + "Represents the number of empty entries inside object tables.", + []string{"datastore"}, + nil, + ) + c.dataStoreFreeBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_free_bytes"), + "Represents the number of free bytes inside key tables.", + []string{"datastore"}, + nil, + ) + c.dataStoreDataEnd = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_data_end_bytes"), + "Represents the data end of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreFileObjects = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_file_objects"), + "Represents the number of file objects in the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreObjectTables = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_object_tables"), + "Represents the number of object tables in the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreKeyTables = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_key_tables"), + "Represents the number of key tables in the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreFileDataSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_file_data_size_bytes"), + "Represents the file data size in bytes of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreTableDataSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_table_data_size_bytes"), + "Represents the table data size in bytes of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreNamesSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_names_size_bytes"), + "Represents the names size in bytes of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreNumberOfKeys = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_number_of_keys"), + "Represents the number of keys in the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreReconnectLatencyMicro = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_reconnect_latency_microseconds"), + "Represents the reconnect latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreDisconnectCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_disconnect_count"), + "Represents the disconnect count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreWriteToFileByteLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_file_byte_latency_microseconds"), + "Represents the write to file byte latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreWriteToFileByteCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_file_byte_count"), + "Represents the write to file byte count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreWriteToFileCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_file_count"), + "Represents the write to file count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreReadFromFileByteLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_file_byte_latency_microseconds"), + "Represents the read from file byte latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreReadFromFileByteCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_file_byte_count"), + "Represents the read from file byte count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreReadFromFileCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_file_count"), + "Represents the read from file count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreWriteToStorageByteLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_storage_byte_latency_microseconds"), + "Represents the write to storage byte latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreWriteToStorageByteCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_storage_byte_count"), + "Represents the write to storage byte count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreWriteToStorageCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_storage_count"), + "Represents the write to storage count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreReadFromStorageByteLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_storage_byte_latency_microseconds"), + "Represents the read from storage byte latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreReadFromStorageByteCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_storage_byte_count"), + "Represents the read from storage byte count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreReadFromStorageCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_storage_count"), + "Represents the read from storage count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreCommitByteLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_commit_byte_latency_microseconds"), + "Represents the commit byte latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreCommitByteCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_commit_byte_count"), + "Represents the commit byte count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreCommitCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_commit_count"), + "Represents the commit count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreCacheUpdateOperationLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_cache_update_operation_latency_microseconds"), + "Represents the cache update operation latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreCacheUpdateOperationCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_cache_update_operation_count"), + "Represents the cache update operation count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreCommitOperationLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_commit_operation_latency_microseconds"), + "Represents the commit operation latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreCommitOperationCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_commit_operation_count"), + "Represents the commit operation count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreCompactOperationLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_compact_operation_latency_microseconds"), + "Represents the compact operation latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreCompactOperationCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_compact_operation_count"), + "Represents the compact operation count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreLoadFileOperationLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_load_file_operation_latency_microseconds"), + "Represents the load file operation latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreLoadFileOperationCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_load_file_operation_count"), + "Represents the load file operation count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreRemoveOperationLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_remove_operation_latency_microseconds"), + "Represents the remove operation latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreRemoveOperationCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_remove_operation_count"), + "Represents the remove operation count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreQuerySizeOperationLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_query_size_operation_latency_microseconds"), + "Represents the query size operation latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreQuerySizeOperationCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_query_size_operation_count"), + "Represents the query size operation count of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreSetOperationLatencyMicro = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_set_operation_latency_microseconds"), + "Represents the set operation latency in microseconds of the DataStore.", + []string{"datastore"}, + nil, + ) + c.dataStoreSetOperationCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "datastore_set_operation_count"), + "Represents the set operation count of the DataStore.", + []string{"datastore"}, + nil, + ) + + return nil +} + +func (c *Collector) collectDataStore(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorDataStore.Collect() + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + return fmt.Errorf("failed to collect Hyper-V DataStore metrics: %w", err) + } + + for name, page := range data { + ch <- prometheus.MustNewConstMetric( + c.dataStoreFragmentationRatio, + prometheus.GaugeValue, + page[dataStoreFragmentationRatio].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreSectorSize, + prometheus.GaugeValue, + page[dataStoreSectorSize].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreDataAlignment, + prometheus.GaugeValue, + page[dataStoreDataAlignment].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreCurrentReplayLogSize, + prometheus.GaugeValue, + page[dataStoreCurrentReplayLogSize].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreAvailableEntries, + prometheus.GaugeValue, + page[dataStoreAvailableEntries].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreEmptyEntries, + prometheus.GaugeValue, + page[dataStoreEmptyEntries].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreFreeBytes, + prometheus.GaugeValue, + page[dataStoreFreeBytes].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreDataEnd, + prometheus.GaugeValue, + page[dataStoreDataEnd].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreFileObjects, + prometheus.GaugeValue, + page[dataStoreFileObjects].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreObjectTables, + prometheus.GaugeValue, + page[dataStoreObjectTables].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreKeyTables, + prometheus.GaugeValue, + page[dataStoreKeyTables].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreFileDataSize, + prometheus.GaugeValue, + page[dataStoreFileDataSize].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreTableDataSize, + prometheus.GaugeValue, + page[dataStoreTableDataSize].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreNamesSize, + prometheus.GaugeValue, + page[dataStoreNamesSize].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreNumberOfKeys, + prometheus.GaugeValue, + page[dataStoreNumberOfKeys].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreReconnectLatencyMicro, + prometheus.GaugeValue, + page[dataStoreReconnectLatencyMicro].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreDisconnectCount, + prometheus.CounterValue, + page[dataStoreDisconnectCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreWriteToFileByteLatency, + prometheus.GaugeValue, + page[dataStoreWriteToFileByteLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreWriteToFileByteCount, + prometheus.CounterValue, + page[dataStoreWriteToFileByteCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreWriteToFileCount, + prometheus.CounterValue, + page[dataStoreWriteToFileCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreReadFromFileByteLatency, + prometheus.GaugeValue, + page[dataStoreReadFromFileByteLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreReadFromFileByteCount, + prometheus.CounterValue, + page[dataStoreReadFromFileByteCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreReadFromFileCount, + prometheus.CounterValue, + page[dataStoreReadFromFileCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreWriteToStorageByteLatency, + prometheus.GaugeValue, + page[dataStoreWriteToStorageByteLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreWriteToStorageByteCount, + prometheus.CounterValue, + page[dataStoreWriteToStorageByteCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreWriteToStorageCount, + prometheus.CounterValue, + page[dataStoreWriteToStorageCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreReadFromStorageByteLatency, + prometheus.GaugeValue, + page[dataStoreReadFromStorageByteLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreReadFromStorageByteCount, + prometheus.CounterValue, + page[dataStoreReadFromStorageByteCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreReadFromStorageCount, + prometheus.CounterValue, + page[dataStoreReadFromStorageCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreCommitByteLatency, + prometheus.GaugeValue, + page[dataStoreCommitByteLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreCommitByteCount, + prometheus.CounterValue, + page[dataStoreCommitByteCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreCommitCount, + prometheus.CounterValue, + page[dataStoreCommitCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreCacheUpdateOperationLatency, + prometheus.GaugeValue, + page[dataStoreCacheUpdateOperationLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreCacheUpdateOperationCount, + prometheus.CounterValue, + page[dataStoreCacheUpdateOperationCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreCommitOperationLatency, + prometheus.GaugeValue, + page[dataStoreCommitOperationLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreCommitOperationCount, + prometheus.CounterValue, + page[dataStoreCommitOperationCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreCompactOperationLatency, + prometheus.GaugeValue, + page[dataStoreCompactOperationLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreCompactOperationCount, + prometheus.CounterValue, + page[dataStoreCompactOperationCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreLoadFileOperationLatency, + prometheus.GaugeValue, + page[dataStoreLoadFileOperationLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreLoadFileOperationCount, + prometheus.CounterValue, + page[dataStoreLoadFileOperationCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreRemoveOperationLatency, + prometheus.GaugeValue, + page[dataStoreRemoveOperationLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreRemoveOperationCount, + prometheus.CounterValue, + page[dataStoreRemoveOperationCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreQuerySizeOperationLatency, + prometheus.GaugeValue, + page[dataStoreQuerySizeOperationLatency].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreQuerySizeOperationCount, + prometheus.CounterValue, + page[dataStoreQuerySizeOperationCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreSetOperationLatencyMicro, + prometheus.GaugeValue, + page[dataStoreSetOperationLatencyMicro].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.dataStoreSetOperationCount, + prometheus.CounterValue, + page[dataStoreSetOperationCount].FirstValue, + name, + ) + } + + return nil +} 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 00000000..cfa6e4ee --- /dev/null +++ b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go @@ -0,0 +1,108 @@ +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" +) + +// 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("Hyper-V Dynamic Memory Balancer", perfdata.InstanceAll, []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"), + "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"), + "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"), + "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"), + "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) + } + + 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 00000000..639c3927 --- /dev/null +++ b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go @@ -0,0 +1,204 @@ +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" +) + +// 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("Hyper-V Dynamic Memory VM", perfdata.InstanceAll, []string{ + vmMemoryAddedMemory, + vmMemoryCurrentPressure, + vmMemoryGuestVisiblePhysicalMemory, + vmMemoryMaximumPressure, + vmMemoryMemoryAddOperations, + vmMemoryMemoryRemoveOperations, + vmMemoryMinimumPressure, + vmMemoryPhysicalMemory, + vmMemoryRemovedMemory, + vmMemoryGuestAvailableMemory, + }) + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + 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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "Represents the cumulative 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 && !errors.Is(err, perfdata.ErrNoData) { + 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_hypervisor_logical_processor.go b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go new file mode 100644 index 00000000..846ba8af --- /dev/null +++ b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go @@ -0,0 +1,121 @@ +package hyperv + +import ( + "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(*)\% Hypervisor Run Time + // \Hyper-V Hypervisor Logical Processor(*)\% Idle Time + 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 ( + 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("Hyper-V Hypervisor Logical Processor", perfdata.InstanceAll, []string{ + hypervisorLogicalProcessorGuestRunTimePercent, + hypervisorLogicalProcessorHypervisorRunTimePercent, + hypervisorLogicalProcessorTotalRunTimePercent, + hypervisorLogicalProcessorIdleRunTimePercent, + hypervisorLogicalProcessorContextSwitches, + }) + if err != nil { + return fmt.Errorf("failed to create Hyper-V Hypervisor Logical Processor collector: %w", err) + } + + 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"), + "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) + } + + 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.hypervisorLogicalProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorLogicalProcessorGuestRunTimePercent].FirstValue, + coreId, "guest", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorLogicalProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorLogicalProcessorHypervisorRunTimePercent].FirstValue, + coreId, "hypervisor", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorLogicalProcessorTimeTotal, + prometheus.CounterValue, + coreData[hypervisorLogicalProcessorIdleRunTimePercent].FirstValue, + coreId, "idle", + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorLogicalProcessorTotalRunTimeTotal, + prometheus.CounterValue, + coreData[hypervisorLogicalProcessorTotalRunTimePercent].FirstValue, + coreId, + ) + + ch <- prometheus.MustNewConstMetric( + c.hypervisorLogicalProcessorContextSwitches, + prometheus.CounterValue, + coreData[hypervisorLogicalProcessorContextSwitches].FirstValue, + coreId, + ) + } + + return nil +} 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 00000000..763bad17 --- /dev/null +++ b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go @@ -0,0 +1,349 @@ +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 + hypervisorRootPartitionVirtualTLBFlushEntries *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Flush Entries/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" + hypervisorRootPartitionVirtualTLBFlushEntries = "Virtual TLB Flush Entires/sec" + hypervisorRootPartitionVirtualTLBPages = "Virtual TLB Pages" +) + +func (c *Collector) buildHypervisorRootPartition() error { + var err error + + c.perfDataCollectorHypervisorRootPartition, err = perfdata.NewCollector("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, + hypervisorRootPartitionVirtualTLBFlushEntries, + 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.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, + ) + 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) + } + + 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.hypervisorRootPartitionVirtualTLBFlushEntries, + prometheus.CounterValue, + rootData[hypervisorRootPartitionVirtualTLBFlushEntries].FirstValue, + ) + ch <- prometheus.MustNewConstMetric( + c.hypervisorRootPartitionVirtualTLBPages, + prometheus.GaugeValue, + rootData[hypervisorRootPartitionVirtualTLBPages].FirstValue, + ) + + return nil +} 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 00000000..9c7e1d73 --- /dev/null +++ b/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go @@ -0,0 +1,133 @@ +package hyperv + +import ( + "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("Hyper-V Hypervisor Root Virtual Processor", perfdata.InstanceAll, []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) + } + + 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 00000000..acf5d077 --- /dev/null +++ b/internal/collector/hyperv/hyperv_hypervisor_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" +) + +// 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("Hyper-V Hypervisor Virtual Processor", perfdata.InstanceAll, []string{ + hypervisorVirtualProcessorGuestRunTimePercent, + hypervisorVirtualProcessorGuestIdleTimePercent, + hypervisorVirtualProcessorHypervisorRunTimePercent, + hypervisorVirtualProcessorTotalRunTimePercent, + hypervisorVirtualProcessorRemoteRunTimePercent, + hypervisorVirtualProcessorCPUWaitTimePerDispatch, + }) + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + 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 && !errors.Is(err, perfdata.ErrNoData) { + return fmt.Errorf("failed to collect Hyper-V Hypervisor Virtual Processor metrics: %w", err) + } + + 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 00000000..b0ccbccc --- /dev/null +++ b/internal/collector/hyperv/hyperv_legacy_network_adapter.go @@ -0,0 +1,139 @@ +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" +) + +// 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("Hyper-V Legacy Network Adapter", perfdata.InstanceAll, []string{ + legacyNetworkAdapterBytesDropped, + legacyNetworkAdapterBytesReceived, + legacyNetworkAdapterBytesSent, + legacyNetworkAdapterFramesDropped, + legacyNetworkAdapterFramesReceived, + legacyNetworkAdapterFramesSent, + }) + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + 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 && !errors.Is(err, perfdata.ErrNoData) { + 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 new file mode 100644 index 00000000..2e71681f --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go @@ -0,0 +1,74 @@ +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" +) + +// collectorVirtualMachineHealthSummary Hyper-V Virtual Machine Health Summary metrics +type collectorVirtualMachineHealthSummary struct { + perfDataCollectorVirtualMachineHealthSummary *perfdata.Collector + + // \Hyper-V Virtual Machine Health Summary\Health Critical + // \Hyper-V Virtual Machine Health Summary\Health Ok + health *prometheus.Desc +} + +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("Hyper-V Virtual Machine Health Summary", nil, []string{ + healthCritical, + healthOk, + }) + if err != nil { + return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err) + } + + c.health = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_machine_health_total_count"), + "Represents the number of virtual machines with critical health", + []string{"state"}, + 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) + } + + healthData, ok := data[perfdata.EmptyInstance] + if !ok { + return errors.New("no data returned for Hyper-V Virtual Machine Health Summary") + } + + ch <- prometheus.MustNewConstMetric( + c.health, + prometheus.GaugeValue, + healthData[healthCritical].FirstValue, + "critical", + ) + + ch <- prometheus.MustNewConstMetric( + c.health, + prometheus.GaugeValue, + healthData[healthOk].FirstValue, + "ok", + ) + + 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 00000000..740d4233 --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go @@ -0,0 +1,90 @@ +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" +) + +// collectorVirtualMachineVidPartition Hyper-V VM Vid Partition metrics +type collectorVirtualMachineVidPartition struct { + 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 ( + physicalPagesAllocated = "Physical Pages Allocated" + preferredNUMANodeIndex = "Preferred NUMA Node Index" + remotePhysicalPages = "Remote Physical Pages" +) + +func (c *Collector) buildVirtualMachineVidPartition() error { + var err error + + c.perfDataCollectorVirtualMachineVidPartition, err = perfdata.NewCollector("Hyper-V VM Vid Partition", perfdata.InstanceAll, []string{ + physicalPagesAllocated, + preferredNUMANodeIndex, + remotePhysicalPages, + }) + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + 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.perfDataCollectorVirtualMachineVidPartition.Collect() + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + 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/collector/hyperv/hyperv_virtual_network_adapter.go b/internal/collector/hyperv/hyperv_virtual_network_adapter.go new file mode 100644 index 00000000..6ac083e0 --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_network_adapter.go @@ -0,0 +1,139 @@ +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" +) + +// 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.perfDataCollectorVirtualNetworkAdapter, err = perfdata.NewCollector("Hyper-V Virtual Network Adapter", perfdata.InstanceAll, []string{ + virtualNetworkAdapterBytesReceived, + virtualNetworkAdapterBytesSent, + virtualNetworkAdapterDroppedPacketsIncoming, + virtualNetworkAdapterDroppedPacketsOutgoing, + virtualNetworkAdapterPacketsReceived, + virtualNetworkAdapterPacketsSent, + }) + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + 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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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.perfDataCollectorVirtualNetworkAdapter.Collect() + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + 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_network_adapter_drop_reasons.go b/internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go new file mode 100644 index 00000000..b0dae657 --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go @@ -0,0 +1,527 @@ +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" +) + +// collectorVirtualNetworkAdapterDropReasons Hyper-V Virtual Network Adapter Drop Reasons metrics +type collectorVirtualNetworkAdapterDropReasons struct { + perfDataCollectorVirtualNetworkAdapterDropReasons *perfdata.Collector + + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing LowPowerPacketFilter + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming LowPowerPacketFilter + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidPDQueue + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidPDQueue + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FilteredIsolationUntagged + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FilteredIsolationUntagged + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing SwitchDataFlowDisabled + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming SwitchDataFlowDisabled + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedPacketFilter + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedPacketFilter + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NicDisabled + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NicDisabled + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedDestinationListUpdate + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedDestinationListUpdate + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InjectedIcmp + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InjectedIcmp + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing StormLimit + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming StormLimit + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidFirstNBTooSmall + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidFirstNBTooSmall + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidSourceMac + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidSourceMac + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidDestMac + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidDestMac + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidVlanFormat + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidVlanFormat + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NativeFwdingReq + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NativeFwdingReq + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing MTUMismatch + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming MTUMismatch + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidConfig + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidConfig + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing RequiredExtensionMissing + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming RequiredExtensionMissing + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing VirtualSubnetId + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming VirtualSubnetId + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing BridgeReserved + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming BridgeReserved + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing RouterGuard + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming RouterGuard + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing DhcpGuard + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming DhcpGuard + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing MacSpoofing + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming MacSpoofing + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Ipsec + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Ipsec + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Qos + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Qos + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedPvlanSetting + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedPvlanSetting + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedSecurityPolicy + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedSecurityPolicy + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing UnauthorizedMAC + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming UnauthorizedMAC + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing UnauthorizedVLAN + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming UnauthorizedVLAN + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FilteredVLAN + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FilteredVLAN + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Filtered + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Filtered + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Busy + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Busy + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NotAccepted + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NotAccepted + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Disconnected + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Disconnected + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NotReady + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NotReady + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Resources + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Resources + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidPacket + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidPacket + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidData + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidData + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Unknown + // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Unknown + virtualNetworkAdapterDropReasons *prometheus.Desc +} + +const ( + virtualNetworkAdapterDropReasonsOutgoingNativeFwdingReq = "Outgoing NativeFwdingReq" + virtualNetworkAdapterDropReasonsIncomingNativeFwdingReq = "Incoming NativeFwdingReq" + virtualNetworkAdapterDropReasonsOutgoingMTUMismatch = "Outgoing MTUMismatch" + virtualNetworkAdapterDropReasonsIncomingMTUMismatch = "Incoming MTUMismatch" + virtualNetworkAdapterDropReasonsOutgoingInvalidConfig = "Outgoing InvalidConfig" + virtualNetworkAdapterDropReasonsIncomingInvalidConfig = "Incoming InvalidConfig" + virtualNetworkAdapterDropReasonsOutgoingRequiredExtensionMissing = "Outgoing RequiredExtensionMissing" + virtualNetworkAdapterDropReasonsIncomingRequiredExtensionMissing = "Incoming RequiredExtensionMissing" + virtualNetworkAdapterDropReasonsOutgoingVirtualSubnetId = "Outgoing VirtualSubnetId" + virtualNetworkAdapterDropReasonsIncomingVirtualSubnetId = "Incoming VirtualSubnetId" + virtualNetworkAdapterDropReasonsOutgoingBridgeReserved = "Outgoing BridgeReserved" + virtualNetworkAdapterDropReasonsIncomingBridgeReserved = "Incoming BridgeReserved" + virtualNetworkAdapterDropReasonsOutgoingRouterGuard = "Outgoing RouterGuard" + virtualNetworkAdapterDropReasonsIncomingRouterGuard = "Incoming RouterGuard" + virtualNetworkAdapterDropReasonsOutgoingDhcpGuard = "Outgoing DhcpGuard" + virtualNetworkAdapterDropReasonsIncomingDhcpGuard = "Incoming DhcpGuard" + virtualNetworkAdapterDropReasonsOutgoingMacSpoofing = "Outgoing MacSpoofing" + virtualNetworkAdapterDropReasonsIncomingMacSpoofing = "Incoming MacSpoofing" + virtualNetworkAdapterDropReasonsOutgoingIpsec = "Outgoing Ipsec" + virtualNetworkAdapterDropReasonsIncomingIpsec = "Incoming Ipsec" + virtualNetworkAdapterDropReasonsOutgoingQos = "Outgoing Qos" + virtualNetworkAdapterDropReasonsIncomingQos = "Incoming Qos" + virtualNetworkAdapterDropReasonsOutgoingFailedPvlanSetting = "Outgoing FailedPvlanSetting" + virtualNetworkAdapterDropReasonsIncomingFailedPvlanSetting = "Incoming FailedPvlanSetting" + virtualNetworkAdapterDropReasonsOutgoingFailedSecurityPolicy = "Outgoing FailedSecurityPolicy" + virtualNetworkAdapterDropReasonsIncomingFailedSecurityPolicy = "Incoming FailedSecurityPolicy" + virtualNetworkAdapterDropReasonsOutgoingUnauthorizedMAC = "Outgoing UnauthorizedMAC" + virtualNetworkAdapterDropReasonsIncomingUnauthorizedMAC = "Incoming UnauthorizedMAC" + virtualNetworkAdapterDropReasonsOutgoingUnauthorizedVLAN = "Outgoing UnauthorizedVLAN" + virtualNetworkAdapterDropReasonsIncomingUnauthorizedVLAN = "Incoming UnauthorizedVLAN" + virtualNetworkAdapterDropReasonsOutgoingFilteredVLAN = "Outgoing FilteredVLAN" + virtualNetworkAdapterDropReasonsIncomingFilteredVLAN = "Incoming FilteredVLAN" + virtualNetworkAdapterDropReasonsOutgoingFiltered = "Outgoing Filtered" + virtualNetworkAdapterDropReasonsIncomingFiltered = "Incoming Filtered" + virtualNetworkAdapterDropReasonsOutgoingBusy = "Outgoing Busy" + virtualNetworkAdapterDropReasonsIncomingBusy = "Incoming Busy" + virtualNetworkAdapterDropReasonsOutgoingNotAccepted = "Outgoing NotAccepted" + virtualNetworkAdapterDropReasonsIncomingNotAccepted = "Incoming NotAccepted" + virtualNetworkAdapterDropReasonsOutgoingDisconnected = "Outgoing Disconnected" + virtualNetworkAdapterDropReasonsIncomingDisconnected = "Incoming Disconnected" + virtualNetworkAdapterDropReasonsOutgoingNotReady = "Outgoing NotReady" + virtualNetworkAdapterDropReasonsIncomingNotReady = "Incoming NotReady" + virtualNetworkAdapterDropReasonsOutgoingResources = "Outgoing Resources" + virtualNetworkAdapterDropReasonsIncomingResources = "Incoming Resources" + virtualNetworkAdapterDropReasonsOutgoingInvalidPacket = "Outgoing InvalidPacket" + virtualNetworkAdapterDropReasonsIncomingInvalidPacket = "Incoming InvalidPacket" + virtualNetworkAdapterDropReasonsOutgoingInvalidData = "Outgoing InvalidData" + virtualNetworkAdapterDropReasonsIncomingInvalidData = "Incoming InvalidData" + virtualNetworkAdapterDropReasonsOutgoingUnknown = "Outgoing Unknown" + virtualNetworkAdapterDropReasonsIncomingUnknown = "Incoming Unknown" +) + +func (c *Collector) buildVirtualNetworkAdapterDropReasons() error { + var err error + + c.perfDataCollectorVirtualNetworkAdapterDropReasons, err = perfdata.NewCollector("Hyper-V Virtual Network Adapter Drop Reasons", perfdata.InstanceAll, []string{ + virtualNetworkAdapterDropReasonsOutgoingNativeFwdingReq, + virtualNetworkAdapterDropReasonsIncomingNativeFwdingReq, + virtualNetworkAdapterDropReasonsOutgoingMTUMismatch, + virtualNetworkAdapterDropReasonsIncomingMTUMismatch, + virtualNetworkAdapterDropReasonsOutgoingInvalidConfig, + virtualNetworkAdapterDropReasonsIncomingInvalidConfig, + virtualNetworkAdapterDropReasonsOutgoingRequiredExtensionMissing, + virtualNetworkAdapterDropReasonsIncomingRequiredExtensionMissing, + virtualNetworkAdapterDropReasonsOutgoingVirtualSubnetId, + virtualNetworkAdapterDropReasonsIncomingVirtualSubnetId, + virtualNetworkAdapterDropReasonsOutgoingBridgeReserved, + virtualNetworkAdapterDropReasonsIncomingBridgeReserved, + virtualNetworkAdapterDropReasonsOutgoingRouterGuard, + virtualNetworkAdapterDropReasonsIncomingRouterGuard, + virtualNetworkAdapterDropReasonsOutgoingDhcpGuard, + virtualNetworkAdapterDropReasonsIncomingDhcpGuard, + virtualNetworkAdapterDropReasonsOutgoingMacSpoofing, + virtualNetworkAdapterDropReasonsIncomingMacSpoofing, + virtualNetworkAdapterDropReasonsOutgoingIpsec, + virtualNetworkAdapterDropReasonsIncomingIpsec, + virtualNetworkAdapterDropReasonsOutgoingQos, + virtualNetworkAdapterDropReasonsIncomingQos, + virtualNetworkAdapterDropReasonsOutgoingFailedPvlanSetting, + virtualNetworkAdapterDropReasonsIncomingFailedPvlanSetting, + virtualNetworkAdapterDropReasonsOutgoingFailedSecurityPolicy, + virtualNetworkAdapterDropReasonsIncomingFailedSecurityPolicy, + virtualNetworkAdapterDropReasonsOutgoingUnauthorizedMAC, + virtualNetworkAdapterDropReasonsIncomingUnauthorizedMAC, + virtualNetworkAdapterDropReasonsOutgoingUnauthorizedVLAN, + virtualNetworkAdapterDropReasonsIncomingUnauthorizedVLAN, + virtualNetworkAdapterDropReasonsOutgoingFilteredVLAN, + virtualNetworkAdapterDropReasonsIncomingFilteredVLAN, + virtualNetworkAdapterDropReasonsOutgoingFiltered, + virtualNetworkAdapterDropReasonsIncomingFiltered, + virtualNetworkAdapterDropReasonsOutgoingBusy, + virtualNetworkAdapterDropReasonsIncomingBusy, + virtualNetworkAdapterDropReasonsOutgoingNotAccepted, + virtualNetworkAdapterDropReasonsIncomingNotAccepted, + virtualNetworkAdapterDropReasonsOutgoingDisconnected, + virtualNetworkAdapterDropReasonsIncomingDisconnected, + virtualNetworkAdapterDropReasonsOutgoingNotReady, + virtualNetworkAdapterDropReasonsIncomingNotReady, + virtualNetworkAdapterDropReasonsOutgoingResources, + virtualNetworkAdapterDropReasonsIncomingResources, + virtualNetworkAdapterDropReasonsOutgoingInvalidPacket, + virtualNetworkAdapterDropReasonsIncomingInvalidPacket, + virtualNetworkAdapterDropReasonsOutgoingInvalidData, + virtualNetworkAdapterDropReasonsIncomingInvalidData, + virtualNetworkAdapterDropReasonsOutgoingUnknown, + virtualNetworkAdapterDropReasonsIncomingUnknown, + }) + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter Drop Reasons collector: %w", err) + } + + c.virtualNetworkAdapterDropReasons = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_drop_reasons"), + "Hyper-V Virtual Network Adapter Drop Reasons", + []string{"adapter", "reason", "direction"}, + nil, + ) + + return nil +} + +func (c *Collector) collectVirtualNetworkAdapterDropReasons(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorVirtualNetworkAdapterDropReasons.Collect() + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + return fmt.Errorf("failed to collect Hyper-V Virtual Network Adapter Drop Reasons metrics: %w", err) + } + + for name, adapterData := range data { + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingNativeFwdingReq].FirstValue, + name, "NativeFwdingReq", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingNativeFwdingReq].FirstValue, + name, "NativeFwdingReq", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingMTUMismatch].FirstValue, + name, "MTUMismatch", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingMTUMismatch].FirstValue, + name, "MTUMismatch", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingInvalidConfig].FirstValue, + name, "InvalidConfig", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingInvalidConfig].FirstValue, + name, "InvalidConfig", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingRequiredExtensionMissing].FirstValue, + name, "RequiredExtensionMissing", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingRequiredExtensionMissing].FirstValue, + name, "RequiredExtensionMissing", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingVirtualSubnetId].FirstValue, + name, "VirtualSubnetId", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingVirtualSubnetId].FirstValue, + name, "VirtualSubnetId", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingBridgeReserved].FirstValue, + name, "BridgeReserved", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingBridgeReserved].FirstValue, + name, "BridgeReserved", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingRouterGuard].FirstValue, + name, "RouterGuard", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingRouterGuard].FirstValue, + name, "RouterGuard", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingDhcpGuard].FirstValue, + name, "DhcpGuard", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingDhcpGuard].FirstValue, + name, "DhcpGuard", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingMacSpoofing].FirstValue, + name, "MacSpoofing", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingMacSpoofing].FirstValue, + name, "MacSpoofing", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingIpsec].FirstValue, + name, "Ipsec", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingIpsec].FirstValue, + name, "Ipsec", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingQos].FirstValue, + name, "Qos", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingQos].FirstValue, + name, "Qos", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingFailedPvlanSetting].FirstValue, + name, "FailedPvlanSetting", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingFailedPvlanSetting].FirstValue, + name, "FailedPvlanSetting", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingFailedSecurityPolicy].FirstValue, + name, "FailedSecurityPolicy", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingFailedSecurityPolicy].FirstValue, + name, "FailedSecurityPolicy", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingUnauthorizedMAC].FirstValue, + name, "UnauthorizedMAC", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingUnauthorizedMAC].FirstValue, + name, "UnauthorizedMAC", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingUnauthorizedVLAN].FirstValue, + name, "UnauthorizedVLAN", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingUnauthorizedVLAN].FirstValue, + name, "UnauthorizedVLAN", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingFilteredVLAN].FirstValue, + name, "FilteredVLAN", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingFilteredVLAN].FirstValue, + name, "FilteredVLAN", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingFiltered].FirstValue, + name, "Filtered", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingFiltered].FirstValue, + name, "Filtered", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingBusy].FirstValue, + name, "Busy", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingBusy].FirstValue, + name, "Busy", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingNotAccepted].FirstValue, + name, "NotAccepted", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingNotAccepted].FirstValue, + name, "NotAccepted", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingDisconnected].FirstValue, + name, "Disconnected", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingDisconnected].FirstValue, + name, "Disconnected", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingNotReady].FirstValue, + name, "NotReady", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingNotReady].FirstValue, + name, "NotReady", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingResources].FirstValue, + name, "Resources", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingResources].FirstValue, + name, "Resources", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingInvalidPacket].FirstValue, + name, "InvalidPacket", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingInvalidPacket].FirstValue, + name, "InvalidPacket", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingInvalidData].FirstValue, + name, "InvalidData", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingInvalidData].FirstValue, + name, "InvalidData", "incoming", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsOutgoingUnknown].FirstValue, + name, "Unknown", "outgoing", + ) + ch <- prometheus.MustNewConstMetric( + c.virtualNetworkAdapterDropReasons, + prometheus.CounterValue, + adapterData[virtualNetworkAdapterDropReasonsIncomingUnknown].FirstValue, + name, "Unknown", "incoming", + ) + } + + return nil +} diff --git a/internal/collector/hyperv/hyperv_virtual_smb.go b/internal/collector/hyperv/hyperv_virtual_smb.go new file mode 100644 index 00000000..d1a0146c --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_smb.go @@ -0,0 +1,315 @@ +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" +) + +// collectorVirtualSMB Hyper-V Virtual SMB metrics +type collectorVirtualSMB struct { + perfDataCollectorVirtualSMB *perfdata.Collector + + virtualSMBDirectMappedSections *prometheus.Desc // \Hyper-V Virtual SMB(*)\Direct-Mapped Sections + virtualSMBDirectMappedPages *prometheus.Desc // \Hyper-V Virtual SMB(*)\Direct-Mapped Pages + virtualSMBWriteBytesRDMA *prometheus.Desc // \Hyper-V Virtual SMB(*)\Write Bytes/sec (RDMA) + virtualSMBWriteBytes *prometheus.Desc // \Hyper-V Virtual SMB(*)\Write Bytes/sec + virtualSMBReadBytesRDMA *prometheus.Desc // \Hyper-V Virtual SMB(*)\Read Bytes/sec (RDMA) + virtualSMBReadBytes *prometheus.Desc // \Hyper-V Virtual SMB(*)\Read Bytes/sec + virtualSMBFlushRequests *prometheus.Desc // \Hyper-V Virtual SMB(*)\Flush Requests/sec + virtualSMBWriteRequestsRDMA *prometheus.Desc // \Hyper-V Virtual SMB(*)\Write Requests/sec (RDMA) + virtualSMBWriteRequests *prometheus.Desc // \Hyper-V Virtual SMB(*)\Write Requests/sec + virtualSMBReadRequestsRDMA *prometheus.Desc // \Hyper-V Virtual SMB(*)\Read Requests/sec (RDMA) + virtualSMBReadRequests *prometheus.Desc // \Hyper-V Virtual SMB(*)\Read Requests/sec + virtualSMBCurrentPendingRequests *prometheus.Desc // \Hyper-V Virtual SMB(*)\Current Pending Requests + virtualSMBCurrentOpenFileCount *prometheus.Desc // \Hyper-V Virtual SMB(*)\Current Open File Count + virtualSMBTreeConnectCount *prometheus.Desc // \Hyper-V Virtual SMB(*)\Tree Connect Count + virtualSMBRequests *prometheus.Desc // \Hyper-V Virtual SMB(*)\Requests/sec + virtualSMBSentBytes *prometheus.Desc // \Hyper-V Virtual SMB(*)\Sent Bytes/sec + virtualSMBReceivedBytes *prometheus.Desc // \Hyper-V Virtual SMB(*)\Received Bytes/sec +} + +const ( + virtualSMBDirectMappedSections = "Direct-Mapped Sections" + virtualSMBDirectMappedPages = "Direct-Mapped Pages" + virtualSMBWriteBytesRDMA = "Write Bytes/sec (RDMA)" + virtualSMBWriteBytes = "Write Bytes/sec" + virtualSMBReadBytesRDMA = "Read Bytes/sec (RDMA)" + virtualSMBReadBytes = "Read Bytes/sec" + virtualSMBFlushRequests = "Flush Requests/sec" + virtualSMBWriteRequestsRDMA = "Write Requests/sec (RDMA)" + virtualSMBWriteRequests = "Write Requests/sec" + virtualSMBReadRequestsRDMA = "Read Requests/sec (RDMA)" + virtualSMBReadRequests = "Read Requests/sec" + virtualSMBCurrentPendingRequests = "Current Pending Requests" + virtualSMBCurrentOpenFileCount = "Current Open File Count" + virtualSMBTreeConnectCount = "Tree Connect Count" + virtualSMBRequests = "Requests/sec" + virtualSMBSentBytes = "Sent Bytes/sec" + virtualSMBReceivedBytes = "Received Bytes/sec" +) + +func (c *Collector) buildVirtualSMB() error { + var err error + + c.perfDataCollectorVirtualSMB, err = perfdata.NewCollector("Hyper-V Virtual SMB", perfdata.InstanceAll, []string{ + virtualSMBDirectMappedSections, + virtualSMBDirectMappedPages, + virtualSMBWriteBytesRDMA, + virtualSMBWriteBytes, + virtualSMBReadBytesRDMA, + virtualSMBReadBytes, + virtualSMBFlushRequests, + virtualSMBWriteRequestsRDMA, + virtualSMBWriteRequests, + virtualSMBReadRequestsRDMA, + virtualSMBReadRequests, + virtualSMBCurrentPendingRequests, + virtualSMBCurrentOpenFileCount, + virtualSMBTreeConnectCount, + virtualSMBRequests, + virtualSMBSentBytes, + virtualSMBReceivedBytes, + }) + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + return fmt.Errorf("failed to create Hyper-V Virtual SMB collector: %w", err) + } + + c.virtualSMBDirectMappedSections = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_direct_mapped_sections"), + "Represents the number of direct-mapped sections in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBDirectMappedPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_direct_mapped_pages"), + "Represents the number of direct-mapped pages in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBWriteBytesRDMA = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_write_bytes_rdma"), + "Represents the number of bytes written per second using RDMA in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBWriteBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_write_bytes"), + "Represents the number of bytes written per second in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBReadBytesRDMA = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_read_bytes_rdma"), + "Represents the number of bytes read per second using RDMA in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBReadBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_read_bytes"), + "Represents the number of bytes read per second in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBFlushRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_flush_requests"), + "Represents the number of flush requests per second in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBWriteRequestsRDMA = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_write_requests_rdma"), + "Represents the number of write requests per second using RDMA in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBWriteRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_write_requests"), + "Represents the number of write requests per second in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBReadRequestsRDMA = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_read_requests_rdma"), + "Represents the number of read requests per second using RDMA in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBReadRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_read_requests"), + "Represents the number of read requests per second in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBCurrentPendingRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_current_pending_requests"), + "Represents the current number of pending requests in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBCurrentOpenFileCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_current_open_file_count"), + "Represents the current number of open files in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBTreeConnectCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_tree_connect_count"), + "Represents the number of tree connects in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_requests"), + "Represents the number of requests per second in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBSentBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_sent_bytes"), + "Represents the number of bytes sent per second in the virtual SMB", + []string{"instance"}, + nil, + ) + c.virtualSMBReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_received_bytes"), + "Represents the number of bytes received per second in the virtual SMB", + []string{"instance"}, + nil, + ) + + return nil +} + +func (c *Collector) collectVirtualSMB(ch chan<- prometheus.Metric) error { + data, err := c.perfDataCollectorVirtualSMB.Collect() + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + return fmt.Errorf("failed to collect Hyper-V Virtual SMB metrics: %w", err) + } + + for name, smbData := range data { + ch <- prometheus.MustNewConstMetric( + c.virtualSMBDirectMappedSections, + prometheus.GaugeValue, + smbData[virtualSMBDirectMappedSections].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBDirectMappedPages, + prometheus.GaugeValue, + smbData[virtualSMBDirectMappedPages].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBWriteBytesRDMA, + prometheus.CounterValue, + smbData[virtualSMBWriteBytesRDMA].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBWriteBytes, + prometheus.CounterValue, + smbData[virtualSMBWriteBytes].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBReadBytesRDMA, + prometheus.CounterValue, + smbData[virtualSMBReadBytesRDMA].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBReadBytes, + prometheus.CounterValue, + smbData[virtualSMBReadBytes].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBFlushRequests, + prometheus.CounterValue, + smbData[virtualSMBFlushRequests].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBWriteRequestsRDMA, + prometheus.CounterValue, + smbData[virtualSMBWriteRequestsRDMA].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBWriteRequests, + prometheus.CounterValue, + smbData[virtualSMBWriteRequests].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBReadRequestsRDMA, + prometheus.CounterValue, + smbData[virtualSMBReadRequestsRDMA].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBReadRequests, + prometheus.CounterValue, + smbData[virtualSMBReadRequests].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBCurrentPendingRequests, + prometheus.GaugeValue, + smbData[virtualSMBCurrentPendingRequests].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBCurrentOpenFileCount, + prometheus.GaugeValue, + smbData[virtualSMBCurrentOpenFileCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBTreeConnectCount, + prometheus.GaugeValue, + smbData[virtualSMBTreeConnectCount].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBRequests, + prometheus.CounterValue, + smbData[virtualSMBRequests].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBSentBytes, + prometheus.CounterValue, + smbData[virtualSMBSentBytes].FirstValue, + name, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualSMBReceivedBytes, + prometheus.CounterValue, + smbData[virtualSMBReceivedBytes].FirstValue, + name, + ) + } + + return nil +} 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 00000000..ce9451a4 --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_storage_device.go @@ -0,0 +1,235 @@ +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" +) + +// 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 + 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" + virtualStorageDeviceIOQuotaReplenishmentRate = "IO Quota Replenishment Rate" +) + +func (c *Collector) buildVirtualStorageDevice() error { + var err error + + c.perfDataCollectorVirtualStorageDevice, err = perfdata.NewCollector("Hyper-V Virtual Storage Device", perfdata.InstanceAll, []string{ + virtualStorageDeviceErrorCount, + virtualStorageDeviceQueueLength, + virtualStorageDeviceReadBytes, + virtualStorageDeviceReadOperations, + virtualStorageDeviceWriteBytes, + virtualStorageDeviceWriteOperations, + virtualStorageDeviceLatency, + virtualStorageDeviceThroughput, + virtualStorageDeviceNormalizedThroughput, + virtualStorageDeviceLowerQueueLength, + virtualStorageDeviceLowerLatency, + virtualStorageDeviceIOQuotaReplenishmentRate, + }) + if err != nil && !errors.Is(err, perfdata.ErrNoData) { + 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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "Represents the IO quota replenishment rate 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 && !errors.Is(err, perfdata.ErrNoData) { + 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, + ) + + ch <- prometheus.MustNewConstMetric( + c.virtualStorageDeviceIOQuotaReplenishmentRate, + prometheus.GaugeValue, + device[virtualStorageDeviceIOQuotaReplenishmentRate].FirstValue, + name, + ) + } + + return nil +} diff --git a/internal/collector/hyperv/hyperv_virtual_switch.go b/internal/collector/hyperv/hyperv_virtual_switch.go new file mode 100644 index 00000000..353ee598 --- /dev/null +++ b/internal/collector/hyperv/hyperv_virtual_switch.go @@ -0,0 +1,368 @@ +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" +) + +// 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("Hyper-V Virtual Switch", perfdata.InstanceAll, []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 && !errors.Is(err, perfdata.ErrNoData) { + 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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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"), + "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 && !errors.Is(err, perfdata.ErrNoData) { + 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 +} diff --git a/internal/collector/mscluster/mscluster.go b/internal/collector/mscluster/mscluster.go index 887339f0..e531ee54 100644 --- a/internal/collector/mscluster/mscluster.go +++ b/internal/collector/mscluster/mscluster.go @@ -35,141 +35,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 056bb72a..d6651d02 100644 --- a/internal/collector/mscluster/mscluster_cluster.go +++ b/internal/collector/mscluster/mscluster_cluster.go @@ -13,6 +13,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 fefba789..a62d78c5 100644 --- a/internal/collector/mscluster/mscluster_network.go +++ b/internal/collector/mscluster/mscluster_network.go @@ -13,6 +13,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 58b4e26a..7a32cf0b 100644 --- a/internal/collector/mscluster/mscluster_node.go +++ b/internal/collector/mscluster/mscluster_node.go @@ -13,6 +13,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 34706aee..2c683955 100644 --- a/internal/collector/mscluster/mscluster_resource.go +++ b/internal/collector/mscluster/mscluster_resource.go @@ -13,6 +13,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 05ff4d95..7fb66f17 100644 --- a/internal/collector/mscluster/mscluster_resourcegroup.go +++ b/internal/collector/mscluster/mscluster_resourcegroup.go @@ -13,6 +13,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 { diff --git a/internal/perfdata/collector.go b/internal/perfdata/collector.go index 0800854c..5f5d69b6 100644 --- a/internal/perfdata/collector.go +++ b/internal/perfdata/collector.go @@ -112,7 +112,7 @@ func NewCollector(object string, instances []string, counters []string) (*Collec } if _, err := collector.Collect(); err != nil { - return nil, fmt.Errorf("failed to collect initial data: %w", err) + return collector, fmt.Errorf("failed to collect initial data: %w", err) } return collector, nil diff --git a/internal/perfdata/error.go b/internal/perfdata/error.go index f7a03ca2..3418344a 100644 --- a/internal/perfdata/error.go +++ b/internal/perfdata/error.go @@ -4,6 +4,8 @@ package perfdata import "errors" +var ErrNoData = NewPdhError(PdhNoData) + // Error represents error returned from Performance Counters API. type Error struct { ErrorCode uint32 diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 44401798..b9085df0 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -22,6 +22,10 @@ func ToPTR[t any](v t) *t { return &v } +func PercentageToRatio(percentage float64) float64 { + return percentage / 100 +} + // Must panics if the error is not nil. // //nolint:ireturn