mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-10-17 10:09:05 +02:00
pdh: make Collector generic over its row type (#2536)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c03d8db231
commit
3d2cdb810e
@@ -1,2 +1,2 @@
|
||||
[codespell]
|
||||
ignore-words-list = notin
|
||||
ignore-words-list = notin,entires
|
||||
|
||||
@@ -39,7 +39,7 @@ var ConfigDefaults = Config{}
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
addressBookClientSessions *prometheus.Desc
|
||||
|
||||
@@ -40,7 +40,7 @@ var ConfigDefaults = Config{}
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
challengeResponseProcessingTime *prometheus.Desc
|
||||
|
||||
@@ -40,7 +40,7 @@ var ConfigDefaults = Config{}
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
adLoginConnectionFailures *prometheus.Desc
|
||||
|
||||
Vendored
+1
-1
@@ -40,7 +40,7 @@ var ConfigDefaults = Config{}
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
asyncCopyReadsTotal *prometheus.Desc
|
||||
|
||||
@@ -41,7 +41,7 @@ var ConfigDefaults = Config{}
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
mu sync.Mutex
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -59,7 +59,7 @@ type Collector struct {
|
||||
|
||||
logger *slog.Logger
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
acksTotal *prometheus.Desc
|
||||
|
||||
@@ -54,7 +54,7 @@ var ConfigDefaults = Config{
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
miSession *mi.Session
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorActiveSync struct {
|
||||
perfDataCollectorActiveSync *pdh.Collector
|
||||
perfDataCollectorActiveSync *pdh.Collector[perfDataCounterValuesActiveSync]
|
||||
perfDataObjectActiveSync []perfDataCounterValuesActiveSync
|
||||
|
||||
activeSyncRequestsPerSec *prometheus.Desc
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorADAccessProcesses struct {
|
||||
perfDataCollectorADAccessProcesses *pdh.Collector
|
||||
perfDataCollectorADAccessProcesses *pdh.Collector[perfDataCounterValuesADAccessProcesses]
|
||||
perfDataObjectADAccessProcesses []perfDataCounterValuesADAccessProcesses
|
||||
|
||||
ldapReadOperations *prometheus.Desc
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorAutoDiscover struct {
|
||||
perfDataCollectorAutoDiscover *pdh.Collector
|
||||
perfDataCollectorAutoDiscover *pdh.Collector[perfDataCounterValuesAutoDiscover]
|
||||
perfDataObjectAutoDiscover []perfDataCounterValuesAutoDiscover
|
||||
|
||||
autoDiscoverRequestsPerSec *prometheus.Desc
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorAvailabilityService struct {
|
||||
perfDataCollectorAvailabilityService *pdh.Collector
|
||||
perfDataCollectorAvailabilityService *pdh.Collector[perfDataCounterValuesAvailabilityService]
|
||||
perfDataObjectAvailabilityService []perfDataCounterValuesAvailabilityService
|
||||
|
||||
availabilityRequestsSec *prometheus.Desc
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorHTTPProxy struct {
|
||||
perfDataCollectorHTTPProxy *pdh.Collector
|
||||
perfDataCollectorHTTPProxy *pdh.Collector[perfDataCounterValuesHTTPProxy]
|
||||
perfDataObjectHTTPProxy []perfDataCounterValuesHTTPProxy
|
||||
|
||||
mailboxServerLocatorAverageLatency *prometheus.Desc
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorMapiHTTPEmsMDB struct {
|
||||
perfDataCollectorMapiHTTPEmsMDB *pdh.Collector
|
||||
perfDataCollectorMapiHTTPEmsMDB *pdh.Collector[perfDataCounterValuesMapiHTTPEmsMDB]
|
||||
perfDataObjectMapiHTTPEmsMDB []perfDataCounterValuesMapiHTTPEmsMDB
|
||||
|
||||
activeUserCountMapiHTTPEmsMDB *prometheus.Desc
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorOWA struct {
|
||||
perfDataCollectorOWA *pdh.Collector
|
||||
perfDataCollectorOWA *pdh.Collector[perfDataCounterValuesOWA]
|
||||
perfDataObjectOWA []perfDataCounterValuesOWA
|
||||
|
||||
currentUniqueUsers *prometheus.Desc
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorRpcClientAccess struct {
|
||||
perfDataCollectorRpcClientAccess *pdh.Collector
|
||||
perfDataCollectorRpcClientAccess *pdh.Collector[perfDataCounterValuesRpcClientAccess]
|
||||
perfDataObjectRpcClientAccess []perfDataCounterValuesRpcClientAccess
|
||||
|
||||
activeUserCount *prometheus.Desc
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorTransportQueues struct {
|
||||
perfDataCollectorTransportQueues *pdh.Collector
|
||||
perfDataCollectorTransportQueues *pdh.Collector[perfDataCounterValuesTransportQueues]
|
||||
perfDataObjectTransportQueues []perfDataCounterValuesTransportQueues
|
||||
|
||||
activeMailboxDeliveryQueueLength *prometheus.Desc
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorWorkloadManagementWorkloads struct {
|
||||
perfDataCollectorWorkloadManagementWorkloads *pdh.Collector
|
||||
perfDataCollectorWorkloadManagementWorkloads *pdh.Collector[perfDataCounterValuesWorkloadManagementWorkloads]
|
||||
perfDataObjectWorkloadManagementWorkloads []perfDataCounterValuesWorkloadManagementWorkloads
|
||||
|
||||
activeTasks *prometheus.Desc
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorAppPoolWAS struct {
|
||||
perfDataCollectorAppPoolWAS *pdh.Collector
|
||||
perfDataCollectorAppPoolWAS *pdh.Collector[perfDataCounterValuesAppPoolWAS]
|
||||
perfDataObjectAppPoolWAS []perfDataCounterValuesAppPoolWAS
|
||||
|
||||
currentApplicationPoolState *prometheus.Desc
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorHttpServiceRequestQueues struct {
|
||||
perfDataCollectorHttpServiceRequestQueues *pdh.Collector
|
||||
perfDataCollectorHttpServiceRequestQueues *pdh.Collector[perfDataCounterValuesHttpServiceRequestQueues]
|
||||
perfDataObjectHttpServiceRequestQueues []perfDataCounterValuesHttpServiceRequestQueues
|
||||
|
||||
httpRequestQueuesCurrentQueueSize *prometheus.Desc
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorWebService struct {
|
||||
perfDataCollectorWebService *pdh.Collector
|
||||
perfDataCollectorWebService *pdh.Collector[perfDataCounterValuesWebService]
|
||||
perfDataObjectWebService []perfDataCounterValuesWebService
|
||||
|
||||
webServiceCurrentAnonymousUsers *prometheus.Desc
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorWebServiceCache struct {
|
||||
serviceCachePerfDataCollector *pdh.Collector
|
||||
serviceCachePerfDataCollector *pdh.Collector[perfDataCounterServiceCache]
|
||||
perfDataObjectServiceCache []perfDataCounterServiceCache
|
||||
|
||||
serviceCacheActiveFlushedEntries *prometheus.Desc
|
||||
|
||||
@@ -85,7 +85,7 @@ type Collector struct {
|
||||
config Config
|
||||
logger *slog.Logger
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
avgReadQueue *prometheus.Desc
|
||||
|
||||
@@ -45,7 +45,7 @@ var ConfigDefaults = Config{}
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
// Performance metrics
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -63,7 +63,7 @@ var ConfigDefaults = Config{
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
bytesReceivedTotal *prometheus.Desc
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -43,7 +43,7 @@ var ConfigDefaults = Config{}
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
pagingFreeBytes *prometheus.Desc
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -48,7 +48,7 @@ var ConfigDefaults = Config{
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
idleTime *prometheus.Desc
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -39,7 +39,7 @@ var ConfigDefaults = Config{}
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
treeConnectCount *prometheus.Desc
|
||||
|
||||
@@ -42,7 +42,7 @@ var ConfigDefaults = Config{}
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
readBytesTotal *prometheus.Desc
|
||||
|
||||
@@ -46,7 +46,7 @@ var ConfigDefaults = Config{
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
badMailedMessagesBadPickupFileTotal *prometheus.Desc
|
||||
|
||||
@@ -43,7 +43,7 @@ type Collector struct {
|
||||
|
||||
bootTimeTimestamp float64
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
contextSwitchesTotal *prometheus.Desc
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -40,7 +40,7 @@ var ConfigDefaults = Config{}
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
percentPassiveLimit *prometheus.Desc
|
||||
|
||||
@@ -61,7 +61,7 @@ var ConfigDefaults = Config{
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector *pdh.Collector
|
||||
perfDataCollector *pdh.Collector[perfDataCounterValues]
|
||||
perfDataObject []perfDataCounterValues
|
||||
|
||||
logger *slog.Logger
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+155
-145
@@ -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
|
||||
}
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
package types
|
||||
|
||||
type Collector interface {
|
||||
Collect(dst any) error
|
||||
type Collector[T any] interface {
|
||||
Collect(dst *[]T) error
|
||||
Close()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user