diff --git a/.github/linters/.codespellrc b/.github/linters/.codespellrc index 0afbbc39..840eca34 100644 --- a/.github/linters/.codespellrc +++ b/.github/linters/.codespellrc @@ -1,2 +1,2 @@ [codespell] -ignore-words-list = notin +ignore-words-list = notin,entires diff --git a/internal/collector/ad/ad.go b/internal/collector/ad/ad.go index 7b3fe113..e6909f6f 100644 --- a/internal/collector/ad/ad.go +++ b/internal/collector/ad/ad.go @@ -39,7 +39,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues addressBookClientSessions *prometheus.Desc diff --git a/internal/collector/adcs/adcs.go b/internal/collector/adcs/adcs.go index c14c9857..1e5b3868 100644 --- a/internal/collector/adcs/adcs.go +++ b/internal/collector/adcs/adcs.go @@ -40,7 +40,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues challengeResponseProcessingTime *prometheus.Desc diff --git a/internal/collector/adfs/adfs.go b/internal/collector/adfs/adfs.go index 591bedfa..a7873c6c 100644 --- a/internal/collector/adfs/adfs.go +++ b/internal/collector/adfs/adfs.go @@ -40,7 +40,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues adLoginConnectionFailures *prometheus.Desc diff --git a/internal/collector/cache/cache.go b/internal/collector/cache/cache.go index b4c52f01..02ab8f2e 100644 --- a/internal/collector/cache/cache.go +++ b/internal/collector/cache/cache.go @@ -40,7 +40,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues asyncCopyReadsTotal *prometheus.Desc diff --git a/internal/collector/cpu/cpu.go b/internal/collector/cpu/cpu.go index de575856..10945d2c 100644 --- a/internal/collector/cpu/cpu.go +++ b/internal/collector/cpu/cpu.go @@ -41,7 +41,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues mu sync.Mutex diff --git a/internal/collector/dfsr/dfsr.go b/internal/collector/dfsr/dfsr.go index ce7b0947..7228f54c 100644 --- a/internal/collector/dfsr/dfsr.go +++ b/internal/collector/dfsr/dfsr.go @@ -47,9 +47,9 @@ var ConfigDefaults = Config{ type Collector struct { config Config - perfDataCollectorConnection *pdh.Collector - perfDataCollectorFolder *pdh.Collector - perfDataCollectorVolume *pdh.Collector + perfDataCollectorConnection *pdh.Collector[perfDataCounterValuesConnection] + perfDataCollectorFolder *pdh.Collector[perfDataCounterValuesFolder] + perfDataCollectorVolume *pdh.Collector[perfDataCounterValuesVolume] perfDataObjectConnection []perfDataCounterValuesConnection perfDataObjectFolder []perfDataCounterValuesFolder perfDataObjectVolume []perfDataCounterValuesVolume diff --git a/internal/collector/dhcp/dhcp.go b/internal/collector/dhcp/dhcp.go index a1fdf727..9dcfb5c1 100644 --- a/internal/collector/dhcp/dhcp.go +++ b/internal/collector/dhcp/dhcp.go @@ -59,7 +59,7 @@ type Collector struct { logger *slog.Logger - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues acksTotal *prometheus.Desc diff --git a/internal/collector/dns/dns.go b/internal/collector/dns/dns.go index eaa6cbd5..2ca49403 100644 --- a/internal/collector/dns/dns.go +++ b/internal/collector/dns/dns.go @@ -54,7 +54,7 @@ var ConfigDefaults = Config{ type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues miSession *mi.Session diff --git a/internal/collector/exchange/exchange_active_sync.go b/internal/collector/exchange/exchange_active_sync.go index 21408d5b..5c408281 100644 --- a/internal/collector/exchange/exchange_active_sync.go +++ b/internal/collector/exchange/exchange_active_sync.go @@ -26,7 +26,7 @@ import ( ) type collectorActiveSync struct { - perfDataCollectorActiveSync *pdh.Collector + perfDataCollectorActiveSync *pdh.Collector[perfDataCounterValuesActiveSync] perfDataObjectActiveSync []perfDataCounterValuesActiveSync activeSyncRequestsPerSec *prometheus.Desc diff --git a/internal/collector/exchange/exchange_ad_access_processes.go b/internal/collector/exchange/exchange_ad_access_processes.go index b507c329..c8ae39ed 100644 --- a/internal/collector/exchange/exchange_ad_access_processes.go +++ b/internal/collector/exchange/exchange_ad_access_processes.go @@ -27,7 +27,7 @@ import ( ) type collectorADAccessProcesses struct { - perfDataCollectorADAccessProcesses *pdh.Collector + perfDataCollectorADAccessProcesses *pdh.Collector[perfDataCounterValuesADAccessProcesses] perfDataObjectADAccessProcesses []perfDataCounterValuesADAccessProcesses ldapReadOperations *prometheus.Desc diff --git a/internal/collector/exchange/exchange_autodiscover.go b/internal/collector/exchange/exchange_autodiscover.go index 99a8232d..8a902a5c 100644 --- a/internal/collector/exchange/exchange_autodiscover.go +++ b/internal/collector/exchange/exchange_autodiscover.go @@ -26,7 +26,7 @@ import ( ) type collectorAutoDiscover struct { - perfDataCollectorAutoDiscover *pdh.Collector + perfDataCollectorAutoDiscover *pdh.Collector[perfDataCounterValuesAutoDiscover] perfDataObjectAutoDiscover []perfDataCounterValuesAutoDiscover autoDiscoverRequestsPerSec *prometheus.Desc diff --git a/internal/collector/exchange/exchange_availability_service.go b/internal/collector/exchange/exchange_availability_service.go index 1d74146a..7f3531cd 100644 --- a/internal/collector/exchange/exchange_availability_service.go +++ b/internal/collector/exchange/exchange_availability_service.go @@ -26,7 +26,7 @@ import ( ) type collectorAvailabilityService struct { - perfDataCollectorAvailabilityService *pdh.Collector + perfDataCollectorAvailabilityService *pdh.Collector[perfDataCounterValuesAvailabilityService] perfDataObjectAvailabilityService []perfDataCounterValuesAvailabilityService availabilityRequestsSec *prometheus.Desc diff --git a/internal/collector/exchange/exchange_http_proxy.go b/internal/collector/exchange/exchange_http_proxy.go index e2a14e04..c49ac695 100644 --- a/internal/collector/exchange/exchange_http_proxy.go +++ b/internal/collector/exchange/exchange_http_proxy.go @@ -27,7 +27,7 @@ import ( ) type collectorHTTPProxy struct { - perfDataCollectorHTTPProxy *pdh.Collector + perfDataCollectorHTTPProxy *pdh.Collector[perfDataCounterValuesHTTPProxy] perfDataObjectHTTPProxy []perfDataCounterValuesHTTPProxy mailboxServerLocatorAverageLatency *prometheus.Desc diff --git a/internal/collector/exchange/exchange_mapi_http_emsmdb.go b/internal/collector/exchange/exchange_mapi_http_emsmdb.go index 67ea1283..60f4b5a3 100644 --- a/internal/collector/exchange/exchange_mapi_http_emsmdb.go +++ b/internal/collector/exchange/exchange_mapi_http_emsmdb.go @@ -26,7 +26,7 @@ import ( ) type collectorMapiHTTPEmsMDB struct { - perfDataCollectorMapiHTTPEmsMDB *pdh.Collector + perfDataCollectorMapiHTTPEmsMDB *pdh.Collector[perfDataCounterValuesMapiHTTPEmsMDB] perfDataObjectMapiHTTPEmsMDB []perfDataCounterValuesMapiHTTPEmsMDB activeUserCountMapiHTTPEmsMDB *prometheus.Desc diff --git a/internal/collector/exchange/exchange_outlook_web_access.go b/internal/collector/exchange/exchange_outlook_web_access.go index 62c1b0b2..49f9e0d1 100644 --- a/internal/collector/exchange/exchange_outlook_web_access.go +++ b/internal/collector/exchange/exchange_outlook_web_access.go @@ -26,7 +26,7 @@ import ( ) type collectorOWA struct { - perfDataCollectorOWA *pdh.Collector + perfDataCollectorOWA *pdh.Collector[perfDataCounterValuesOWA] perfDataObjectOWA []perfDataCounterValuesOWA currentUniqueUsers *prometheus.Desc diff --git a/internal/collector/exchange/exchange_rpc_client_access.go b/internal/collector/exchange/exchange_rpc_client_access.go index cd78b915..eb50c8e6 100644 --- a/internal/collector/exchange/exchange_rpc_client_access.go +++ b/internal/collector/exchange/exchange_rpc_client_access.go @@ -27,7 +27,7 @@ import ( ) type collectorRpcClientAccess struct { - perfDataCollectorRpcClientAccess *pdh.Collector + perfDataCollectorRpcClientAccess *pdh.Collector[perfDataCounterValuesRpcClientAccess] perfDataObjectRpcClientAccess []perfDataCounterValuesRpcClientAccess activeUserCount *prometheus.Desc diff --git a/internal/collector/exchange/exchange_transport_queues.go b/internal/collector/exchange/exchange_transport_queues.go index 35c3b3dd..982e70bd 100644 --- a/internal/collector/exchange/exchange_transport_queues.go +++ b/internal/collector/exchange/exchange_transport_queues.go @@ -26,7 +26,7 @@ import ( ) type collectorTransportQueues struct { - perfDataCollectorTransportQueues *pdh.Collector + perfDataCollectorTransportQueues *pdh.Collector[perfDataCounterValuesTransportQueues] perfDataObjectTransportQueues []perfDataCounterValuesTransportQueues activeMailboxDeliveryQueueLength *prometheus.Desc diff --git a/internal/collector/exchange/exchange_workload_management.go b/internal/collector/exchange/exchange_workload_management.go index afe53ae9..6fbd1e19 100644 --- a/internal/collector/exchange/exchange_workload_management.go +++ b/internal/collector/exchange/exchange_workload_management.go @@ -26,7 +26,7 @@ import ( ) type collectorWorkloadManagementWorkloads struct { - perfDataCollectorWorkloadManagementWorkloads *pdh.Collector + perfDataCollectorWorkloadManagementWorkloads *pdh.Collector[perfDataCounterValuesWorkloadManagementWorkloads] perfDataObjectWorkloadManagementWorkloads []perfDataCounterValuesWorkloadManagementWorkloads activeTasks *prometheus.Desc diff --git a/internal/collector/gpu/gpu.go b/internal/collector/gpu/gpu.go index 45fd2dcb..2e2e3b5a 100644 --- a/internal/collector/gpu/gpu.go +++ b/internal/collector/gpu/gpu.go @@ -45,7 +45,7 @@ type Collector struct { gpuDeviceCache map[string]gpuDevice // GPU Engine - gpuEnginePerfDataCollector *pdh.Collector + gpuEnginePerfDataCollector *pdh.Collector[gpuEnginePerfDataCounterValues] gpuEnginePerfDataObject []gpuEnginePerfDataCounterValues gpuInfo *prometheus.Desc @@ -56,7 +56,7 @@ type Collector struct { gpuDedicatedVideoMemorySize *prometheus.Desc // GPU Adapter Memory - gpuAdapterMemoryPerfDataCollector *pdh.Collector + gpuAdapterMemoryPerfDataCollector *pdh.Collector[gpuAdapterMemoryPerfDataCounterValues] gpuAdapterMemoryPerfDataObject []gpuAdapterMemoryPerfDataCounterValues gpuAdapterMemoryDedicatedUsage *prometheus.Desc @@ -64,19 +64,19 @@ type Collector struct { gpuAdapterMemoryTotalCommitted *prometheus.Desc // GPU Local Adapter Memory - gpuLocalAdapterMemoryPerfDataCollector *pdh.Collector + gpuLocalAdapterMemoryPerfDataCollector *pdh.Collector[gpuLocalAdapterMemoryPerfDataCounterValues] gpuLocalAdapterMemoryPerfDataObject []gpuLocalAdapterMemoryPerfDataCounterValues gpuLocalAdapterMemoryUsage *prometheus.Desc // GPU Non Local Adapter Memory - gpuNonLocalAdapterMemoryPerfDataCollector *pdh.Collector + gpuNonLocalAdapterMemoryPerfDataCollector *pdh.Collector[gpuNonLocalAdapterMemoryPerfDataCounterValues] gpuNonLocalAdapterMemoryPerfDataObject []gpuNonLocalAdapterMemoryPerfDataCounterValues gpuNonLocalAdapterMemoryUsage *prometheus.Desc // GPU Process Memory - gpuProcessMemoryPerfDataCollector *pdh.Collector + gpuProcessMemoryPerfDataCollector *pdh.Collector[gpuProcessMemoryPerfDataCounterValues] gpuProcessMemoryPerfDataObject []gpuProcessMemoryPerfDataCounterValues gpuProcessMemoryDedicatedUsage *prometheus.Desc diff --git a/internal/collector/hyperv/hyperv_datastore.go b/internal/collector/hyperv/hyperv_datastore.go index 439e2d22..b99e97ed 100644 --- a/internal/collector/hyperv/hyperv_datastore.go +++ b/internal/collector/hyperv/hyperv_datastore.go @@ -27,7 +27,7 @@ import ( // collectorDataStore Hyper-V DataStore metrics type collectorDataStore struct { - perfDataCollectorDataStore *pdh.Collector + perfDataCollectorDataStore *pdh.Collector[perfDataCounterValuesDataStore] perfDataObjectDataStore []perfDataCounterValuesDataStore dataStoreFragmentationRatio *prometheus.Desc // \Hyper-V DataStore(*)\Fragmentation ratio diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go index f10f2200..63c4a309 100644 --- a/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go +++ b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go @@ -29,7 +29,7 @@ import ( // collectorDynamicMemoryBalancer Hyper-V Dynamic Memory Balancer metrics type collectorDynamicMemoryBalancer struct { - perfDataCollectorDynamicMemoryBalancer *pdh.Collector + perfDataCollectorDynamicMemoryBalancer *pdh.Collector[perfDataCounterValuesDynamicMemoryBalancer] perfDataObjectDynamicMemoryBalancer []perfDataCounterValuesDynamicMemoryBalancer vmDynamicMemoryBalancerAvailableMemoryForBalancing *prometheus.Desc // \Hyper-V Dynamic Memory Balancer(*)\Available Memory For Balancing diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go index 6147ba0f..344882a6 100644 --- a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go +++ b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go @@ -29,7 +29,7 @@ import ( // collectorDynamicMemoryVM Hyper-V Dynamic Memory VM metrics type collectorDynamicMemoryVM struct { - perfDataCollectorDynamicMemoryVM *pdh.Collector + perfDataCollectorDynamicMemoryVM *pdh.Collector[perfDataCounterValuesDynamicMemoryVM] perfDataObjectDynamicMemoryVM []perfDataCounterValuesDynamicMemoryVM vmMemoryAddedMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Added Memory diff --git a/internal/collector/hyperv/hyperv_host.go b/internal/collector/hyperv/hyperv_host.go index 39efbf2e..ac227cb2 100644 --- a/internal/collector/hyperv/hyperv_host.go +++ b/internal/collector/hyperv/hyperv_host.go @@ -32,7 +32,7 @@ import ( // collectorHost Hyper-V Host metrics type collectorHost struct { - perfDataCollectorLogicalProcessor *pdh.Collector + perfDataCollectorLogicalProcessor *pdh.Collector[perfDataCounterValuesHost] perfDataObjectLogicalProcessor []perfDataCounterValuesHost vmProcessorCount *prometheus.Desc diff --git a/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go index 11d50575..817c1bdf 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go +++ b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go @@ -28,7 +28,7 @@ import ( // collectorHypervisorLogicalProcessor Hyper-V Hypervisor Logical Processor metrics type collectorHypervisorLogicalProcessor struct { - perfDataCollectorHypervisorLogicalProcessor *pdh.Collector + perfDataCollectorHypervisorLogicalProcessor *pdh.Collector[perfDataCounterValuesHypervisorLogicalProcessor] perfDataObjectHypervisorLogicalProcessor []perfDataCounterValuesHypervisorLogicalProcessor // \Hyper-V Hypervisor Logical Processor(*)\% Guest Run Time diff --git a/internal/collector/hyperv/hyperv_hypervisor_root_partition.go b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go index 1f2a4e4b..61b44c24 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_root_partition.go +++ b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go @@ -27,7 +27,7 @@ import ( // collectorHypervisorRootPartition Hyper-V Hypervisor Root Partition metrics type collectorHypervisorRootPartition struct { - perfDataCollectorHypervisorRootPartition *pdh.Collector + perfDataCollectorHypervisorRootPartition *pdh.Collector[perfDataCounterValuesHypervisorRootPartition] perfDataObjectHypervisorRootPartition []perfDataCounterValuesHypervisorRootPartition hypervisorRootPartitionAddressSpaces *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Address Spaces diff --git a/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go b/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go index 9077a34c..e0c36717 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go +++ b/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go @@ -28,7 +28,7 @@ import ( // collectorHypervisorRootVirtualProcessor Hyper-V Hypervisor Root Virtual Processor metrics type collectorHypervisorRootVirtualProcessor struct { - perfDataCollectorHypervisorRootVirtualProcessor *pdh.Collector + perfDataCollectorHypervisorRootVirtualProcessor *pdh.Collector[perfDataCounterValuesHypervisorRootVirtualProcessor] perfDataObjectHypervisorRootVirtualProcessor []perfDataCounterValuesHypervisorRootVirtualProcessor // \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Run Time diff --git a/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go b/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go index d6e3048b..579751ab 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go +++ b/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go @@ -28,7 +28,7 @@ import ( // collectorHypervisorVirtualProcessor Hyper-V Hypervisor Virtual Processor metrics type collectorHypervisorVirtualProcessor struct { - perfDataCollectorHypervisorVirtualProcessor *pdh.Collector + perfDataCollectorHypervisorVirtualProcessor *pdh.Collector[perfDataCounterValuesHypervisorVirtualProcessor] perfDataObjectHypervisorVirtualProcessor []perfDataCounterValuesHypervisorVirtualProcessor // \Hyper-V Hypervisor Virtual Processor(*)\% Guest Run Time diff --git a/internal/collector/hyperv/hyperv_legacy_network_adapter.go b/internal/collector/hyperv/hyperv_legacy_network_adapter.go index 00e0e2b9..8f86c91a 100644 --- a/internal/collector/hyperv/hyperv_legacy_network_adapter.go +++ b/internal/collector/hyperv/hyperv_legacy_network_adapter.go @@ -27,7 +27,7 @@ import ( // collectorLegacyNetworkAdapter Hyper-V Legacy Network Adapter metrics type collectorLegacyNetworkAdapter struct { - perfDataCollectorLegacyNetworkAdapter *pdh.Collector + perfDataCollectorLegacyNetworkAdapter *pdh.Collector[perfDataCounterValuesLegacyNetworkAdapter] perfDataObjectLegacyNetworkAdapter []perfDataCounterValuesLegacyNetworkAdapter legacyNetworkAdapterBytesDropped *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Dropped diff --git a/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go index d59690f8..229635b7 100644 --- a/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go +++ b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go @@ -27,7 +27,7 @@ import ( // collectorVirtualMachineHealthSummary Hyper-V Virtual Machine Health Summary metrics type collectorVirtualMachineHealthSummary struct { - perfDataCollectorVirtualMachineHealthSummary *pdh.Collector + perfDataCollectorVirtualMachineHealthSummary *pdh.Collector[perfDataCounterValuesVirtualMachineHealthSummary] perfDataObjectVirtualMachineHealthSummary []perfDataCounterValuesVirtualMachineHealthSummary // \Hyper-V Virtual Machine Health Summary\Health Critical diff --git a/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go index fafc8f83..f0364ae2 100644 --- a/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go +++ b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go @@ -27,7 +27,7 @@ import ( // collectorVirtualMachineVidPartition Hyper-V VM Vid Partition metrics type collectorVirtualMachineVidPartition struct { - perfDataCollectorVirtualMachineVidPartition *pdh.Collector + perfDataCollectorVirtualMachineVidPartition *pdh.Collector[perfDataCounterValuesVirtualMachineVidPartition] perfDataObjectVirtualMachineVidPartition []perfDataCounterValuesVirtualMachineVidPartition physicalPagesAllocated *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Physical Pages Allocated diff --git a/internal/collector/hyperv/hyperv_virtual_network_adapter.go b/internal/collector/hyperv/hyperv_virtual_network_adapter.go index 71fc532f..20e5db9f 100644 --- a/internal/collector/hyperv/hyperv_virtual_network_adapter.go +++ b/internal/collector/hyperv/hyperv_virtual_network_adapter.go @@ -27,7 +27,7 @@ import ( // collectorVirtualNetworkAdapter Hyper-V Virtual Network Adapter metrics type collectorVirtualNetworkAdapter struct { - perfDataCollectorVirtualNetworkAdapter *pdh.Collector + perfDataCollectorVirtualNetworkAdapter *pdh.Collector[perfDataCounterValuesVirtualNetworkAdapter] perfDataObjectVirtualNetworkAdapter []perfDataCounterValuesVirtualNetworkAdapter virtualNetworkAdapterBytesReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Bytes Received/sec diff --git a/internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go b/internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go index 759a2206..ba524a18 100644 --- a/internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go +++ b/internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go @@ -27,7 +27,7 @@ import ( // collectorVirtualNetworkAdapterDropReasons Hyper-V Virtual Network Adapter Drop Reasons metrics type collectorVirtualNetworkAdapterDropReasons struct { - perfDataCollectorVirtualNetworkAdapterDropReasons *pdh.Collector + perfDataCollectorVirtualNetworkAdapterDropReasons *pdh.Collector[perfDataCounterValuesVirtualNetworkAdapterDropReasons] perfDataObjectVirtualNetworkAdapterDropReasons []perfDataCounterValuesVirtualNetworkAdapterDropReasons // \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing LowPowerPacketFilter diff --git a/internal/collector/hyperv/hyperv_virtual_smb.go b/internal/collector/hyperv/hyperv_virtual_smb.go index 2468868b..24bb2fae 100644 --- a/internal/collector/hyperv/hyperv_virtual_smb.go +++ b/internal/collector/hyperv/hyperv_virtual_smb.go @@ -27,7 +27,7 @@ import ( // collectorVirtualSMB Hyper-V Virtual SMB metrics type collectorVirtualSMB struct { - perfDataCollectorVirtualSMB *pdh.Collector + perfDataCollectorVirtualSMB *pdh.Collector[perfDataCounterValuesVirtualSMB] perfDataObjectVirtualSMB []perfDataCounterValuesVirtualSMB virtualSMBDirectMappedSections *prometheus.Desc // \Hyper-V Virtual SMB(*)\Direct-Mapped Sections diff --git a/internal/collector/hyperv/hyperv_virtual_storage_device.go b/internal/collector/hyperv/hyperv_virtual_storage_device.go index 5812ec43..cee9a265 100644 --- a/internal/collector/hyperv/hyperv_virtual_storage_device.go +++ b/internal/collector/hyperv/hyperv_virtual_storage_device.go @@ -27,7 +27,7 @@ import ( // Hyper-V Virtual Storage Device metrics type collectorVirtualStorageDevice struct { - perfDataCollectorVirtualStorageDevice *pdh.Collector + perfDataCollectorVirtualStorageDevice *pdh.Collector[perfDataCounterValuesVirtualStorageDevice] perfDataObjectVirtualStorageDevice []perfDataCounterValuesVirtualStorageDevice virtualStorageDeviceErrorCount *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Error Count diff --git a/internal/collector/hyperv/hyperv_virtual_switch.go b/internal/collector/hyperv/hyperv_virtual_switch.go index fb93940d..9828eedd 100644 --- a/internal/collector/hyperv/hyperv_virtual_switch.go +++ b/internal/collector/hyperv/hyperv_virtual_switch.go @@ -27,7 +27,7 @@ import ( // collectorVirtualMachineHealthSummary Hyper-V Virtual Switch Summary metrics type collectorVirtualSwitch struct { - perfDataCollectorVirtualSwitch *pdh.Collector + perfDataCollectorVirtualSwitch *pdh.Collector[perfDataCounterValuesVirtualSwitch] perfDataObjectVirtualSwitch []perfDataCounterValuesVirtualSwitch virtualSwitchBroadcastPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Broadcast Packets Received/sec diff --git a/internal/collector/iis/iis_app_pool_was.go b/internal/collector/iis/iis_app_pool_was.go index 9f26e6bb..2971ceb6 100644 --- a/internal/collector/iis/iis_app_pool_was.go +++ b/internal/collector/iis/iis_app_pool_was.go @@ -26,7 +26,7 @@ import ( ) type collectorAppPoolWAS struct { - perfDataCollectorAppPoolWAS *pdh.Collector + perfDataCollectorAppPoolWAS *pdh.Collector[perfDataCounterValuesAppPoolWAS] perfDataObjectAppPoolWAS []perfDataCounterValuesAppPoolWAS currentApplicationPoolState *prometheus.Desc diff --git a/internal/collector/iis/iis_http_service_request_queues.go b/internal/collector/iis/iis_http_service_request_queues.go index d490bdd8..ab680c32 100644 --- a/internal/collector/iis/iis_http_service_request_queues.go +++ b/internal/collector/iis/iis_http_service_request_queues.go @@ -27,7 +27,7 @@ import ( ) type collectorHttpServiceRequestQueues struct { - perfDataCollectorHttpServiceRequestQueues *pdh.Collector + perfDataCollectorHttpServiceRequestQueues *pdh.Collector[perfDataCounterValuesHttpServiceRequestQueues] perfDataObjectHttpServiceRequestQueues []perfDataCounterValuesHttpServiceRequestQueues httpRequestQueuesCurrentQueueSize *prometheus.Desc diff --git a/internal/collector/iis/iis_w3svc_w3wp.go b/internal/collector/iis/iis_w3svc_w3wp.go index 6fa46996..790f923e 100644 --- a/internal/collector/iis/iis_w3svc_w3wp.go +++ b/internal/collector/iis/iis_w3svc_w3wp.go @@ -27,8 +27,8 @@ import ( ) type collectorW3SVCW3WP struct { - w3SVCW3WPPerfDataCollector *pdh.Collector - w3SVCW3WPPerfDataCollectorV8 *pdh.Collector + w3SVCW3WPPerfDataCollector *pdh.Collector[perfDataCounterValuesW3SVCW3WP] + w3SVCW3WPPerfDataCollectorV8 *pdh.Collector[perfDataCounterValuesW3SVCW3WPV8] perfDataObjectW3SVCW3WP []perfDataCounterValuesW3SVCW3WP perfDataObjectW3SVCW3WPV8 []perfDataCounterValuesW3SVCW3WPV8 diff --git a/internal/collector/iis/iis_web_service.go b/internal/collector/iis/iis_web_service.go index 84afffb2..4f828289 100644 --- a/internal/collector/iis/iis_web_service.go +++ b/internal/collector/iis/iis_web_service.go @@ -26,7 +26,7 @@ import ( ) type collectorWebService struct { - perfDataCollectorWebService *pdh.Collector + perfDataCollectorWebService *pdh.Collector[perfDataCounterValuesWebService] perfDataObjectWebService []perfDataCounterValuesWebService webServiceCurrentAnonymousUsers *prometheus.Desc diff --git a/internal/collector/iis/iis_web_service_cache.go b/internal/collector/iis/iis_web_service_cache.go index 66bad5aa..be09b475 100644 --- a/internal/collector/iis/iis_web_service_cache.go +++ b/internal/collector/iis/iis_web_service_cache.go @@ -26,7 +26,7 @@ import ( ) type collectorWebServiceCache struct { - serviceCachePerfDataCollector *pdh.Collector + serviceCachePerfDataCollector *pdh.Collector[perfDataCounterServiceCache] perfDataObjectServiceCache []perfDataCounterServiceCache serviceCacheActiveFlushedEntries *prometheus.Desc diff --git a/internal/collector/logical_disk/logical_disk.go b/internal/collector/logical_disk/logical_disk.go index cfc5a00d..65362e57 100644 --- a/internal/collector/logical_disk/logical_disk.go +++ b/internal/collector/logical_disk/logical_disk.go @@ -85,7 +85,7 @@ type Collector struct { config Config logger *slog.Logger - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues avgReadQueue *prometheus.Desc diff --git a/internal/collector/memory/memory.go b/internal/collector/memory/memory.go index 40aed96c..d9c63938 100644 --- a/internal/collector/memory/memory.go +++ b/internal/collector/memory/memory.go @@ -45,7 +45,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues // Performance metrics diff --git a/internal/collector/msmq/msmq.go b/internal/collector/msmq/msmq.go index ba485011..384d4bcd 100644 --- a/internal/collector/msmq/msmq.go +++ b/internal/collector/msmq/msmq.go @@ -39,7 +39,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics. type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues bytesInJournalQueue *prometheus.Desc diff --git a/internal/collector/mssql/mssql.go b/internal/collector/mssql/mssql.go index 4e50610c..250b5fbd 100644 --- a/internal/collector/mssql/mssql.go +++ b/internal/collector/mssql/mssql.go @@ -368,11 +368,11 @@ func (c *Collector) mssqlGetPerfObjectName(sqlInstance mssqlInstance, collector // mssqlGetPerfObjectName returns the name of the Windows Performance // Counter object for the given SQL instance and Collector. -func (c *Collector) collect( +func (c *Collector) collect[T any]( ch chan<- prometheus.Metric, collector string, - perfDataCollectors map[mssqlInstance]*pdh.Collector, - collectFn func(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error, + perfDataCollectors map[mssqlInstance]*pdh.Collector[T], + collectFn func(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[T]) error, ) error { errs := make([]error, 0, len(perfDataCollectors)) diff --git a/internal/collector/mssql/mssql_access_methods.go b/internal/collector/mssql/mssql_access_methods.go index 2267ce04..a89f62e2 100644 --- a/internal/collector/mssql/mssql_access_methods.go +++ b/internal/collector/mssql/mssql_access_methods.go @@ -27,7 +27,7 @@ import ( ) type collectorAccessMethods struct { - accessMethodsPerfDataCollectors map[mssqlInstance]*pdh.Collector + accessMethodsPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesAccessMethods] accessMethodsPerfDataObject []perfDataCounterValuesAccessMethods accessMethodsAUcleanupbatches *prometheus.Desc @@ -126,7 +126,7 @@ type perfDataCounterValuesAccessMethods struct { func (c *Collector) buildAccessMethods() error { var err error - c.accessMethodsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.accessMethodsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesAccessMethods], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -409,7 +409,7 @@ func (c *Collector) collectAccessMethods(ch chan<- prometheus.Metric) error { return c.collect(ch, subCollectorAccessMethods, c.accessMethodsPerfDataCollectors, c.collectAccessMethodsInstance) } -func (c *Collector) collectAccessMethodsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectAccessMethodsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesAccessMethods]) error { err := perfDataCollector.Collect(&c.accessMethodsPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "AccessMethods"), err) diff --git a/internal/collector/mssql/mssql_availability_replica.go b/internal/collector/mssql/mssql_availability_replica.go index c9ff2aa1..bfde0e6d 100644 --- a/internal/collector/mssql/mssql_availability_replica.go +++ b/internal/collector/mssql/mssql_availability_replica.go @@ -28,7 +28,7 @@ import ( ) type collectorAvailabilityReplica struct { - availabilityReplicaPerfDataCollectors map[mssqlInstance]*pdh.Collector + availabilityReplicaPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesAvailabilityReplica] availabilityReplicaPerfDataObject []perfDataCounterValuesAvailabilityReplica availReplicaBytesReceivedFromReplica *prometheus.Desc @@ -59,7 +59,7 @@ type perfDataCounterValuesAvailabilityReplica struct { func (c *Collector) buildAvailabilityReplica() error { var err error - c.availabilityReplicaPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.availabilityReplicaPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesAvailabilityReplica], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -132,7 +132,7 @@ func (c *Collector) collectAvailabilityReplica(ch chan<- prometheus.Metric) erro return c.collect(ch, subCollectorAvailabilityReplica, c.availabilityReplicaPerfDataCollectors, c.collectAvailabilityReplicaInstance) } -func (c *Collector) collectAvailabilityReplicaInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectAvailabilityReplicaInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesAvailabilityReplica]) error { err := perfDataCollector.Collect(&c.availabilityReplicaPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Availability Replica"), err) diff --git a/internal/collector/mssql/mssql_buffer_manager.go b/internal/collector/mssql/mssql_buffer_manager.go index f4a67ba0..1cad88a9 100644 --- a/internal/collector/mssql/mssql_buffer_manager.go +++ b/internal/collector/mssql/mssql_buffer_manager.go @@ -27,7 +27,7 @@ import ( ) type collectorBufferManager struct { - bufManPerfDataCollectors map[mssqlInstance]*pdh.Collector + bufManPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesBufMan] bufManPerfDataObject []perfDataCounterValuesBufMan bufManBackgroundwriterpages *prometheus.Desc @@ -84,7 +84,7 @@ type perfDataCounterValuesBufMan struct { func (c *Collector) buildBufferManager() error { var err error - c.bufManPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.bufManPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesBufMan], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -240,7 +240,7 @@ func (c *Collector) collectBufferManager(ch chan<- prometheus.Metric) error { return c.collect(ch, subCollectorBufferManager, c.bufManPerfDataCollectors, c.collectBufferManagerInstance) } -func (c *Collector) collectBufferManagerInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectBufferManagerInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesBufMan]) error { err := perfDataCollector.Collect(&c.bufManPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Buffer Manager"), err) diff --git a/internal/collector/mssql/mssql_database.go b/internal/collector/mssql/mssql_database.go index ed90f544..51612d96 100644 --- a/internal/collector/mssql/mssql_database.go +++ b/internal/collector/mssql/mssql_database.go @@ -27,8 +27,8 @@ import ( ) type collectorDatabases struct { - databasesPerfDataCollectors map[mssqlInstance]*pdh.Collector - databasesPerfDataCollectors2019 map[mssqlInstance]*pdh.Collector + databasesPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesDatabases] + databasesPerfDataCollectors2019 map[mssqlInstance]*pdh.Collector[perfDataCounterValuesDatabases2019] databasesPerfDataObject []perfDataCounterValuesDatabases databasesPerfDataObject2019 []perfDataCounterValuesDatabases2019 @@ -143,8 +143,8 @@ type perfDataCounterValuesDatabases2019 struct { func (c *Collector) buildDatabases() error { var err error - c.databasesPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) - c.databasesPerfDataCollectors2019 = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.databasesPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesDatabases], len(c.mssqlInstances)) + c.databasesPerfDataCollectors2019 = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesDatabases2019], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -460,7 +460,7 @@ func (c *Collector) collectDatabases(ch chan<- prometheus.Metric) error { ) } -func (c *Collector) collectDatabasesInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectDatabasesInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesDatabases]) error { err := perfDataCollector.Collect(&c.databasesPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Databases"), err) @@ -800,7 +800,7 @@ func (c *Collector) collectDatabasesInstance(ch chan<- prometheus.Metric, sqlIns return nil } -func (c *Collector) collectDatabasesInstance2019(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectDatabasesInstance2019(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesDatabases2019]) error { err := perfDataCollector.Collect(&c.databasesPerfDataObject2019) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Databases"), err) diff --git a/internal/collector/mssql/mssql_database_replica.go b/internal/collector/mssql/mssql_database_replica.go index 72b3cfc9..5fe47224 100644 --- a/internal/collector/mssql/mssql_database_replica.go +++ b/internal/collector/mssql/mssql_database_replica.go @@ -27,7 +27,7 @@ import ( ) type collectorDatabaseReplica struct { - dbReplicaPerfDataCollectors map[mssqlInstance]*pdh.Collector + dbReplicaPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesDBReplica] dbReplicaPerfDataObject []perfDataCounterValuesDBReplica dbReplicaDatabaseFlowControlDelay *prometheus.Desc @@ -88,7 +88,7 @@ type perfDataCounterValuesDBReplica struct { func (c *Collector) buildDatabaseReplica() error { var err error - c.dbReplicaPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.dbReplicaPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesDBReplica], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -251,7 +251,7 @@ func (c *Collector) collectDatabaseReplica(ch chan<- prometheus.Metric) error { return c.collect(ch, subCollectorDatabaseReplica, c.dbReplicaPerfDataCollectors, c.collectDatabaseReplicaInstance) } -func (c *Collector) collectDatabaseReplicaInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectDatabaseReplicaInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesDBReplica]) error { err := perfDataCollector.Collect(&c.dbReplicaPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Database Replica"), err) diff --git a/internal/collector/mssql/mssql_general_statistics.go b/internal/collector/mssql/mssql_general_statistics.go index d2bdc1f9..1b8c6ea6 100644 --- a/internal/collector/mssql/mssql_general_statistics.go +++ b/internal/collector/mssql/mssql_general_statistics.go @@ -27,7 +27,7 @@ import ( ) type collectorGeneralStatistics struct { - genStatsPerfDataCollectors map[mssqlInstance]*pdh.Collector + genStatsPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesGenStats] genStatsPerfDataObject []perfDataCounterValuesGenStats genStatsActiveTempTables *prometheus.Desc @@ -86,7 +86,7 @@ type perfDataCounterValuesGenStats struct { func (c *Collector) buildGeneralStatistics() error { var err error - c.genStatsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.genStatsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesGenStats], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -249,7 +249,7 @@ func (c *Collector) collectGeneralStatistics(ch chan<- prometheus.Metric) error return c.collect(ch, subCollectorGeneralStatistics, c.genStatsPerfDataCollectors, c.collectGeneralStatisticsInstance) } -func (c *Collector) collectGeneralStatisticsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectGeneralStatisticsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesGenStats]) error { err := perfDataCollector.Collect(&c.genStatsPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "General Statistics"), err) diff --git a/internal/collector/mssql/mssql_locks.go b/internal/collector/mssql/mssql_locks.go index 8f72e0c1..eded127f 100644 --- a/internal/collector/mssql/mssql_locks.go +++ b/internal/collector/mssql/mssql_locks.go @@ -27,7 +27,7 @@ import ( ) type collectorLocks struct { - locksPerfDataCollectors map[mssqlInstance]*pdh.Collector + locksPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesLocks] locksPerfDataObject []perfDataCounterValuesLocks // Win32_PerfRawData_{instance}_SQLServerLocks @@ -57,7 +57,7 @@ type perfDataCounterValuesLocks struct { func (c *Collector) buildLocks() error { var err error - c.locksPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.locksPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesLocks], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -123,7 +123,7 @@ func (c *Collector) collectLocks(ch chan<- prometheus.Metric) error { return c.collect(ch, subCollectorLocks, c.locksPerfDataCollectors, c.collectLocksInstance) } -func (c *Collector) collectLocksInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectLocksInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesLocks]) error { err := perfDataCollector.Collect(&c.locksPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Locks"), err) diff --git a/internal/collector/mssql/mssql_memory_manager.go b/internal/collector/mssql/mssql_memory_manager.go index d34d3715..58ad692c 100644 --- a/internal/collector/mssql/mssql_memory_manager.go +++ b/internal/collector/mssql/mssql_memory_manager.go @@ -27,7 +27,7 @@ import ( ) type collectorMemoryManager struct { - memMgrPerfDataCollectors map[mssqlInstance]*pdh.Collector + memMgrPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesMemMgr] memMgrPerfDataObject []perfDataCounterValuesMemMgr memMgrConnectionMemoryKB *prometheus.Desc @@ -78,7 +78,7 @@ type perfDataCounterValuesMemMgr struct { func (c *Collector) buildMemoryManager() error { var err error - c.memMgrPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.memMgrPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesMemMgr], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -216,7 +216,7 @@ func (c *Collector) collectMemoryManager(ch chan<- prometheus.Metric) error { return c.collect(ch, subCollectorMemoryManager, c.memMgrPerfDataCollectors, c.collectMemoryManagerInstance) } -func (c *Collector) collectMemoryManagerInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectMemoryManagerInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesMemMgr]) error { err := perfDataCollector.Collect(&c.memMgrPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Memory Manager"), err) diff --git a/internal/collector/mssql/mssql_sql_errors.go b/internal/collector/mssql/mssql_sql_errors.go index 82313a49..5f539db2 100644 --- a/internal/collector/mssql/mssql_sql_errors.go +++ b/internal/collector/mssql/mssql_sql_errors.go @@ -27,7 +27,7 @@ import ( ) type collectorSQLErrors struct { - sqlErrorsPerfDataCollectors map[mssqlInstance]*pdh.Collector + sqlErrorsPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesSqlErrors] sqlErrorsPerfDataObject []perfDataCounterValuesSqlErrors // Win32_PerfRawData_{instance}_SQLServerSQLErrors @@ -43,7 +43,7 @@ type perfDataCounterValuesSqlErrors struct { func (c *Collector) buildSQLErrors() error { var err error - c.sqlErrorsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.sqlErrorsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesSqlErrors], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -68,7 +68,7 @@ func (c *Collector) collectSQLErrors(ch chan<- prometheus.Metric) error { return c.collect(ch, subCollectorSQLErrors, c.sqlErrorsPerfDataCollectors, c.collectSQLErrorsInstance) } -func (c *Collector) collectSQLErrorsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectSQLErrorsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesSqlErrors]) error { err := perfDataCollector.Collect(&c.sqlErrorsPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "SQL Errors"), err) diff --git a/internal/collector/mssql/mssql_sql_stats.go b/internal/collector/mssql/mssql_sql_stats.go index a3c46b14..3868cf41 100644 --- a/internal/collector/mssql/mssql_sql_stats.go +++ b/internal/collector/mssql/mssql_sql_stats.go @@ -27,7 +27,7 @@ import ( ) type collectorSQLStats struct { - sqlStatsPerfDataCollectors map[mssqlInstance]*pdh.Collector + sqlStatsPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesSqlStats] sqlStatsPerfDataObject []perfDataCounterValuesSqlStats sqlStatsAutoParamAttempts *prometheus.Desc @@ -60,7 +60,7 @@ type perfDataCounterValuesSqlStats struct { func (c *Collector) buildSQLStats() error { var err error - c.sqlStatsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.sqlStatsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesSqlStats], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -144,7 +144,7 @@ func (c *Collector) collectSQLStats(ch chan<- prometheus.Metric) error { return c.collect(ch, subCollectorSQLStats, c.sqlStatsPerfDataCollectors, c.collectSQLStatsInstance) } -func (c *Collector) collectSQLStatsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectSQLStatsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesSqlStats]) error { err := perfDataCollector.Collect(&c.sqlStatsPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "SQL Statistics"), err) diff --git a/internal/collector/mssql/mssql_transactions.go b/internal/collector/mssql/mssql_transactions.go index 057a3467..42bdf8e8 100644 --- a/internal/collector/mssql/mssql_transactions.go +++ b/internal/collector/mssql/mssql_transactions.go @@ -27,7 +27,7 @@ import ( ) type collectorTransactions struct { - transactionsPerfDataCollectors map[mssqlInstance]*pdh.Collector + transactionsPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesTransactions] transactionsPerfDataObject []perfDataCounterValuesTransactions transactionsTempDbFreeSpaceBytes *prometheus.Desc @@ -64,7 +64,7 @@ type perfDataCounterValuesTransactions struct { func (c *Collector) buildTransactions() error { var err error - c.transactionsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.transactionsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesTransactions], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -162,7 +162,7 @@ func (c *Collector) collectTransactions(ch chan<- prometheus.Metric) error { // Win32_PerfRawData_MSSQLSERVER_Transactions docs: // - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-transactions-object -func (c *Collector) collectTransactionsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectTransactionsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesTransactions]) error { err := perfDataCollector.Collect(&c.transactionsPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Transactions"), err) diff --git a/internal/collector/mssql/mssql_wait_stats.go b/internal/collector/mssql/mssql_wait_stats.go index 24353a1a..311631fc 100644 --- a/internal/collector/mssql/mssql_wait_stats.go +++ b/internal/collector/mssql/mssql_wait_stats.go @@ -27,7 +27,7 @@ import ( ) type collectorWaitStats struct { - waitStatsPerfDataCollectors map[mssqlInstance]*pdh.Collector + waitStatsPerfDataCollectors map[mssqlInstance]*pdh.Collector[perfDataCounterValuesWaitStats] waitStatsPerfDataObject []perfDataCounterValuesWaitStats waitStatsLockWaits *prometheus.Desc @@ -64,7 +64,7 @@ type perfDataCounterValuesWaitStats struct { func (c *Collector) buildWaitStats() error { var err error - c.waitStatsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector, len(c.mssqlInstances)) + c.waitStatsPerfDataCollectors = make(map[mssqlInstance]*pdh.Collector[perfDataCounterValuesWaitStats], len(c.mssqlInstances)) errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { @@ -155,7 +155,7 @@ func (c *Collector) collectWaitStats(ch chan<- prometheus.Metric) error { return c.collect(ch, subCollectorWaitStats, c.waitStatsPerfDataCollectors, c.collectWaitStatsInstance) } -func (c *Collector) collectWaitStatsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector) error { +func (c *Collector) collectWaitStatsInstance(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesWaitStats]) error { err := perfDataCollector.Collect(&c.waitStatsPerfDataObject) if err != nil { return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Wait Statistics"), err) diff --git a/internal/collector/net/net.go b/internal/collector/net/net.go index bac69165..33f2a914 100644 --- a/internal/collector/net/net.go +++ b/internal/collector/net/net.go @@ -63,7 +63,7 @@ var ConfigDefaults = Config{ type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues bytesReceivedTotal *prometheus.Desc diff --git a/internal/collector/nps/nps.go b/internal/collector/nps/nps.go index 7fe86614..26757340 100644 --- a/internal/collector/nps/nps.go +++ b/internal/collector/nps/nps.go @@ -40,7 +40,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - accessPerfDataCollector *pdh.Collector + accessPerfDataCollector *pdh.Collector[perfDataCounterValuesAccess] accessPerfDataObject []perfDataCounterValuesAccess accessAccepts *prometheus.Desc accessChallenges *prometheus.Desc @@ -56,7 +56,7 @@ type Collector struct { accessServerUpTime *prometheus.Desc accessUnknownType *prometheus.Desc - accountingPerfDataCollector *pdh.Collector + accountingPerfDataCollector *pdh.Collector[perfDataCounterValuesAccounting] accountingPerfDataObject []perfDataCounterValuesAccounting accountingRequests *prometheus.Desc accountingResponses *prometheus.Desc diff --git a/internal/collector/pagefile/pagefile.go b/internal/collector/pagefile/pagefile.go index 3ee884e1..b138f1f2 100644 --- a/internal/collector/pagefile/pagefile.go +++ b/internal/collector/pagefile/pagefile.go @@ -43,7 +43,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues pagingFreeBytes *prometheus.Desc diff --git a/internal/collector/performancecounter/performancecounter.go b/internal/collector/performancecounter/performancecounter.go index 3a6616ed..fddd81b3 100644 --- a/internal/collector/performancecounter/performancecounter.go +++ b/internal/collector/performancecounter/performancecounter.go @@ -22,10 +22,8 @@ import ( "fmt" "log/slog" "maps" - "reflect" "regexp" "slices" - "strconv" "strings" "time" @@ -153,8 +151,8 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { names = append(names, object.Name) counters := make([]Counter, 0, len(object.Counters)) - fields := make([]reflect.StructField, 0, len(object.Counters)+2) - object.fieldIndex = make(map[string]int, len(object.Counters)) + counterNames := make([]string, 0, len(object.Counters)) + object.valueIndex = make(map[string]int, len(object.Counters)) for j, counter := range object.Counters { if counter.Metric == "" { @@ -170,7 +168,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { continue } - if _, ok := object.fieldIndex[counter.Name]; ok { + if _, ok := object.valueIndex[counter.Name]; ok { errs = append(errs, fmt.Errorf("object %s: counter name %s is duplicated", object.Name, counter.Name)) continue @@ -188,35 +186,15 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { counters = append(counters, counter) - // Counter names are free text and may produce invalid or colliding Go identifiers, - // so the struct fields get synthetic names and are looked up by index instead. - object.fieldIndex[counter.Name] = len(fields) - fields = append(fields, reflect.StructField{ - Name: "F" + strconv.Itoa(len(fields)), - Type: reflect.TypeFor[float64](), - Tag: reflect.StructTag(`perfdata:` + strconv.Quote(counter.Name)), - }) + object.valueIndex[counter.Name] = len(counterNames) + counterNames = append(counterNames, counter.Name) } - if object.Instances != nil { - fields = append(fields, reflect.StructField{ - Name: "Name", - Type: reflect.TypeFor[string](), - }) - } - - fields = append(fields, reflect.StructField{ - Name: "MetricType", - Type: reflect.TypeFor[prometheus.ValueType](), - }) - - valueType := reflect.StructOf(fields) - if object.Type == "" { object.Type = pdh.CounterTypeRaw } - collector, err := pdh.NewCollectorWithReflection(c.logger, object.Type, object.Object, object.Instances, valueType) + collector, err := pdh.NewDynamicCollector(c.logger, object.Type, object.Object, object.Instances, counterNames) if err != nil { errs = append(errs, fmt.Errorf("failed collector for %s: %w", object.Name, err)) } @@ -226,7 +204,6 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { } object.collector = collector - object.perfDataObject = reflect.New(reflect.SliceOf(valueType)).Interface() c.objects = append(c.objects, object) } @@ -288,69 +265,31 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error } func (c *Collector) collectObject(ch chan<- prometheus.Metric, perfDataObject Object) error { - err := perfDataObject.collector.Collect(perfDataObject.perfDataObject) + var rows []pdh.Row + + err := perfDataObject.collector.Collect(&rows) if err != nil { return fmt.Errorf("failed to collect data: %w", err) } var errs []error - sliceValue := reflect.ValueOf(perfDataObject.perfDataObject).Elem().Interface() - for i := range reflect.ValueOf(sliceValue).Len() { + for _, row := range rows { for _, counter := range perfDataObject.Counters { - val := reflect.ValueOf(sliceValue).Index(i) - - fieldIndex, ok := perfDataObject.fieldIndex[counter.Name] + valueIndex, ok := perfDataObject.valueIndex[counter.Name] if !ok { errs = append(errs, fmt.Errorf("%s not found in collected data", counter.Name)) continue } - field := val.Field(fieldIndex) - if field.Kind() != reflect.Float64 { - errs = append(errs, fmt.Errorf("failed to cast %s to float64", counter.Name)) - - continue - } - - collectedCounterValue := field.Float() - - field = val.FieldByName("MetricType") - if !field.IsValid() { - errs = append(errs, errors.New("field MetricType not found in collected data")) - - continue - } - - if field.Type() != reflect.TypeFor[prometheus.ValueType]() { - errs = append(errs, fmt.Errorf("failed to cast MetricType for %s to prometheus.ValueType", counter.Name)) - - continue - } - - metricType, _ := reflect.TypeAssert[prometheus.ValueType](field) + collectedCounterValue := row.Values[valueIndex] + metricType := row.MetricType labels := make(prometheus.Labels, len(counter.Labels)+1) - if perfDataObject.Instances != nil { - field := val.FieldByName("Name") - if !field.IsValid() { - errs = append(errs, errors.New("field Name not found in collected data")) - - continue - } - - if field.Kind() != reflect.String { - errs = append(errs, fmt.Errorf("failed to cast Name for %s to string", counter.Name)) - - continue - } - - collectedInstance := field.String() - if collectedInstance != pdh.InstanceEmpty { - labels[perfDataObject.InstanceLabel] = collectedInstance - } + if perfDataObject.Instances != nil && row.Name != pdh.InstanceEmpty { + labels[perfDataObject.InstanceLabel] = row.Name } maps.Copy(labels, counter.Labels) diff --git a/internal/collector/performancecounter/types.go b/internal/collector/performancecounter/types.go index 70931bb0..44d317fa 100644 --- a/internal/collector/performancecounter/types.go +++ b/internal/collector/performancecounter/types.go @@ -30,10 +30,9 @@ type Object struct { Counters []Counter `json:"counters" yaml:"counters"` InstanceLabel string `json:"instance_label" yaml:"instance_label"` - collector *pdh.Collector - perfDataObject any - // fieldIndex maps a counter name to its field index in the element type of perfDataObject. - fieldIndex map[string]int + collector *pdh.Collector[pdh.Row] + // valueIndex maps a counter name to its index in pdh.Row.Values. + valueIndex map[string]int } type Counter struct { diff --git a/internal/collector/physical_disk/physical_disk.go b/internal/collector/physical_disk/physical_disk.go index 1bf6f44f..c878f2f9 100644 --- a/internal/collector/physical_disk/physical_disk.go +++ b/internal/collector/physical_disk/physical_disk.go @@ -48,7 +48,7 @@ var ConfigDefaults = Config{ type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues idleTime *prometheus.Desc diff --git a/internal/collector/process/process.go b/internal/collector/process/process.go index 5d37e674..454a98aa 100644 --- a/internal/collector/process/process.go +++ b/internal/collector/process/process.go @@ -66,7 +66,7 @@ type Collector struct { miSession *mi.Session workerProcessMIQueryQuery mi.Query - perfDataCollector pdhtypes.Collector + perfDataCollector pdhtypes.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues workerCh chan processWorkerRequest diff --git a/internal/collector/remote_fx/remote_fx.go b/internal/collector/remote_fx/remote_fx.go index b239285b..10042ee3 100644 --- a/internal/collector/remote_fx/remote_fx.go +++ b/internal/collector/remote_fx/remote_fx.go @@ -47,9 +47,9 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollectorNetwork *pdh.Collector + perfDataCollectorNetwork *pdh.Collector[perfDataCounterValuesNetwork] perfDataObjectNetwork []perfDataCounterValuesNetwork - perfDataCollectorGraphics *pdh.Collector + perfDataCollectorGraphics *pdh.Collector[perfDataCounterValuesGraphics] perfDataObjectGraphics []perfDataCounterValuesGraphics // net diff --git a/internal/collector/smb/smb.go b/internal/collector/smb/smb.go index 0d00f465..b4c28947 100644 --- a/internal/collector/smb/smb.go +++ b/internal/collector/smb/smb.go @@ -39,7 +39,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues treeConnectCount *prometheus.Desc diff --git a/internal/collector/smbclient/smbclient.go b/internal/collector/smbclient/smbclient.go index 0fc522c1..70990397 100644 --- a/internal/collector/smbclient/smbclient.go +++ b/internal/collector/smbclient/smbclient.go @@ -42,7 +42,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues readBytesTotal *prometheus.Desc diff --git a/internal/collector/smtp/smtp.go b/internal/collector/smtp/smtp.go index 7c832769..004b01aa 100644 --- a/internal/collector/smtp/smtp.go +++ b/internal/collector/smtp/smtp.go @@ -46,7 +46,7 @@ var ConfigDefaults = Config{ type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues badMailedMessagesBadPickupFileTotal *prometheus.Desc diff --git a/internal/collector/system/system.go b/internal/collector/system/system.go index d0bf559e..93a8963e 100644 --- a/internal/collector/system/system.go +++ b/internal/collector/system/system.go @@ -43,7 +43,7 @@ type Collector struct { bootTimeTimestamp float64 - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues contextSwitchesTotal *prometheus.Desc diff --git a/internal/collector/tcp/tcp.go b/internal/collector/tcp/tcp.go index b947925e..53a87546 100644 --- a/internal/collector/tcp/tcp.go +++ b/internal/collector/tcp/tcp.go @@ -60,8 +60,8 @@ var ConfigDefaults = Config{ type Collector struct { config Config - perfDataCollector4 *pdh.Collector - perfDataCollector6 *pdh.Collector + perfDataCollector4 *pdh.Collector[perfDataCounterValues] + perfDataCollector6 *pdh.Collector[perfDataCounterValues] perfDataObject4 []perfDataCounterValues perfDataObject6 []perfDataCounterValues diff --git a/internal/collector/terminal_services/terminal_services.go b/internal/collector/terminal_services/terminal_services.go index 13b3158c..c47912c3 100644 --- a/internal/collector/terminal_services/terminal_services.go +++ b/internal/collector/terminal_services/terminal_services.go @@ -75,8 +75,8 @@ type Collector struct { connectionBrokerEnabled bool - perfDataCollectorTerminalServicesSession *pdh.Collector - perfDataCollectorBroker *pdh.Collector + perfDataCollectorTerminalServicesSession *pdh.Collector[perfDataCounterValuesTerminalServicesSession] + perfDataCollectorBroker *pdh.Collector[perfDataCounterValuesBroker] perfDataObjectTerminalServicesSession []perfDataCounterValuesTerminalServicesSession perfDataObjectBroker []perfDataCounterValuesBroker diff --git a/internal/collector/thermalzone/thermalzone.go b/internal/collector/thermalzone/thermalzone.go index aca704f8..f0594a7d 100644 --- a/internal/collector/thermalzone/thermalzone.go +++ b/internal/collector/thermalzone/thermalzone.go @@ -40,7 +40,7 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues percentPassiveLimit *prometheus.Desc diff --git a/internal/collector/time/time.go b/internal/collector/time/time.go index a475f96f..7f62dd0f 100644 --- a/internal/collector/time/time.go +++ b/internal/collector/time/time.go @@ -61,7 +61,7 @@ var ConfigDefaults = Config{ type Collector struct { config Config - perfDataCollector *pdh.Collector + perfDataCollector *pdh.Collector[perfDataCounterValues] perfDataObject []perfDataCounterValues logger *slog.Logger diff --git a/internal/collector/udp/udp.go b/internal/collector/udp/udp.go index 6cd56d56..d534b363 100644 --- a/internal/collector/udp/udp.go +++ b/internal/collector/udp/udp.go @@ -41,8 +41,8 @@ var ConfigDefaults = Config{} type Collector struct { config Config - perfDataCollector4 *pdh.Collector - perfDataCollector6 *pdh.Collector + perfDataCollector4 *pdh.Collector[perfDataCounterValues] + perfDataCollector6 *pdh.Collector[perfDataCounterValues] perfDataObject4 []perfDataCounterValues perfDataObject6 []perfDataCounterValues diff --git a/internal/collector/vmware/vmware.go b/internal/collector/vmware/vmware.go index 3ebb1f45..2f35e9a3 100644 --- a/internal/collector/vmware/vmware.go +++ b/internal/collector/vmware/vmware.go @@ -41,8 +41,8 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics. type Collector struct { config Config - perfDataCollectorCPU *pdh.Collector - perfDataCollectorMemory *pdh.Collector + perfDataCollectorCPU *pdh.Collector[perfDataCounterValuesCPU] + perfDataCollectorMemory *pdh.Collector[perfDataCounterValuesMemory] perfDataObjectCPU []perfDataCounterValuesCPU perfDataObjectMemory []perfDataCounterValuesMemory diff --git a/internal/pdh/collector.go b/internal/pdh/collector.go index 285e5bef..9f90d230 100644 --- a/internal/pdh/collector.go +++ b/internal/pdh/collector.go @@ -28,7 +28,6 @@ import ( "sync" "unsafe" - "github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/osversion" "github.com/prometheus/client_golang/prometheus" "golang.org/x/sys/windows" @@ -42,7 +41,7 @@ var ( type CounterValues = map[string]map[string]CounterValue -type Collector struct { +type Collector[T any] struct { object string counters map[string]Counter handle pdhQueryHandle @@ -50,13 +49,35 @@ type Collector struct { mu sync.RWMutex logger *slog.Logger - nameIndexValue int - metricsTypeIndexValue int + rows rowAccessor[T] - collectCh chan any + collectCh chan *[]T errorCh chan error } +// Row holds the values of one instance collected by a collector from [NewDynamicCollector]. +type Row struct { + Name string + MetricType prometheus.ValueType + // Values holds one value per counter, in the order the counters were passed to [NewDynamicCollector]. + Values []float64 +} + +// rowAccessor creates rows of type T and sets their counter values. +// field is the index the counterField of the counter was created with. +type rowAccessor[T any] struct { + newRow func(instance string, metricType prometheus.ValueType) T + setValue func(row *T, field int, value float64) +} + +// counterField maps a counter to the field index passed to rowAccessor.setValue. +type counterField struct { + // tag is the counter name, optionally suffixed with ",secondvalue". + tag string + index int + minOSBuild string +} + type Counter struct { Name string Desc string @@ -69,13 +90,96 @@ type Counter struct { FieldIndexSecondValue int } -func NewCollector[T any](logger *slog.Logger, resultType CounterType, object string, instances []string) (*Collector, error) { +// NewCollector creates a collector for the counters declared by the perfdata tags of the struct T. +// +// The optional fields Name (string) and MetricType (prometheus.ValueType) of T +// receive the instance name and the metric type of the counter. +func NewCollector[T any](logger *slog.Logger, resultType CounterType, object string, instances []string) (*Collector[T], error) { valueType := reflect.TypeFor[T]() + if valueType.Kind() != reflect.Struct { + return nil, fmt.Errorf("expected a struct, got %s", valueType) + } - return NewCollectorWithReflection(logger, resultType, object, instances, valueType) + nameIndex, metricTypeIndex := -1, -1 + + if f, ok := valueType.FieldByName("Name"); ok && f.Type.Kind() == reflect.String { + nameIndex = f.Index[0] + } + + if f, ok := valueType.FieldByName("MetricType"); ok && f.Type == reflect.TypeFor[prometheus.ValueType]() { + metricTypeIndex = f.Index[0] + } + + var errs []error + + fields := make([]counterField, 0, valueType.NumField()) + + for _, f := range reflect.VisibleFields(valueType) { + counterName, ok := f.Tag.Lookup("perfdata") + if !ok { + continue + } + + if f.Type.Kind() != reflect.Float64 { + errs = append(errs, fmt.Errorf("field %s must be a float64", f.Name)) + + continue + } + + fields = append(fields, counterField{ + tag: counterName, + index: f.Index[0], + minOSBuild: f.Tag.Get("perfdata_min_build"), + }) + } + + rows := rowAccessor[T]{ + newRow: func(instance string, metricType prometheus.ValueType) T { + var row T + + rv := reflect.ValueOf(&row).Elem() + + if nameIndex != -1 { + rv.Field(nameIndex).SetString(instance) + } + + if metricTypeIndex != -1 { + rv.Field(metricTypeIndex).SetInt(int64(metricType)) + } + + return row + }, + setValue: func(row *T, field int, value float64) { + reflect.ValueOf(row).Elem().Field(field).SetFloat(value) + }, + } + + return newCollector(logger, resultType, object, instances, fields, rows, errs) } -func NewCollectorWithReflection(logger *slog.Logger, resultType CounterType, object string, instances []string, valueType reflect.Type) (*Collector, error) { +// NewDynamicCollector creates a collector for counters that are only known at runtime. +// Row.Values of the collected rows holds one value per entry of counters, in the same order. +func NewDynamicCollector(logger *slog.Logger, resultType CounterType, object string, instances []string, counters []string) (*Collector[Row], error) { + fields := make([]counterField, len(counters)) + for i, counter := range counters { + fields[i] = counterField{tag: counter, index: i} + } + + rows := rowAccessor[Row]{ + newRow: func(instance string, metricType prometheus.ValueType) Row { + return Row{Name: instance, MetricType: metricType, Values: make([]float64, len(counters))} + }, + setValue: func(row *Row, field int, value float64) { + row.Values[field] = value + }, + } + + return newCollector(logger, resultType, object, instances, fields, rows, nil) +} + +func newCollector[T any](logger *slog.Logger, resultType CounterType, object string, instances []string, + fields []counterField, rows rowAccessor[T], errs []error, +) (*Collector[T], error) { var handle pdhQueryHandle if ret := OpenQuery(0, 0, &handle); ret != ErrorSuccess { @@ -90,50 +194,21 @@ func NewCollectorWithReflection(logger *slog.Logger, resultType CounterType, obj return nil, fmt.Errorf("invalid result type: %v", resultType) } - collector := &Collector{ + collector := &Collector[T]{ object: object, - counters: make(map[string]Counter, valueType.NumField()), + counters: make(map[string]Counter, len(fields)), handle: handle, totalCounterRequested: slices.Contains(instances, InstanceTotal), mu: sync.RWMutex{}, logger: logger, - nameIndexValue: -1, - metricsTypeIndexValue: -1, + rows: rows, } - errs := make([]error, 0, valueType.NumField()) + for _, f := range fields { + counterName, secondValue := strings.CutSuffix(f.tag, ",secondvalue") - if f, ok := valueType.FieldByName("Name"); ok { - if f.Type.Kind() == reflect.String { - collector.nameIndexValue = f.Index[0] - } - } - - if f, ok := valueType.FieldByName("MetricType"); ok { - if f.Type == reflect.TypeFor[prometheus.ValueType]() { - collector.metricsTypeIndexValue = f.Index[0] - } - } - - for _, f := range reflect.VisibleFields(valueType) { - counterName, ok := f.Tag.Lookup("perfdata") + counter, ok := collector.counters[counterName] if !ok { - continue - } - - if f.Type.Kind() != reflect.Float64 { - errs = append(errs, fmt.Errorf("field %s must be a float64", f.Name)) - - continue - } - - secondValue := strings.HasSuffix(counterName, ",secondvalue") - if secondValue { - counterName = strings.TrimSuffix(counterName, ",secondvalue") - } - - var counter Counter - if counter, ok = collector.counters[counterName]; !ok { counter = Counter{ Name: counterName, Instances: make(map[string]pdhCounterHandle, len(instances)), @@ -143,9 +218,9 @@ func NewCollectorWithReflection(logger *slog.Logger, resultType CounterType, obj } if secondValue { - counter.FieldIndexSecondValue = f.Index[0] + counter.FieldIndexSecondValue = f.index } else { - counter.FieldIndexValue = f.Index[0] + counter.FieldIndexValue = f.index } if len(counter.Instances) != 0 { @@ -164,8 +239,8 @@ func NewCollectorWithReflection(logger *slog.Logger, resultType CounterType, obj //nolint:nestif if ret := AddEnglishCounter(handle, counterPath, 0, &counterHandle); ret != ErrorSuccess { if ret == CstatusNoCounter { - if minOSBuildTag, ok := f.Tag.Lookup("perfdata_min_build"); ok { - if minOSBuild, err := strconv.Atoi(minOSBuildTag); err == nil { + if f.minOSBuild != "" { + if minOSBuild, err := strconv.Atoi(f.minOSBuild); err == nil { if uint16(minOSBuild) > osversion.Build() { continue } @@ -240,7 +315,7 @@ func NewCollectorWithReflection(logger *slog.Logger, resultType CounterType, obj return nil, errors.New("no counters configured") } - collector.collectCh = make(chan any) + collector.collectCh = make(chan *[]T) collector.errorCh = make(chan error) if resultType == CounterTypeRaw { @@ -250,15 +325,15 @@ func NewCollectorWithReflection(logger *slog.Logger, resultType CounterType, obj } // Collect initial data because some counters need to be read twice to get the correct value. - collectValues := reflect.New(reflect.SliceOf(valueType)).Elem() - if err := collector.Collect(collectValues.Addr().Interface()); err != nil && !errors.Is(err, ErrNoData) { + var collectValues []T + if err := collector.Collect(&collectValues); err != nil && !errors.Is(err, ErrNoData) { return collector, fmt.Errorf("failed to collect initial data: %w", err) } return collector, nil } -func (c *Collector) Describe() map[string]string { +func (c *Collector[T]) Describe() map[string]string { if c == nil { return map[string]string{} } @@ -275,11 +350,16 @@ func (c *Collector) Describe() map[string]string { return desc } -func (c *Collector) Collect(dst any) error { +// Collect replaces the content of dst with one row per collected instance. +func (c *Collector[T]) Collect(dst *[]T) error { if c == nil { return ErrPerformanceCounterNotInitialized } + if dst == nil { + return errors.New("dst must not be nil") + } + c.mu.RLock() defer c.mu.RUnlock() @@ -292,7 +372,7 @@ func (c *Collector) Collect(dst any) error { return <-c.errorCh } -func (c *Collector) collectWorkerRaw() { +func (c *Collector[T]) collectWorkerRaw() { var ( err error itemCount uint32 @@ -305,36 +385,13 @@ func (c *Collector) collectWorkerRaw() { // which corrupts the neighboring heap memory of a tiny allocation. var buf []byte - for data := range c.collectCh { + for dst := range c.collectCh { err = (func() error { if ret := CollectQueryData(c.handle); ret != ErrorSuccess { return fmt.Errorf("failed to collect query data: %w", NewPdhError(ret)) } - dv := reflect.ValueOf(data) - if dv.Kind() != reflect.Pointer || dv.IsNil() { - return fmt.Errorf("expected a pointer, got %s: %w", dv.Kind(), mi.ErrInvalidEntityType) - } - - dv = dv.Elem() - - if dv.Kind() != reflect.Slice { - return fmt.Errorf("expected a pointer to a slice, got %s: %w", dv.Kind(), mi.ErrInvalidEntityType) - } - - elemType := dv.Type().Elem() - - if elemType.Kind() != reflect.Struct { - return fmt.Errorf("expected a pointer to a slice of structs, got a slice of %s: %w", elemType.Kind(), mi.ErrInvalidEntityType) - } - - if dv.Len() != 0 { - dv.Set(reflect.MakeSlice(dv.Type(), 0, 0)) - } - - dv.Clear() - - elemValue := reflect.ValueOf(reflect.New(elemType).Interface()).Elem() + *dst = (*dst)[:0:0] indexMap := map[string]int{} nameCache := map[string]string{} @@ -396,55 +453,41 @@ func (c *Collector) collectWorkerRaw() { ) if index, ok = indexMap[instanceName]; !ok { - index = dv.Len() + index = len(*dst) indexMap[instanceName] = index - if c.nameIndexValue != -1 { - elemValue.Field(c.nameIndexValue).SetString(instanceName) + var metricsType prometheus.ValueType + if metricsType, ok = SupportedCounterTypes[counter.Type]; !ok { + metricsType = prometheus.GaugeValue } - if c.metricsTypeIndexValue != -1 { - var metricsType prometheus.ValueType - if metricsType, ok = SupportedCounterTypes[counter.Type]; !ok { - metricsType = prometheus.GaugeValue - } - - elemValue.Field(c.metricsTypeIndexValue).Set(reflect.ValueOf(metricsType)) - } - - dv.Set(reflect.Append(dv, elemValue)) + *dst = append(*dst, c.rows.newRow(instanceName, metricsType)) } + row := &(*dst)[index] + // This is a workaround for the issue with the elapsed time counter type. // Source: https://github.com/prometheus-community/windows_exporter/pull/335/files#diff-d5d2528f559ba2648c2866aec34b1eaa5c094dedb52bd0ff22aa5eb83226bd8dR76-R83 // Ref: https://learn.microsoft.com/en-us/windows/win32/perfctrs/calculating-counter-values switch counter.Type { case PERF_ELAPSED_TIME: - dv.Index(index). - Field(counter.FieldIndexValue). - SetFloat(float64((item.RawValue.SecondValue - item.RawValue.FirstValue) / counter.Frequency)) + c.rows.setValue(row, counter.FieldIndexValue, float64((item.RawValue.SecondValue-item.RawValue.FirstValue)/counter.Frequency)) case PERF_100NSEC_TIMER, PERF_PRECISION_100NS_TIMER: - dv.Index(index). - Field(counter.FieldIndexValue). - SetFloat(float64(item.RawValue.FirstValue) * TicksToSecondScaleFactor) + c.rows.setValue(row, counter.FieldIndexValue, float64(item.RawValue.FirstValue)*TicksToSecondScaleFactor) default: if counter.FieldIndexSecondValue != -1 { - dv.Index(index). - Field(counter.FieldIndexSecondValue). - SetFloat(float64(item.RawValue.SecondValue)) + c.rows.setValue(row, counter.FieldIndexSecondValue, float64(item.RawValue.SecondValue)) } if counter.FieldIndexValue != -1 { - dv.Index(index). - Field(counter.FieldIndexValue). - SetFloat(float64(item.RawValue.FirstValue)) + c.rows.setValue(row, counter.FieldIndexValue, float64(item.RawValue.FirstValue)) } } } } } - if dv.Len() == 0 { + if len(*dst) == 0 { return ErrNoData } @@ -455,7 +498,7 @@ func (c *Collector) collectWorkerRaw() { } } -func (c *Collector) collectWorkerFormatted() { +func (c *Collector[T]) collectWorkerFormatted() { var ( err error itemCount uint32 @@ -467,36 +510,13 @@ func (c *Collector) collectWorkerFormatted() { // See collectWorkerRaw. var buf []byte - for data := range c.collectCh { + for dst := range c.collectCh { err = (func() error { if ret := CollectQueryData(c.handle); ret != ErrorSuccess { return fmt.Errorf("failed to collect query data: %w", NewPdhError(ret)) } - dv := reflect.ValueOf(data) - if dv.Kind() != reflect.Pointer || dv.IsNil() { - return fmt.Errorf("expected a pointer, got %s: %w", dv.Kind(), mi.ErrInvalidEntityType) - } - - dv = dv.Elem() - - if dv.Kind() != reflect.Slice { - return fmt.Errorf("expected a pointer to a slice, got %s: %w", dv.Kind(), mi.ErrInvalidEntityType) - } - - elemType := dv.Type().Elem() - - if elemType.Kind() != reflect.Struct { - return fmt.Errorf("expected a pointer to a slice of structs, got a slice of %s: %w", elemType.Kind(), mi.ErrInvalidEntityType) - } - - if dv.Len() != 0 { - dv.Set(reflect.MakeSlice(dv.Type(), 0, 0)) - } - - dv.Clear() - - elemValue := reflect.ValueOf(reflect.New(elemType).Interface()).Elem() + *dst = (*dst)[:0:0] indexMap := map[string]int{} nameCache := map[string]string{} @@ -552,30 +572,20 @@ func (c *Collector) collectWorkerFormatted() { ) if index, ok = indexMap[instanceName]; !ok { - index = dv.Len() + index = len(*dst) indexMap[instanceName] = index - if c.nameIndexValue != -1 { - elemValue.Field(c.nameIndexValue).SetString(instanceName) - } - - if c.metricsTypeIndexValue != -1 { - elemValue.Field(c.metricsTypeIndexValue).Set(reflect.ValueOf(prometheus.GaugeValue)) - } - - dv.Set(reflect.Append(dv, elemValue)) + *dst = append(*dst, c.rows.newRow(instanceName, prometheus.GaugeValue)) } if counter.FieldIndexValue != -1 { - dv.Index(index). - Field(counter.FieldIndexValue). - SetFloat(item.FmtValue.DoubleValue) + c.rows.setValue(&(*dst)[index], counter.FieldIndexValue, item.FmtValue.DoubleValue) } } } } - if dv.Len() == 0 { + if len(*dst) == 0 { return ErrNoData } @@ -586,7 +596,7 @@ func (c *Collector) collectWorkerFormatted() { } } -func (c *Collector) Close() { +func (c *Collector[T]) Close() { if c == nil { return } diff --git a/internal/pdh/collector_test.go b/internal/pdh/collector_test.go index 60937a91..05fb5cfd 100644 --- a/internal/pdh/collector_test.go +++ b/internal/pdh/collector_test.go @@ -135,3 +135,37 @@ func TestCollectorExplicitInstances(t *testing.T) { }) } } + +func TestNewCollectorNonStruct(t *testing.T) { + t.Parallel() + + _, err := pdh.NewCollector[int](slog.New(slog.DiscardHandler), pdh.CounterTypeRaw, "Process", pdh.InstancesAll) + require.Error(t, err) +} + +func TestDynamicCollector(t *testing.T) { + t.Parallel() + + counters := []string{"Thread Count", "Handle Count"} + + collector, err := pdh.NewDynamicCollector(slog.New(slog.DiscardHandler), pdh.CounterTypeRaw, "Process", pdh.InstancesAll, counters) + require.NoError(t, err) + + t.Cleanup(collector.Close) + + var data []pdh.Row + + require.NoError(t, collector.Collect(&data)) + require.NotEmpty(t, data) + + for _, row := range data { + require.NotEmpty(t, row.Name) + require.Len(t, row.Values, len(counters)) + + if row.Name == "Idle" || row.Name == "Secure System" { + continue + } + + require.NotZerof(t, row.Values[0], "instance: %s, counter: %s", row.Name, counters[0]) + } +} diff --git a/internal/pdh/registry/collector.go b/internal/pdh/registry/collector.go index 5409f0de..e8995b45 100644 --- a/internal/pdh/registry/collector.go +++ b/internal/pdh/registry/collector.go @@ -18,15 +18,15 @@ package registry import ( + "errors" "fmt" "reflect" "strings" - "github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/pdh" ) -type Collector struct { +type Collector[T any] struct { object string query string @@ -45,16 +45,20 @@ type Counter struct { FieldIndexSecondValue int } -func NewCollector[T any](object string, _ []string) (*Collector, error) { - collector := &Collector{ +// NewCollector creates a collector for the counters declared by the perfdata_v1 or perfdata tags of the struct T. +func NewCollector[T any](object string, _ []string) (*Collector[T], error) { + valueType := reflect.TypeFor[T]() + if valueType.Kind() != reflect.Struct { + return nil, fmt.Errorf("expected a struct, got %s", valueType) + } + + collector := &Collector[T]{ object: object, query: MapCounterToIndex(object), nameIndexValue: -1, counters: make(map[string]Counter), } - valueType := reflect.TypeFor[T]() - if f, ok := valueType.FieldByName("Name"); ok { if f.Type.Kind() == reflect.String { collector.nameIndexValue = f.Index[0] @@ -62,16 +66,22 @@ func NewCollector[T any](object string, _ []string) (*Collector, error) { } for _, f := range reflect.VisibleFields(valueType) { - counterName, ok := f.Tag.Lookup("perfdata_v1") + tag, ok := f.Tag.Lookup("perfdata_v1") if !ok { - counterName, ok = f.Tag.Lookup("perfdata") + tag, ok = f.Tag.Lookup("perfdata") if !ok { continue } } - var counter Counter - if counter, ok = collector.counters[counterName]; !ok { + if f.Type.Kind() != reflect.Float64 { + return nil, fmt.Errorf("field %s must be a float64", f.Name) + } + + counterName, secondValue := strings.CutSuffix(tag, ",secondvalue") + + counter, ok := collector.counters[counterName] + if !ok { counter = Counter{ Name: counterName, FieldIndexSecondValue: -1, @@ -79,7 +89,7 @@ func NewCollector[T any](object string, _ []string) (*Collector, error) { } } - if counterName, ok = strings.CutSuffix(counterName, ",secondvalue"); ok { + if secondValue { counter.FieldIndexSecondValue = f.Index[0] } else { counter.FieldIndexValue = f.Index[0] @@ -97,25 +107,16 @@ func NewCollector[T any](object string, _ []string) (*Collector, error) { return collector, nil } -func (c *Collector) Describe() map[string]string { +func (c *Collector[T]) Describe() map[string]string { return map[string]string{} } -func (c *Collector) Collect(data any) error { - dv := reflect.ValueOf(data) - if dv.Kind() != reflect.Pointer || dv.IsNil() { - return mi.ErrInvalidEntityType +// Collect replaces the content of dst with one row per collected instance. +func (c *Collector[T]) Collect(dst *[]T) error { + if dst == nil { + return errors.New("dst must not be nil") } - dv = dv.Elem() - - if dv.Kind() != reflect.Slice || dv.Type().Elem().Kind() != reflect.Struct { - return mi.ErrInvalidEntityType - } - - elemType := dv.Type().Elem() - elemValue := reflect.ValueOf(reflect.New(elemType).Interface()).Elem() - perfObjects, err := QueryPerformanceData(c.query, c.object) if err != nil { return fmt.Errorf("QueryPerformanceData: %w", err) @@ -125,11 +126,7 @@ func (c *Collector) Collect(data any) error { return nil } - if dv.Len() != 0 { - dv.Set(reflect.MakeSlice(dv.Type(), 0, len(perfObjects[0].Instances))) - } - - dv.Clear() + *dst = make([]T, 0, len(perfObjects[0].Instances)) for _, perfObject := range perfObjects { if perfObject.Name != c.object { @@ -146,12 +143,13 @@ func (c *Collector) Collect(data any) error { instanceName = pdh.InstanceEmpty } - if c.nameIndexValue != -1 { - elemValue.Field(c.nameIndexValue).SetString(instanceName) - } + var row T - dv.Set(reflect.Append(dv, elemValue)) - index := dv.Len() - 1 + rv := reflect.ValueOf(&row).Elem() + + if c.nameIndexValue != -1 { + rv.Field(c.nameIndexValue).SetString(instanceName) + } for _, perfCounter := range perfInstance.Counters { if perfCounter.Def.IsBaseValue && !perfCounter.Def.IsNanosecondCounter { @@ -165,31 +163,29 @@ func (c *Collector) Collect(data any) error { switch perfCounter.Def.CounterType { case pdh.PERF_ELAPSED_TIME: - dv.Index(index). - Field(counter.FieldIndexValue). + rv.Field(counter.FieldIndexValue). SetFloat(float64((perfCounter.Value - pdh.WindowsEpoch) / perfObject.Frequency)) case pdh.PERF_100NSEC_TIMER, pdh.PERF_PRECISION_100NS_TIMER: - dv.Index(index). - Field(counter.FieldIndexValue). + rv.Field(counter.FieldIndexValue). SetFloat(float64(perfCounter.Value) * pdh.TicksToSecondScaleFactor) default: if counter.FieldIndexSecondValue != -1 { - dv.Index(index). - Field(counter.FieldIndexSecondValue). + rv.Field(counter.FieldIndexSecondValue). SetFloat(float64(perfCounter.SecondValue)) } if counter.FieldIndexValue != -1 { - dv.Index(index). - Field(counter.FieldIndexValue). + rv.Field(counter.FieldIndexValue). SetFloat(float64(perfCounter.Value)) } } } + + *dst = append(*dst, row) } } return nil } -func (c *Collector) Close() {} +func (c *Collector[T]) Close() {} diff --git a/internal/pdh/registry/perflib_test.go b/internal/pdh/registry/perflib_test.go index cbd14f69..82c72212 100644 --- a/internal/pdh/registry/perflib_test.go +++ b/internal/pdh/registry/perflib_test.go @@ -18,10 +18,7 @@ package registry import ( - "errors" "testing" - - "github.com/prometheus-community/windows_exporter/internal/mi" ) // TestNewCollectorStructTypeParam guards against a regression where @@ -40,32 +37,25 @@ func TestNewCollectorStructTypeParam(t *testing.T) { } } -// TestCollectInvalidEntityType guards against a regression where Collect -// called reflect.Type.Elem() on a non-slice destination and panicked instead -// of returning mi.ErrInvalidEntityType. -func TestCollectInvalidEntityType(t *testing.T) { +// TestNewCollectorNonStruct guards against a regression where NewCollector +// panicked instead of returning an error for a type parameter that is not a struct. +func TestNewCollectorNonStruct(t *testing.T) { + t.Parallel() + + if _, err := NewCollector[int]("System", nil); err == nil { + t.Error("expected an error, got nil") + } +} + +func TestCollectNilDestination(t *testing.T) { t.Parallel() type counterValues struct { Name string } - c := &Collector{} - - for name, dst := range map[string]any{ - "nil": nil, - "non-pointer": []counterValues{}, - "pointer to struct": &counterValues{}, - "pointer to []int": &[]int{}, - "pointer to integer": new(int), - } { - t.Run(name, func(t *testing.T) { - t.Parallel() - - if err := c.Collect(dst); !errors.Is(err, mi.ErrInvalidEntityType) { - t.Errorf("expected %v, got %v", mi.ErrInvalidEntityType, err) - } - }) + if err := (&Collector[counterValues]{}).Collect(nil); err == nil { + t.Error("expected an error, got nil") } } diff --git a/internal/pdh/types/types.go b/internal/pdh/types/types.go index bf38ecce..e2d1ff72 100644 --- a/internal/pdh/types/types.go +++ b/internal/pdh/types/types.go @@ -17,7 +17,7 @@ package types -type Collector interface { - Collect(dst any) error +type Collector[T any] interface { + Collect(dst *[]T) error Close() }