diff --git a/.run/all.run.xml b/.run/all.run.xml index 8ed34eb80..7773cac13 100644 --- a/.run/all.run.xml +++ b/.run/all.run.xml @@ -2,7 +2,7 @@ - + diff --git a/config.yaml b/config.yaml index d26e5f893..c4f16ee61 100644 --- a/config.yaml +++ b/config.yaml @@ -7,10 +7,17 @@ collector: include: "windows_exporter" performancecounter: objects: |- - - name: memory - object: "Memory" + - name: photon_udp + object: "Photon Socket Server: UDP" + instances: ["*"] counters: - - name: "Cache Faults/sec" - type: "counter" # optional + - name: "UDP: Datagrams in" + metric: "photon_udp_datagrams" + labels: + direction: "in" + - name: "UDP: Datagrams out" + metric: "photon_udp_datagrams" + labels: + direction: "out" log: level: warn diff --git a/docs/collector.performancecounter.md b/docs/collector.performancecounter.md index 16c906f02..b0755e0ff 100644 --- a/docs/collector.performancecounter.md +++ b/docs/collector.performancecounter.md @@ -59,6 +59,7 @@ YAML: state: idle - name: memory object: "Memory" + type: "formatted" counters: - name: "Cache Faults/sec" type: "counter" # optional @@ -98,6 +99,7 @@ YAML: { "name": "memory", "object": "Memory", + "type": "formatted", "counters": [ { "name": "Cache Faults/sec", @@ -120,6 +122,33 @@ ObjectName is the Object to query for, like Processor, DirectoryServices, Logica The collector supports only english named counter. Localized counter-names are not supported. +#### type + +The counter-type. The value can be `raw` or `formatted`. Optional and defaults to `raw`. + +- `raw` returns the raw value of the counter. This is the default. +- `formatted` returns the formatted value of the counter. This is useful for counters like `Processor Information` where the value is a percentage. + +The difference between a raw Windows Performance Counter and a formatted Windows Performance Counter is about how the data is presented and processed: + +1. Raw Windows Performance Counter: + + This provides the counter's data in its basic, unprocessed form. + The values may represent cumulative counts, time intervals, or other uncalibrated metrics. + Interpreting these values often requires more calculations or context, such as calculating deltas or normalizing values over time. + +2. Formatted Windows Performance Counter: + + This presents data that has already been processed and interpreted according to the counter type (e.g., rates per second, averages, percentages). + Formatted counters are easier to understand directly since the necessary calculations have been applied. + These are often what monitoring tools display to users because they are meaningful at a glance. + +For example: + +* A raw counter for CPU time might give the total number of clock ticks used since the system started. +* A formatted counter would convert this into a percentage of CPU utilization over a specific time interval. + + #### instances The instances key (this is an array) declares the instances of a counter you would like returned, it can be one or more values. diff --git a/internal/collector/ad/ad.go b/internal/collector/ad/ad.go index f02b4982c..ab48432d7 100644 --- a/internal/collector/ad/ad.go +++ b/internal/collector/ad/ad.go @@ -132,7 +132,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("DirectoryServices", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "DirectoryServices", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create DirectoryServices collector: %w", err) } diff --git a/internal/collector/adcs/adcs.go b/internal/collector/adcs/adcs.go index 0f7a50f72..ca1125ec2 100644 --- a/internal/collector/adcs/adcs.go +++ b/internal/collector/adcs/adcs.go @@ -84,7 +84,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("Certification Authority", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Certification Authority", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Certification Authority collector: %w", err) } diff --git a/internal/collector/adfs/adfs.go b/internal/collector/adfs/adfs.go index 7d9c89516..963233e28 100644 --- a/internal/collector/adfs/adfs.go +++ b/internal/collector/adfs/adfs.go @@ -114,7 +114,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("AD FS", nil) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "AD FS", nil) if err != nil { return fmt.Errorf("failed to create AD FS collector: %w", err) } diff --git a/internal/collector/cache/cache.go b/internal/collector/cache/cache.go index 632505edd..fe35c6d01 100644 --- a/internal/collector/cache/cache.go +++ b/internal/collector/cache/cache.go @@ -100,7 +100,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("Cache", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Cache", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Cache collector: %w", err) } diff --git a/internal/collector/cpu/cpu.go b/internal/collector/cpu/cpu.go index a6e8d2219..a1d7e93e7 100644 --- a/internal/collector/cpu/cpu.go +++ b/internal/collector/cpu/cpu.go @@ -93,7 +93,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { c.mu = sync.Mutex{} - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("Processor Information", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Processor Information", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Processor Information collector: %w", err) } diff --git a/internal/collector/dfsr/dfsr.go b/internal/collector/dfsr/dfsr.go index 8e28e3fc1..7863f7d06 100644 --- a/internal/collector/dfsr/dfsr.go +++ b/internal/collector/dfsr/dfsr.go @@ -163,21 +163,21 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { var err error if slices.Contains(c.config.CollectorsEnabled, "connection") { - c.perfDataCollectorConnection, err = pdh.NewCollector[perfDataCounterValuesConnection]("DFS Replication Connections", pdh.InstancesAll) + c.perfDataCollectorConnection, err = pdh.NewCollector[perfDataCounterValuesConnection](pdh.CounterTypeRaw, "DFS Replication Connections", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create DFS Replication Connections collector: %w", err) } } if slices.Contains(c.config.CollectorsEnabled, "folder") { - c.perfDataCollectorFolder, err = pdh.NewCollector[perfDataCounterValuesFolder]("DFS Replicated Folders", pdh.InstancesAll) + c.perfDataCollectorFolder, err = pdh.NewCollector[perfDataCounterValuesFolder](pdh.CounterTypeRaw, "DFS Replicated Folders", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create DFS Replicated Folders collector: %w", err) } } if slices.Contains(c.config.CollectorsEnabled, "volume") { - c.perfDataCollectorVolume, err = pdh.NewCollector[perfDataCounterValuesVolume]("DFS Replication Service Volumes", pdh.InstancesAll) + c.perfDataCollectorVolume, err = pdh.NewCollector[perfDataCounterValuesVolume](pdh.CounterTypeRaw, "DFS Replication Service Volumes", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create DFS Replication Service Volumes collector: %w", err) } diff --git a/internal/collector/dhcp/dhcp.go b/internal/collector/dhcp/dhcp.go index 357a64c3f..71540bd60 100644 --- a/internal/collector/dhcp/dhcp.go +++ b/internal/collector/dhcp/dhcp.go @@ -96,7 +96,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("DHCP Server", nil) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "DHCP Server", nil) if err != nil { return fmt.Errorf("failed to create DHCP Server collector: %w", err) } diff --git a/internal/collector/dns/dns.go b/internal/collector/dns/dns.go index 17c651f84..0a9ed82df 100644 --- a/internal/collector/dns/dns.go +++ b/internal/collector/dns/dns.go @@ -93,7 +93,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("DNS", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "DNS", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create DNS collector: %w", err) } diff --git a/internal/collector/exchange/exchange_active_sync.go b/internal/collector/exchange/exchange_active_sync.go index 618e830b1..938e61a28 100644 --- a/internal/collector/exchange/exchange_active_sync.go +++ b/internal/collector/exchange/exchange_active_sync.go @@ -41,7 +41,7 @@ type perfDataCounterValuesActiveSync struct { func (c *Collector) buildActiveSync() error { var err error - c.perfDataCollectorActiveSync, err = pdh.NewCollector[perfDataCounterValuesActiveSync]("MSExchange ActiveSync", pdh.InstancesAll) + c.perfDataCollectorActiveSync, err = pdh.NewCollector[perfDataCounterValuesActiveSync](pdh.CounterTypeRaw, "MSExchange ActiveSync", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchange ActiveSync collector: %w", err) } diff --git a/internal/collector/exchange/exchange_ad_access_processes.go b/internal/collector/exchange/exchange_ad_access_processes.go index cfda3791f..036137f58 100644 --- a/internal/collector/exchange/exchange_ad_access_processes.go +++ b/internal/collector/exchange/exchange_ad_access_processes.go @@ -48,7 +48,7 @@ type perfDataCounterValuesADAccessProcesses struct { func (c *Collector) buildADAccessProcesses() error { var err error - c.perfDataCollectorADAccessProcesses, err = pdh.NewCollector[perfDataCounterValuesADAccessProcesses]("MSExchange ADAccess Processes", pdh.InstancesAll) + c.perfDataCollectorADAccessProcesses, err = pdh.NewCollector[perfDataCounterValuesADAccessProcesses](pdh.CounterTypeRaw, "MSExchange ADAccess Processes", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchange ADAccess Processes collector: %w", err) } diff --git a/internal/collector/exchange/exchange_autodiscover.go b/internal/collector/exchange/exchange_autodiscover.go index a0a29510b..90a3bb21e 100644 --- a/internal/collector/exchange/exchange_autodiscover.go +++ b/internal/collector/exchange/exchange_autodiscover.go @@ -37,7 +37,7 @@ type perfDataCounterValuesAutoDiscover struct { func (c *Collector) buildAutoDiscover() error { var err error - c.perfDataCollectorAutoDiscover, err = pdh.NewCollector[perfDataCounterValuesAutoDiscover]("MSExchange Autodiscover", pdh.InstancesAll) + c.perfDataCollectorAutoDiscover, err = pdh.NewCollector[perfDataCounterValuesAutoDiscover](pdh.CounterTypeRaw, "MSExchange Autodiscover", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchange Autodiscover collector: %w", err) } diff --git a/internal/collector/exchange/exchange_availability_service.go b/internal/collector/exchange/exchange_availability_service.go index 31efa42db..74d80f377 100644 --- a/internal/collector/exchange/exchange_availability_service.go +++ b/internal/collector/exchange/exchange_availability_service.go @@ -37,7 +37,7 @@ type perfDataCounterValuesAvailabilityService struct { func (c *Collector) buildAvailabilityService() error { var err error - c.perfDataCollectorAvailabilityService, err = pdh.NewCollector[perfDataCounterValuesAvailabilityService]("MSExchange Availability Service", pdh.InstancesAll) + c.perfDataCollectorAvailabilityService, err = pdh.NewCollector[perfDataCounterValuesAvailabilityService](pdh.CounterTypeRaw, "MSExchange Availability Service", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchange Availability Service collector: %w", err) } diff --git a/internal/collector/exchange/exchange_http_proxy.go b/internal/collector/exchange/exchange_http_proxy.go index c42f5cda4..d45c60be1 100644 --- a/internal/collector/exchange/exchange_http_proxy.go +++ b/internal/collector/exchange/exchange_http_proxy.go @@ -50,7 +50,7 @@ type perfDataCounterValuesHTTPProxy struct { func (c *Collector) buildHTTPProxy() error { var err error - c.perfDataCollectorHTTPProxy, err = pdh.NewCollector[perfDataCounterValuesHTTPProxy]("MSExchange HttpProxy", pdh.InstancesAll) + c.perfDataCollectorHTTPProxy, err = pdh.NewCollector[perfDataCounterValuesHTTPProxy](pdh.CounterTypeRaw, "MSExchange HttpProxy", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchange HttpProxy collector: %w", err) } diff --git a/internal/collector/exchange/exchange_mapi_http_emsmdb.go b/internal/collector/exchange/exchange_mapi_http_emsmdb.go index 34bc6cda3..817687a7f 100644 --- a/internal/collector/exchange/exchange_mapi_http_emsmdb.go +++ b/internal/collector/exchange/exchange_mapi_http_emsmdb.go @@ -37,7 +37,7 @@ type perfDataCounterValuesMapiHttpEmsmdb struct { func (c *Collector) buildMapiHttpEmsmdb() error { var err error - c.perfDataCollectorMapiHttpEmsmdb, err = pdh.NewCollector[perfDataCounterValuesMapiHttpEmsmdb]("MSExchange MapiHttp Emsmdb", pdh.InstancesAll) + c.perfDataCollectorMapiHttpEmsmdb, err = pdh.NewCollector[perfDataCounterValuesMapiHttpEmsmdb](pdh.CounterTypeRaw, "MSExchange MapiHttp Emsmdb", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchange MapiHttp Emsmdb: %w", err) } diff --git a/internal/collector/exchange/exchange_outlook_web_access.go b/internal/collector/exchange/exchange_outlook_web_access.go index c4c4e60cf..d95f58d4d 100644 --- a/internal/collector/exchange/exchange_outlook_web_access.go +++ b/internal/collector/exchange/exchange_outlook_web_access.go @@ -39,7 +39,7 @@ type perfDataCounterValuesOWA struct { func (c *Collector) buildOWA() error { var err error - c.perfDataCollectorOWA, err = pdh.NewCollector[perfDataCounterValuesOWA]("MSExchange OWA", pdh.InstancesAll) + c.perfDataCollectorOWA, err = pdh.NewCollector[perfDataCounterValuesOWA](pdh.CounterTypeRaw, "MSExchange OWA", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchange OWA collector: %w", err) } diff --git a/internal/collector/exchange/exchange_rpc_client_access.go b/internal/collector/exchange/exchange_rpc_client_access.go index b144d9339..2801856fb 100644 --- a/internal/collector/exchange/exchange_rpc_client_access.go +++ b/internal/collector/exchange/exchange_rpc_client_access.go @@ -48,7 +48,7 @@ type perfDataCounterValuesRpcClientAccess struct { func (c *Collector) buildRpcClientAccess() error { var err error - c.perfDataCollectorRpcClientAccess, err = pdh.NewCollector[perfDataCounterValuesRpcClientAccess]("MSExchange RpcClientAccess", pdh.InstancesAll) + c.perfDataCollectorRpcClientAccess, err = pdh.NewCollector[perfDataCounterValuesRpcClientAccess](pdh.CounterTypeRaw, "MSExchange RpcClientAccess", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchange RpcClientAccess collector: %w", err) } diff --git a/internal/collector/exchange/exchange_transport_queues.go b/internal/collector/exchange/exchange_transport_queues.go index 1eea43cba..d00b4f534 100644 --- a/internal/collector/exchange/exchange_transport_queues.go +++ b/internal/collector/exchange/exchange_transport_queues.go @@ -75,7 +75,7 @@ type perfDataCounterValuesTransportQueues struct { func (c *Collector) buildTransportQueues() error { var err error - c.perfDataCollectorTransportQueues, err = pdh.NewCollector[perfDataCounterValuesTransportQueues]("MSExchangeTransport Queues", pdh.InstancesAll) + c.perfDataCollectorTransportQueues, err = pdh.NewCollector[perfDataCounterValuesTransportQueues](pdh.CounterTypeRaw, "MSExchangeTransport Queues", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchangeTransport Queues collector: %w", err) } diff --git a/internal/collector/exchange/exchange_workload_management.go b/internal/collector/exchange/exchange_workload_management.go index ccedfcdcd..e2be15cd6 100644 --- a/internal/collector/exchange/exchange_workload_management.go +++ b/internal/collector/exchange/exchange_workload_management.go @@ -47,7 +47,7 @@ type perfDataCounterValuesWorkloadManagementWorkloads struct { func (c *Collector) buildWorkloadManagementWorkloads() error { var err error - c.perfDataCollectorWorkloadManagementWorkloads, err = pdh.NewCollector[perfDataCounterValuesWorkloadManagementWorkloads]("MSExchange WorkloadManagement Workloads", pdh.InstancesAll) + c.perfDataCollectorWorkloadManagementWorkloads, err = pdh.NewCollector[perfDataCounterValuesWorkloadManagementWorkloads](pdh.CounterTypeRaw, "MSExchange WorkloadManagement Workloads", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchange WorkloadManagement Workloads collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_datastore.go b/internal/collector/hyperv/hyperv_datastore.go index 8ea41d674..35ff06318 100644 --- a/internal/collector/hyperv/hyperv_datastore.go +++ b/internal/collector/hyperv/hyperv_datastore.go @@ -130,7 +130,7 @@ type perfDataCounterValuesDataStore struct { func (c *Collector) buildDataStore() error { var err error - c.perfDataCollectorDataStore, err = pdh.NewCollector[perfDataCounterValuesDataStore]("Hyper-V DataStore", pdh.InstancesAll) + c.perfDataCollectorDataStore, err = pdh.NewCollector[perfDataCounterValuesDataStore](pdh.CounterTypeRaw, "Hyper-V DataStore", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V DataStore collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go index fb02f4d5a..97a26b384 100644 --- a/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go +++ b/internal/collector/hyperv/hyperv_dynamic_memory_balancer.go @@ -49,7 +49,7 @@ func (c *Collector) buildDynamicMemoryBalancer() error { var err error // https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012 - c.perfDataCollectorDynamicMemoryBalancer, err = pdh.NewCollector[perfDataCounterValuesDynamicMemoryBalancer]("Hyper-V Dynamic Memory Balancer", pdh.InstancesAll) + c.perfDataCollectorDynamicMemoryBalancer, err = pdh.NewCollector[perfDataCounterValuesDynamicMemoryBalancer](pdh.CounterTypeRaw, "Hyper-V Dynamic Memory Balancer", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go index 665a846a0..86162f88e 100644 --- a/internal/collector/hyperv/hyperv_dynamic_memory_vm.go +++ b/internal/collector/hyperv/hyperv_dynamic_memory_vm.go @@ -60,7 +60,7 @@ type perfDataCounterValuesDynamicMemoryVM struct { func (c *Collector) buildDynamicMemoryVM() error { var err error - c.perfDataCollectorDynamicMemoryVM, err = pdh.NewCollector[perfDataCounterValuesDynamicMemoryVM]("Hyper-V Dynamic Memory VM", pdh.InstancesAll) + c.perfDataCollectorDynamicMemoryVM, err = pdh.NewCollector[perfDataCounterValuesDynamicMemoryVM](pdh.CounterTypeRaw, "Hyper-V Dynamic Memory VM", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Dynamic Memory VM collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go index 3fd60ad5f..76db01cc2 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go +++ b/internal/collector/hyperv/hyperv_hypervisor_logical_processor.go @@ -50,7 +50,7 @@ type perfDataCounterValuesHypervisorLogicalProcessor struct { func (c *Collector) buildHypervisorLogicalProcessor() error { var err error - c.perfDataCollectorHypervisorLogicalProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorLogicalProcessor]("Hyper-V Hypervisor Logical Processor", pdh.InstancesAll) + c.perfDataCollectorHypervisorLogicalProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorLogicalProcessor](pdh.CounterTypeRaw, "Hyper-V Hypervisor Logical Processor", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Hypervisor Logical Processor collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_hypervisor_root_partition.go b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go index c8d5290e8..dd9f432f3 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_root_partition.go +++ b/internal/collector/hyperv/hyperv_hypervisor_root_partition.go @@ -78,7 +78,7 @@ type perfDataCounterValuesHypervisorRootPartition struct { func (c *Collector) buildHypervisorRootPartition() error { var err error - c.perfDataCollectorHypervisorRootPartition, err = pdh.NewCollector[perfDataCounterValuesHypervisorRootPartition]("Hyper-V Hypervisor Root Partition", []string{"Root"}) + c.perfDataCollectorHypervisorRootPartition, err = pdh.NewCollector[perfDataCounterValuesHypervisorRootPartition](pdh.CounterTypeRaw, "Hyper-V Hypervisor Root Partition", []string{"Root"}) if err != nil { return fmt.Errorf("failed to create Hyper-V Hypervisor Root Partition collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go b/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go index 8ef5983d5..481114bc7 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go +++ b/internal/collector/hyperv/hyperv_hypervisor_root_virtual_processor.go @@ -51,7 +51,7 @@ type perfDataCounterValuesHypervisorRootVirtualProcessor struct { func (c *Collector) buildHypervisorRootVirtualProcessor() error { var err error - c.perfDataCollectorHypervisorRootVirtualProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorRootVirtualProcessor]("Hyper-V Hypervisor Root Virtual Processor", pdh.InstancesAll) + c.perfDataCollectorHypervisorRootVirtualProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorRootVirtualProcessor](pdh.CounterTypeRaw, "Hyper-V Hypervisor Root Virtual Processor", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Hypervisor Root Virtual Processor collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go b/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go index 48f9d2746..78ef1561e 100644 --- a/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go +++ b/internal/collector/hyperv/hyperv_hypervisor_virtual_processor.go @@ -50,7 +50,7 @@ type perfDataCounterValuesHypervisorVirtualProcessor struct { func (c *Collector) buildHypervisorVirtualProcessor() error { var err error - c.perfDataCollectorHypervisorVirtualProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorVirtualProcessor]("Hyper-V Hypervisor Virtual Processor", pdh.InstancesAll) + c.perfDataCollectorHypervisorVirtualProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorVirtualProcessor](pdh.CounterTypeRaw, "Hyper-V Hypervisor Virtual Processor", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Hypervisor Virtual Processor collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_legacy_network_adapter.go b/internal/collector/hyperv/hyperv_legacy_network_adapter.go index 6d8422f58..18cd1f54e 100644 --- a/internal/collector/hyperv/hyperv_legacy_network_adapter.go +++ b/internal/collector/hyperv/hyperv_legacy_network_adapter.go @@ -50,7 +50,7 @@ type perfDataCounterValuesLegacyNetworkAdapter struct { func (c *Collector) buildLegacyNetworkAdapter() error { var err error - c.perfDataCollectorLegacyNetworkAdapter, err = pdh.NewCollector[perfDataCounterValuesLegacyNetworkAdapter]("Hyper-V Legacy Network Adapter", pdh.InstancesAll) + c.perfDataCollectorLegacyNetworkAdapter, err = pdh.NewCollector[perfDataCounterValuesLegacyNetworkAdapter](pdh.CounterTypeRaw, "Hyper-V Legacy Network Adapter", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Legacy Network Adapter collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go index d9525e6bb..7f670052f 100644 --- a/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go +++ b/internal/collector/hyperv/hyperv_virtual_machine_health_summary.go @@ -42,7 +42,7 @@ type perfDataCounterValuesVirtualMachineHealthSummary struct { func (c *Collector) buildVirtualMachineHealthSummary() error { var err error - c.perfDataCollectorVirtualMachineHealthSummary, err = pdh.NewCollector[perfDataCounterValuesVirtualMachineHealthSummary]("Hyper-V Virtual Machine Health Summary", nil) + c.perfDataCollectorVirtualMachineHealthSummary, err = pdh.NewCollector[perfDataCounterValuesVirtualMachineHealthSummary](pdh.CounterTypeRaw, "Hyper-V Virtual Machine Health Summary", nil) if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go index 1db84e7d3..196da9508 100644 --- a/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go +++ b/internal/collector/hyperv/hyperv_virtual_machine_vid_partition.go @@ -44,7 +44,7 @@ type perfDataCounterValuesVirtualMachineVidPartition struct { func (c *Collector) buildVirtualMachineVidPartition() error { var err error - c.perfDataCollectorVirtualMachineVidPartition, err = pdh.NewCollector[perfDataCounterValuesVirtualMachineVidPartition]("Hyper-V VM Vid Partition", pdh.InstancesAll) + c.perfDataCollectorVirtualMachineVidPartition, err = pdh.NewCollector[perfDataCounterValuesVirtualMachineVidPartition](pdh.CounterTypeRaw, "Hyper-V VM Vid Partition", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V VM Vid Partition collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_network_adapter.go b/internal/collector/hyperv/hyperv_virtual_network_adapter.go index c624c57aa..e489e82e5 100644 --- a/internal/collector/hyperv/hyperv_virtual_network_adapter.go +++ b/internal/collector/hyperv/hyperv_virtual_network_adapter.go @@ -50,7 +50,7 @@ type perfDataCounterValuesVirtualNetworkAdapter struct { func (c *Collector) buildVirtualNetworkAdapter() error { var err error - c.perfDataCollectorVirtualNetworkAdapter, err = pdh.NewCollector[perfDataCounterValuesVirtualNetworkAdapter]("Hyper-V Virtual Network Adapter", pdh.InstancesAll) + c.perfDataCollectorVirtualNetworkAdapter, err = pdh.NewCollector[perfDataCounterValuesVirtualNetworkAdapter](pdh.CounterTypeRaw, "Hyper-V Virtual Network Adapter", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go b/internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go index 0e177719f..42cd20ac1 100644 --- a/internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go +++ b/internal/collector/hyperv/hyperv_virtual_network_adapter_drop_reasons.go @@ -165,7 +165,7 @@ type perfDataCounterValuesVirtualNetworkAdapterDropReasons struct { func (c *Collector) buildVirtualNetworkAdapterDropReasons() error { var err error - c.perfDataCollectorVirtualNetworkAdapterDropReasons, err = pdh.NewCollector[perfDataCounterValuesVirtualNetworkAdapterDropReasons]("Hyper-V Virtual Network Adapter Drop Reasons", pdh.InstancesAll) + c.perfDataCollectorVirtualNetworkAdapterDropReasons, err = pdh.NewCollector[perfDataCounterValuesVirtualNetworkAdapterDropReasons](pdh.CounterTypeRaw, "Hyper-V Virtual Network Adapter Drop Reasons", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter Drop Reasons collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_smb.go b/internal/collector/hyperv/hyperv_virtual_smb.go index f45fce358..8a8147678 100644 --- a/internal/collector/hyperv/hyperv_virtual_smb.go +++ b/internal/collector/hyperv/hyperv_virtual_smb.go @@ -72,7 +72,7 @@ type perfDataCounterValuesVirtualSMB struct { func (c *Collector) buildVirtualSMB() error { var err error - c.perfDataCollectorVirtualSMB, err = pdh.NewCollector[perfDataCounterValuesVirtualSMB]("Hyper-V Virtual SMB", pdh.InstancesAll) + c.perfDataCollectorVirtualSMB, err = pdh.NewCollector[perfDataCounterValuesVirtualSMB](pdh.CounterTypeRaw, "Hyper-V Virtual SMB", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual SMB collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_storage_device.go b/internal/collector/hyperv/hyperv_virtual_storage_device.go index 0f26ec8b6..9247aa057 100644 --- a/internal/collector/hyperv/hyperv_virtual_storage_device.go +++ b/internal/collector/hyperv/hyperv_virtual_storage_device.go @@ -62,7 +62,7 @@ type perfDataCounterValuesVirtualStorageDevice struct { func (c *Collector) buildVirtualStorageDevice() error { var err error - c.perfDataCollectorVirtualStorageDevice, err = pdh.NewCollector[perfDataCounterValuesVirtualStorageDevice]("Hyper-V Virtual Storage Device", pdh.InstancesAll) + c.perfDataCollectorVirtualStorageDevice, err = pdh.NewCollector[perfDataCounterValuesVirtualStorageDevice](pdh.CounterTypeRaw, "Hyper-V Virtual Storage Device", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Storage Device collector: %w", err) } diff --git a/internal/collector/hyperv/hyperv_virtual_switch.go b/internal/collector/hyperv/hyperv_virtual_switch.go index 9052d7c1b..13759006f 100644 --- a/internal/collector/hyperv/hyperv_virtual_switch.go +++ b/internal/collector/hyperv/hyperv_virtual_switch.go @@ -80,7 +80,7 @@ type perfDataCounterValuesVirtualSwitch struct { func (c *Collector) buildVirtualSwitch() error { var err error - c.perfDataCollectorVirtualSwitch, err = pdh.NewCollector[perfDataCounterValuesVirtualSwitch]("Hyper-V Virtual Switch", pdh.InstancesAll) + c.perfDataCollectorVirtualSwitch, err = pdh.NewCollector[perfDataCounterValuesVirtualSwitch](pdh.CounterTypeRaw, "Hyper-V Virtual Switch", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Hyper-V Virtual Switch collector: %w", err) } diff --git a/internal/collector/iis/iis_app_pool_was.go b/internal/collector/iis/iis_app_pool_was.go index 48729f1a6..39f6b7229 100644 --- a/internal/collector/iis/iis_app_pool_was.go +++ b/internal/collector/iis/iis_app_pool_was.go @@ -77,7 +77,7 @@ var applicationStates = map[uint32]string{ func (c *Collector) buildAppPoolWAS() error { var err error - c.perfDataCollectorAppPoolWAS, err = pdh.NewCollector[perfDataCounterValuesAppPoolWAS]("APP_POOL_WAS", pdh.InstancesAll) + c.perfDataCollectorAppPoolWAS, err = pdh.NewCollector[perfDataCounterValuesAppPoolWAS](pdh.CounterTypeRaw, "APP_POOL_WAS", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create APP_POOL_WAS collector: %w", err) } diff --git a/internal/collector/iis/iis_w3svc_w3wp.go b/internal/collector/iis/iis_w3svc_w3wp.go index 22cbb037f..c40e391cd 100644 --- a/internal/collector/iis/iis_w3svc_w3wp.go +++ b/internal/collector/iis/iis_w3svc_w3wp.go @@ -150,13 +150,13 @@ func (p perfDataCounterValuesW3SVCW3WPV8) GetName() string { func (c *Collector) buildW3SVCW3WP() error { var err error - c.w3SVCW3WPPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesW3SVCW3WP]("W3SVC_W3WP", pdh.InstancesAll) + c.w3SVCW3WPPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesW3SVCW3WP](pdh.CounterTypeRaw, "W3SVC_W3WP", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create W3SVC_W3WP collector: %w", err) } if c.iisVersion.major >= 8 { - c.w3SVCW3WPPerfDataCollectorV8, err = pdh.NewCollector[perfDataCounterValuesW3SVCW3WPV8]("W3SVC_W3WP", pdh.InstancesAll) + c.w3SVCW3WPPerfDataCollectorV8, err = pdh.NewCollector[perfDataCounterValuesW3SVCW3WPV8](pdh.CounterTypeRaw, "W3SVC_W3WP", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create W3SVC_W3WP collector: %w", err) } diff --git a/internal/collector/iis/iis_web_service.go b/internal/collector/iis/iis_web_service.go index 001424888..e343e784f 100644 --- a/internal/collector/iis/iis_web_service.go +++ b/internal/collector/iis/iis_web_service.go @@ -100,7 +100,7 @@ func (p perfDataCounterValuesWebService) GetName() string { func (c *Collector) buildWebService() error { var err error - c.perfDataCollectorWebService, err = pdh.NewCollector[perfDataCounterValuesWebService]("Web Service", pdh.InstancesAll) + c.perfDataCollectorWebService, err = pdh.NewCollector[perfDataCounterValuesWebService](pdh.CounterTypeRaw, "Web Service", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Web Service collector: %w", err) } diff --git a/internal/collector/iis/iis_web_service_cache.go b/internal/collector/iis/iis_web_service_cache.go index 08a916109..b662eb50a 100644 --- a/internal/collector/iis/iis_web_service_cache.go +++ b/internal/collector/iis/iis_web_service_cache.go @@ -107,7 +107,7 @@ func (p perfDataCounterServiceCache) GetName() string { func (c *Collector) buildWebServiceCache() error { var err error - c.serviceCachePerfDataCollector, err = pdh.NewCollector[perfDataCounterServiceCache]("Web Service Cache", pdh.InstancesAll) + c.serviceCachePerfDataCollector, err = pdh.NewCollector[perfDataCounterServiceCache](pdh.CounterTypeRaw, "Web Service Cache", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Web Service Cache collector: %w", err) } diff --git a/internal/collector/logical_disk/logical_disk.go b/internal/collector/logical_disk/logical_disk.go index f6f0b6a4e..1075438f6 100644 --- a/internal/collector/logical_disk/logical_disk.go +++ b/internal/collector/logical_disk/logical_disk.go @@ -152,7 +152,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("LogicalDisk", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "LogicalDisk", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create LogicalDisk collector: %w", err) } diff --git a/internal/collector/memory/memory.go b/internal/collector/memory/memory.go index 9f53deb5c..3c779e837 100644 --- a/internal/collector/memory/memory.go +++ b/internal/collector/memory/memory.go @@ -112,7 +112,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("Memory", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Memory", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Memory collector: %w", err) } diff --git a/internal/collector/msmq/msmq.go b/internal/collector/msmq/msmq.go index 3ff749ca8..2111c6bf1 100644 --- a/internal/collector/msmq/msmq.go +++ b/internal/collector/msmq/msmq.go @@ -76,7 +76,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("MSMQ Queue", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "MSMQ Queue", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSMQ Queue collector: %w", err) } diff --git a/internal/collector/mssql/mssql_access_methods.go b/internal/collector/mssql/mssql_access_methods.go index 52fe3d338..0d9a7b68b 100644 --- a/internal/collector/mssql/mssql_access_methods.go +++ b/internal/collector/mssql/mssql_access_methods.go @@ -128,9 +128,7 @@ func (c *Collector) buildAccessMethods() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.accessMethodsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesAccessMethods]( - c.mssqlGetPerfObjectName(sqlInstance.name, "Access Methods"), nil, - ) + c.accessMethodsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesAccessMethods](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "Access Methods"), nil) if err != nil { errs = append(errs, fmt.Errorf("failed to create AccessMethods collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_availability_replica.go b/internal/collector/mssql/mssql_availability_replica.go index 6214f141b..3451625aa 100644 --- a/internal/collector/mssql/mssql_availability_replica.go +++ b/internal/collector/mssql/mssql_availability_replica.go @@ -61,9 +61,7 @@ func (c *Collector) buildAvailabilityReplica() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.availabilityReplicaPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesAvailabilityReplica]( - c.mssqlGetPerfObjectName(sqlInstance.name, "Availability Replica"), pdh.InstancesAll, - ) + c.availabilityReplicaPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesAvailabilityReplica](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "Availability Replica"), pdh.InstancesAll) if err != nil { errs = append(errs, fmt.Errorf("failed to create Availability Replica collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_buffer_manager.go b/internal/collector/mssql/mssql_buffer_manager.go index 61de0884c..e378738ce 100644 --- a/internal/collector/mssql/mssql_buffer_manager.go +++ b/internal/collector/mssql/mssql_buffer_manager.go @@ -86,9 +86,7 @@ func (c *Collector) buildBufferManager() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.bufManPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesBufMan]( - c.mssqlGetPerfObjectName(sqlInstance.name, "Buffer Manager"), nil, - ) + c.bufManPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesBufMan](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "Buffer Manager"), nil) if err != nil { errs = append(errs, fmt.Errorf("failed to create Buffer Manager collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_database.go b/internal/collector/mssql/mssql_database.go index dd8b51f8b..a1cda5238 100644 --- a/internal/collector/mssql/mssql_database.go +++ b/internal/collector/mssql/mssql_database.go @@ -146,13 +146,13 @@ func (c *Collector) buildDatabases() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.databasesPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesDatabases](c.mssqlGetPerfObjectName(sqlInstance.name, "Databases"), pdh.InstancesAll) + c.databasesPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesDatabases](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "Databases"), pdh.InstancesAll) if err != nil { errs = append(errs, fmt.Errorf("failed to create Databases collector for instance %s: %w", sqlInstance.name, err)) } if sqlInstance.isVersionGreaterOrEqualThan(serverVersion2019) { - c.databasesPerfDataCollectors2019[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesDatabases2019](c.mssqlGetPerfObjectName(sqlInstance.name, "Databases"), pdh.InstancesAll) + c.databasesPerfDataCollectors2019[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesDatabases2019](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "Databases"), pdh.InstancesAll) if err != nil { errs = append(errs, fmt.Errorf("failed to create Databases 2019 collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_database_replica.go b/internal/collector/mssql/mssql_database_replica.go index 037a3430d..c91a53cc5 100644 --- a/internal/collector/mssql/mssql_database_replica.go +++ b/internal/collector/mssql/mssql_database_replica.go @@ -90,9 +90,7 @@ func (c *Collector) buildDatabaseReplica() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.dbReplicaPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesDBReplica]( - c.mssqlGetPerfObjectName(sqlInstance.name, "Database Replica"), pdh.InstancesAll, - ) + c.dbReplicaPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesDBReplica](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "Database Replica"), pdh.InstancesAll) if err != nil { errs = append(errs, fmt.Errorf("failed to create Database Replica collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_general_statistics.go b/internal/collector/mssql/mssql_general_statistics.go index 00ee2333e..3ed9b6c38 100644 --- a/internal/collector/mssql/mssql_general_statistics.go +++ b/internal/collector/mssql/mssql_general_statistics.go @@ -88,9 +88,7 @@ func (c *Collector) buildGeneralStatistics() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.genStatsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesGenStats]( - c.mssqlGetPerfObjectName(sqlInstance.name, "General Statistics"), nil, - ) + c.genStatsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesGenStats](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "General Statistics"), nil) if err != nil { errs = append(errs, fmt.Errorf("failed to create General Statistics collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_locks.go b/internal/collector/mssql/mssql_locks.go index 5199b77bd..8b06377b1 100644 --- a/internal/collector/mssql/mssql_locks.go +++ b/internal/collector/mssql/mssql_locks.go @@ -59,9 +59,7 @@ func (c *Collector) buildLocks() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.locksPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesLocks]( - c.mssqlGetPerfObjectName(sqlInstance.name, "Locks"), pdh.InstancesAll, - ) + c.locksPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesLocks](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "Locks"), pdh.InstancesAll) if err != nil { errs = append(errs, fmt.Errorf("failed to create Locks collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_memory_manager.go b/internal/collector/mssql/mssql_memory_manager.go index 508043ed3..6f1cf2ac9 100644 --- a/internal/collector/mssql/mssql_memory_manager.go +++ b/internal/collector/mssql/mssql_memory_manager.go @@ -80,9 +80,7 @@ func (c *Collector) buildMemoryManager() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.memMgrPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesMemMgr]( - c.mssqlGetPerfObjectName(sqlInstance.name, "Memory Manager"), pdh.InstancesAll, - ) + c.memMgrPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesMemMgr](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "Memory Manager"), pdh.InstancesAll) if err != nil { errs = append(errs, fmt.Errorf("failed to create Memory Manager collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_sql_errors.go b/internal/collector/mssql/mssql_sql_errors.go index e4033fa7d..70c66af3d 100644 --- a/internal/collector/mssql/mssql_sql_errors.go +++ b/internal/collector/mssql/mssql_sql_errors.go @@ -45,9 +45,7 @@ func (c *Collector) buildSQLErrors() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.sqlErrorsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesSqlErrors]( - c.mssqlGetPerfObjectName(sqlInstance.name, "SQL Errors"), pdh.InstancesAll, - ) + c.sqlErrorsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesSqlErrors](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "SQL Errors"), pdh.InstancesAll) if err != nil { errs = append(errs, fmt.Errorf("failed to create SQL Errors collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_sql_stats.go b/internal/collector/mssql/mssql_sql_stats.go index 453b9f74f..722fec176 100644 --- a/internal/collector/mssql/mssql_sql_stats.go +++ b/internal/collector/mssql/mssql_sql_stats.go @@ -62,9 +62,7 @@ func (c *Collector) buildSQLStats() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.sqlStatsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesSqlStats]( - c.mssqlGetPerfObjectName(sqlInstance.name, "SQL Statistics"), nil, - ) + c.sqlStatsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesSqlStats](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "SQL Statistics"), nil) if err != nil { errs = append(errs, fmt.Errorf("failed to create SQL Statistics collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_transactions.go b/internal/collector/mssql/mssql_transactions.go index f76f50bce..21387575e 100644 --- a/internal/collector/mssql/mssql_transactions.go +++ b/internal/collector/mssql/mssql_transactions.go @@ -66,9 +66,7 @@ func (c *Collector) buildTransactions() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.transactionsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesTransactions]( - c.mssqlGetPerfObjectName(sqlInstance.name, "Transactions"), nil, - ) + c.transactionsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesTransactions](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "Transactions"), nil) if err != nil { errs = append(errs, fmt.Errorf("failed to create Transactions collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/mssql/mssql_wait_stats.go b/internal/collector/mssql/mssql_wait_stats.go index 70c96caf7..90fa65508 100644 --- a/internal/collector/mssql/mssql_wait_stats.go +++ b/internal/collector/mssql/mssql_wait_stats.go @@ -66,9 +66,7 @@ func (c *Collector) buildWaitStats() error { errs := make([]error, 0, len(c.mssqlInstances)) for _, sqlInstance := range c.mssqlInstances { - c.waitStatsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesWaitStats]( - c.mssqlGetPerfObjectName(sqlInstance.name, "Wait Statistics"), pdh.InstancesAll, - ) + c.waitStatsPerfDataCollectors[sqlInstance.name], err = pdh.NewCollector[perfDataCounterValuesWaitStats](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance.name, "Wait Statistics"), pdh.InstancesAll) if err != nil { errs = append(errs, fmt.Errorf("failed to create Wait Statistics collector for instance %s: %w", sqlInstance.name, err)) } diff --git a/internal/collector/net/net.go b/internal/collector/net/net.go index 5fabbcf1f..3703de9c2 100644 --- a/internal/collector/net/net.go +++ b/internal/collector/net/net.go @@ -159,7 +159,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("Network Interface", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Network Interface", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Network Interface collector: %w", err) } diff --git a/internal/collector/nps/nps.go b/internal/collector/nps/nps.go index 2a8bf163a..abaec15fd 100644 --- a/internal/collector/nps/nps.go +++ b/internal/collector/nps/nps.go @@ -98,12 +98,12 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { errs := make([]error, 0, 2) - c.accessPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesAccess]("NPS Authentication Server", nil) + c.accessPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesAccess](pdh.CounterTypeRaw, "NPS Authentication Server", nil) if err != nil { errs = append(errs, fmt.Errorf("failed to create NPS Authentication Server collector: %w", err)) } - c.accountingPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesAccounting]("NPS Accounting Server", nil) + c.accountingPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesAccounting](pdh.CounterTypeRaw, "NPS Accounting Server", nil) if err != nil { errs = append(errs, fmt.Errorf("failed to create NPS Accounting Server collector: %w", err)) } diff --git a/internal/collector/pagefile/pagefile.go b/internal/collector/pagefile/pagefile.go index 5ce2b3e1d..849e13198 100644 --- a/internal/collector/pagefile/pagefile.go +++ b/internal/collector/pagefile/pagefile.go @@ -76,7 +76,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("Paging File", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Paging File", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Paging File collector: %w", err) } diff --git a/internal/collector/performancecounter/performancecounter.go b/internal/collector/performancecounter/performancecounter.go index b4f5697be..6876292f4 100644 --- a/internal/collector/performancecounter/performancecounter.go +++ b/internal/collector/performancecounter/performancecounter.go @@ -35,7 +35,16 @@ import ( const Name = "performancecounter" -var reNonAlphaNum = regexp.MustCompile(`[^a-zA-Z0-9]`) +var ( + reNonAlphaNum = regexp.MustCompile(`[^a-zA-Z0-9]`) + + //nolint:gochecknoglobals // strings.NewReplacer is safe for concurrent use + stringReplacer = strings.NewReplacer( + "%", "percent", + "(", "", + ")", "", + ) +) type Config struct { Objects []Object `yaml:"objects"` @@ -200,7 +209,11 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { valueType := reflect.StructOf(fields) - collector, err := pdh.NewCollectorWithReflection(object.Object, object.Instances, valueType) + if object.Type == "" { + object.Type = pdh.CounterTypeRaw + } + + collector, err := pdh.NewCollectorWithReflection(object.Type, object.Object, object.Instances, valueType) if err != nil { errs = append(errs, fmt.Errorf("failed collector for %s: %w", object.Name, err)) } @@ -364,5 +377,5 @@ func (c *Collector) collectObject(ch chan<- prometheus.Metric, perfDataObject Ob } func sanitizeMetricName(name string) string { - return strings.Trim(reNonAlphaNum.ReplaceAllString(strings.ToLower(name), "_"), "_") + return strings.Trim(reNonAlphaNum.ReplaceAllString(strings.ToLower(stringReplacer.Replace(name)), "_"), "_") } diff --git a/internal/collector/performancecounter/performancecounter_test_test.go b/internal/collector/performancecounter/performancecounter_test_test.go index a9c541950..07fda4572 100644 --- a/internal/collector/performancecounter/performancecounter_test_test.go +++ b/internal/collector/performancecounter/performancecounter_test_test.go @@ -52,6 +52,7 @@ func TestCollector(t *testing.T) { for _, tc := range []struct { name string object string + counterType pdh.CounterType instances []string instanceLabel string buildErr string @@ -59,11 +60,12 @@ func TestCollector(t *testing.T) { expectedMetrics *regexp.Regexp }{ { - name: "memory", - object: "Memory", - instances: nil, - buildErr: "", - counters: []performancecounter.Counter{{Name: "Available Bytes", Type: "gauge"}}, + name: "memory", + object: "Memory", + counterType: pdh.CounterTypeRaw, + instances: nil, + buildErr: "", + counters: []performancecounter.Counter{{Name: "Available Bytes", Type: "gauge"}}, expectedMetrics: regexp.MustCompile(`^# HELP windows_performancecounter_collector_duration_seconds windows_exporter: Duration of an performancecounter child collection. # TYPE windows_performancecounter_collector_duration_seconds gauge windows_performancecounter_collector_duration_seconds\{collector="memory"} [0-9.e+-]+ @@ -75,11 +77,12 @@ windows_performancecounter_collector_success\{collector="memory"} 1 windows_performancecounter_memory_available_bytes [0-9.e+-]+`), }, { - name: "process", - object: "Process", - instances: []string{"*"}, - buildErr: "", - counters: []performancecounter.Counter{{Name: "Thread Count", Type: "counter"}}, + name: "process", + object: "Process", + counterType: "", + instances: []string{"*"}, + buildErr: "", + counters: []performancecounter.Counter{{Name: "Thread Count", Type: "counter"}}, expectedMetrics: regexp.MustCompile(`^# HELP windows_performancecounter_collector_duration_seconds windows_exporter: Duration of an performancecounter child collection. # TYPE windows_performancecounter_collector_duration_seconds gauge windows_performancecounter_collector_duration_seconds\{collector="process"} [0-9.e+-]+ @@ -94,6 +97,7 @@ windows_performancecounter_process_thread_count\{instance=".+"} [0-9.e+-]+ { name: "processor_information", object: "Processor Information", + counterType: pdh.CounterTypeRaw, instances: []string{"*"}, instanceLabel: "core", buildErr: "", @@ -108,11 +112,32 @@ windows_performancecounter_collector_success\{collector="processor_information"} # TYPE windows_performancecounter_processor_information_processor_time counter windows_performancecounter_processor_information_processor_time\{core="0,0",state="active"} [0-9.e+-]+ windows_performancecounter_processor_information_processor_time\{core="0,0",state="idle"} [0-9.e+-]+ +.*`), + }, + { + name: "processor_information_formatted", + object: "Processor Information", + counterType: pdh.CounterTypeFormatted, + instances: []string{"*"}, + instanceLabel: "core", + buildErr: "", + counters: []performancecounter.Counter{{Name: "% Processor Time", Metric: "windows_performancecounter_processor_information_processor_time", Labels: map[string]string{"state": "active"}}, {Name: "% Idle Time", Metric: "windows_performancecounter_processor_information_processor_time", Labels: map[string]string{"state": "idle"}}}, + expectedMetrics: regexp.MustCompile(`^# HELP windows_performancecounter_collector_duration_seconds windows_exporter: Duration of an performancecounter child collection. +# TYPE windows_performancecounter_collector_duration_seconds gauge +windows_performancecounter_collector_duration_seconds\{collector="processor_information_formatted"} [0-9.e+-]+ +# HELP windows_performancecounter_collector_success windows_exporter: Whether a performancecounter child collector was successful. +# TYPE windows_performancecounter_collector_success gauge +windows_performancecounter_collector_success\{collector="processor_information_formatted"} 1 +# HELP windows_performancecounter_processor_information_processor_time windows_exporter: custom Performance Counter metric +# TYPE windows_performancecounter_processor_information_processor_time gauge +windows_performancecounter_processor_information_processor_time\{core="0,0",state="active"} [0-9]+ +windows_performancecounter_processor_information_processor_time\{core="0,0",state="idle"} [0-9]+ .*`), }, { name: "", object: "Processor Information", + counterType: pdh.CounterTypeRaw, instances: nil, instanceLabel: "", buildErr: "object name is required", @@ -122,6 +147,7 @@ windows_performancecounter_processor_information_processor_time\{core="0,0",stat { name: "double_counter", object: "Memory", + counterType: pdh.CounterTypeRaw, instances: nil, buildErr: "counter name Available Bytes is duplicated", counters: []performancecounter.Counter{{Name: "Available Bytes", Type: "gauge"}, {Name: "Available Bytes", Type: "gauge"}}, @@ -130,11 +156,21 @@ windows_performancecounter_processor_information_processor_time\{core="0,0",stat { name: "counter with spaces and brackets", object: "invalid", + counterType: pdh.CounterTypeRaw, instances: nil, buildErr: pdh.NewPdhError(pdh.CstatusNoObject).Error(), counters: []performancecounter.Counter{{Name: "Total Memory Usage --- Non-Paged Pool", Type: "counter"}, {Name: "Max Session Input Delay (ms)", Type: "counter"}}, expectedMetrics: nil, }, + { + name: "invalid counter type", + object: "invalid", + counterType: "invalid", + instances: nil, + buildErr: "invalid result type: ", + counters: []performancecounter.Counter{{Name: "Total Memory Usage --- Non-Paged Pool", Type: "counter"}, {Name: "Max Session Input Delay (ms)", Type: "counter"}}, + expectedMetrics: nil, + }, } { t.Run(tc.name, func(t *testing.T) { t.Parallel() @@ -144,6 +180,7 @@ windows_performancecounter_processor_information_processor_time\{core="0,0",stat { Name: tc.name, Object: tc.object, + Type: tc.counterType, Instances: tc.instances, InstanceLabel: tc.instanceLabel, Counters: tc.counters, diff --git a/internal/collector/performancecounter/types.go b/internal/collector/performancecounter/types.go index 2034f01a0..b57097e58 100644 --- a/internal/collector/performancecounter/types.go +++ b/internal/collector/performancecounter/types.go @@ -20,11 +20,12 @@ import ( ) type Object struct { - Name string `json:"name" yaml:"name"` - Object string `json:"object" yaml:"object"` - Instances []string `json:"instances" yaml:"instances"` - Counters []Counter `json:"counters" yaml:"counters"` - InstanceLabel string `json:"instance_label" yaml:"instance_label"` //nolint:tagliatelle + Name string `json:"name" yaml:"name"` + Object string `json:"object" yaml:"object"` + Type pdh.CounterType `json:"type" yaml:"type"` + Instances []string `json:"instances" yaml:"instances"` + Counters []Counter `json:"counters" yaml:"counters"` + InstanceLabel string `json:"instance_label" yaml:"instance_label"` //nolint:tagliatelle collector *pdh.Collector perfDataObject any diff --git a/internal/collector/physical_disk/physical_disk.go b/internal/collector/physical_disk/physical_disk.go index e8e23fbf1..431aad5a8 100644 --- a/internal/collector/physical_disk/physical_disk.go +++ b/internal/collector/physical_disk/physical_disk.go @@ -129,7 +129,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("PhysicalDisk", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "PhysicalDisk", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create PhysicalDisk collector: %w", err) } diff --git a/internal/collector/process/process.go b/internal/collector/process/process.go index 9bf087536..eef2ca162 100644 --- a/internal/collector/process/process.go +++ b/internal/collector/process/process.go @@ -175,7 +175,7 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error { c.miSession = miSession c.collectorVersion = 2 - c.perfDataCollectorV2, err = pdh.NewCollector[perfDataCounterValuesV2]("Process V2", pdh.InstancesAll) + c.perfDataCollectorV2, err = pdh.NewCollector[perfDataCounterValuesV2](pdh.CounterTypeRaw, "Process V2", pdh.InstancesAll) if errors.Is(err, pdh.NewPdhError(pdh.CstatusNoObject)) { c.collectorVersion = 1 diff --git a/internal/collector/remote_fx/remote_fx.go b/internal/collector/remote_fx/remote_fx.go index 197cda10d..d43197d60 100644 --- a/internal/collector/remote_fx/remote_fx.go +++ b/internal/collector/remote_fx/remote_fx.go @@ -104,12 +104,12 @@ func (c *Collector) Close() error { func (c *Collector) Build(*slog.Logger, *mi.Session) error { var err error - c.perfDataCollectorNetwork, err = pdh.NewCollector[perfDataCounterValuesNetwork]("RemoteFX Network", pdh.InstancesAll) + c.perfDataCollectorNetwork, err = pdh.NewCollector[perfDataCounterValuesNetwork](pdh.CounterTypeRaw, "RemoteFX Network", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create RemoteFX Network collector: %w", err) } - c.perfDataCollectorGraphics, err = pdh.NewCollector[perfDataCounterValuesGraphics]("RemoteFX Graphics", pdh.InstancesAll) + c.perfDataCollectorGraphics, err = pdh.NewCollector[perfDataCounterValuesGraphics](pdh.CounterTypeRaw, "RemoteFX Graphics", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create RemoteFX Graphics collector: %w", err) } diff --git a/internal/collector/smb/smb.go b/internal/collector/smb/smb.go index 86eb53fbe..bc9a183e7 100644 --- a/internal/collector/smb/smb.go +++ b/internal/collector/smb/smb.go @@ -78,7 +78,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("SMB Server Shares", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "SMB Server Shares", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create SMB Server Shares collector: %w", err) } diff --git a/internal/collector/smbclient/smbclient.go b/internal/collector/smbclient/smbclient.go index 3c514aaa3..c6d117049 100644 --- a/internal/collector/smbclient/smbclient.go +++ b/internal/collector/smbclient/smbclient.go @@ -93,7 +93,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("SMB Client Shares", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "SMB Client Shares", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create SMB Client Shares collector: %w", err) } diff --git a/internal/collector/smtp/smtp.go b/internal/collector/smtp/smtp.go index 0c2c984b6..e00490678 100644 --- a/internal/collector/smtp/smtp.go +++ b/internal/collector/smtp/smtp.go @@ -159,7 +159,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("SMTP Server", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "SMTP Server", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create SMTP Server collector: %w", err) } diff --git a/internal/collector/system/system.go b/internal/collector/system/system.go index 0557c3da5..dec0eedda 100644 --- a/internal/collector/system/system.go +++ b/internal/collector/system/system.go @@ -79,7 +79,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("System", nil) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "System", nil) if err != nil { return fmt.Errorf("failed to create System collector: %w", err) } diff --git a/internal/collector/tcp/tcp.go b/internal/collector/tcp/tcp.go index c9ed665b3..b54c05136 100644 --- a/internal/collector/tcp/tcp.go +++ b/internal/collector/tcp/tcp.go @@ -120,12 +120,12 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector4, err = pdh.NewCollector[perfDataCounterValues]("TCPv4", nil) + c.perfDataCollector4, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "TCPv4", nil) if err != nil { return fmt.Errorf("failed to create TCPv4 collector: %w", err) } - c.perfDataCollector6, err = pdh.NewCollector[perfDataCounterValues]("TCPv6", nil) + c.perfDataCollector6, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "TCPv6", nil) if err != nil { return fmt.Errorf("failed to create TCPv6 collector: %w", err) } diff --git a/internal/collector/terminal_services/terminal_services.go b/internal/collector/terminal_services/terminal_services.go index f9f6af282..1b479b90c 100644 --- a/internal/collector/terminal_services/terminal_services.go +++ b/internal/collector/terminal_services/terminal_services.go @@ -141,7 +141,7 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error { var err error - c.perfDataCollectorTerminalServicesSession, err = pdh.NewCollector[perfDataCounterValuesTerminalServicesSession]("Terminal Services Session", pdh.InstancesAll) + c.perfDataCollectorTerminalServicesSession, err = pdh.NewCollector[perfDataCounterValuesTerminalServicesSession](pdh.CounterTypeRaw, "Terminal Services Session", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Terminal Services Session collector: %w", err) } @@ -151,7 +151,7 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error { if c.connectionBrokerEnabled { var err error - c.perfDataCollectorBroker, err = pdh.NewCollector[perfDataCounterValuesBroker]("Remote Desktop Connection Broker Counterset", pdh.InstancesAll) + c.perfDataCollectorBroker, err = pdh.NewCollector[perfDataCounterValuesBroker](pdh.CounterTypeRaw, "Remote Desktop Connection Broker Counterset", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Remote Desktop Connection Broker Counterset collector: %w", err) } diff --git a/internal/collector/thermalzone/thermalzone.go b/internal/collector/thermalzone/thermalzone.go index bea13e14f..0f14ba734 100644 --- a/internal/collector/thermalzone/thermalzone.go +++ b/internal/collector/thermalzone/thermalzone.go @@ -72,7 +72,7 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("Thermal Zone Information", pdh.InstancesAll) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Thermal Zone Information", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create Thermal Zone Information collector: %w", err) } diff --git a/internal/collector/time/time.go b/internal/collector/time/time.go index 5a98a31a0..40b055c8c 100644 --- a/internal/collector/time/time.go +++ b/internal/collector/time/time.go @@ -127,7 +127,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues]("Windows Time Service", nil) + c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Windows Time Service", nil) if err != nil { return fmt.Errorf("failed to create Windows Time Service collector: %w", err) } diff --git a/internal/collector/udp/udp.go b/internal/collector/udp/udp.go index 6f8ef7664..aac6a4e93 100644 --- a/internal/collector/udp/udp.go +++ b/internal/collector/udp/udp.go @@ -82,12 +82,12 @@ func (c *Collector) Close() error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { var err error - c.perfDataCollector4, err = pdh.NewCollector[perfDataCounterValues]("UDPv4", nil) + c.perfDataCollector4, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "UDPv4", nil) if err != nil { return fmt.Errorf("failed to create UDPv4 collector: %w", err) } - c.perfDataCollector6, err = pdh.NewCollector[perfDataCounterValues]("UDPv6", nil) + c.perfDataCollector6, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "UDPv6", nil) if err != nil { return fmt.Errorf("failed to create UDPv6 collector: %w", err) } diff --git a/internal/collector/vmware/vmware.go b/internal/collector/vmware/vmware.go index a34ec44d7..22be6dd8d 100644 --- a/internal/collector/vmware/vmware.go +++ b/internal/collector/vmware/vmware.go @@ -98,12 +98,12 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { errs []error ) - c.perfDataCollectorCPU, err = pdh.NewCollector[perfDataCounterValuesCPU]("VM Processor", pdh.InstancesTotal) + c.perfDataCollectorCPU, err = pdh.NewCollector[perfDataCounterValuesCPU](pdh.CounterTypeRaw, "VM Processor", pdh.InstancesTotal) if err != nil { errs = append(errs, fmt.Errorf("failed to create VM Processor collector: %w", err)) } - c.perfDataCollectorMemory, err = pdh.NewCollector[perfDataCounterValuesMemory]("VM Memory", nil) + c.perfDataCollectorMemory, err = pdh.NewCollector[perfDataCounterValuesMemory](pdh.CounterTypeRaw, "VM Memory", nil) if err != nil { errs = append(errs, fmt.Errorf("failed to create VM Memory collector: %w", err)) } diff --git a/internal/pdh/collector.go b/internal/pdh/collector.go index 500f0e058..6a8672be0 100644 --- a/internal/pdh/collector.go +++ b/internal/pdh/collector.go @@ -63,13 +63,13 @@ type Counter struct { FieldIndexSecondValue int } -func NewCollector[T any](object string, instances []string) (*Collector, error) { +func NewCollector[T any](resultType CounterType, object string, instances []string) (*Collector, error) { valueType := reflect.TypeFor[T]() - return NewCollectorWithReflection(object, instances, valueType) + return NewCollectorWithReflection(resultType, object, instances, valueType) } -func NewCollectorWithReflection(object string, instances []string, valueType reflect.Type) (*Collector, error) { +func NewCollectorWithReflection(resultType CounterType, object string, instances []string, valueType reflect.Type) (*Collector, error) { var handle pdhQueryHandle if ret := OpenQuery(0, 0, &handle); ret != ErrorSuccess { @@ -80,6 +80,10 @@ func NewCollectorWithReflection(object string, instances []string, valueType ref instances = []string{InstanceEmpty} } + if resultType != CounterTypeRaw && resultType != CounterTypeFormatted { + return nil, fmt.Errorf("invalid result type: %v", resultType) + } + collector := &Collector{ object: object, counters: make(map[string]Counter, valueType.NumField()), @@ -209,7 +213,11 @@ func NewCollectorWithReflection(object string, instances []string, valueType ref collector.collectCh = make(chan any) collector.errorCh = make(chan error) - go collector.collectRoutine() + if resultType == CounterTypeRaw { + go collector.collectWorkerRaw() + } else { + go collector.collectWorkerFormatted() + } // Collect initial data because some counters need to be read twice to get the correct value. collectValues := reflect.New(reflect.SliceOf(valueType)).Elem() @@ -254,7 +262,7 @@ func (c *Collector) Collect(dst any) error { return <-c.errorCh } -func (c *Collector) collectRoutine() { +func (c *Collector) collectWorkerRaw() { var ( err error itemCount uint32 @@ -310,7 +318,11 @@ func (c *Collector) collectRoutine() { break } - if err := NewPdhError(ret); ret != MoreData && !isKnownCounterDataError(err) { + if err := NewPdhError(ret); ret != MoreData { + if isKnownCounterDataError(err) { + break + } + return fmt.Errorf("GetRawCounterArray: %w", err) } @@ -411,6 +423,142 @@ func (c *Collector) collectRoutine() { } } +func (c *Collector) collectWorkerFormatted() { + var ( + err error + itemCount uint32 + items []FmtCounterValueItemDouble + bytesNeeded uint32 + ) + + buf := make([]byte, 1) + + for data := 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.Ptr || 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() + + indexMap := map[string]int{} + stringMap := map[*uint16]string{} + + for _, counter := range c.counters { + for _, instance := range counter.Instances { + // Get the info with the current buffer size + bytesNeeded = uint32(cap(buf)) + + for { + ret := GetFormattedCounterArrayDouble(instance, &bytesNeeded, &itemCount, &buf[0]) + + if ret == ErrorSuccess { + break + } + + if err := NewPdhError(ret); ret != MoreData { + if isKnownCounterDataError(err) { + break + } + + return fmt.Errorf("GetFormattedCounterArrayDouble: %w", err) + } + + if bytesNeeded <= uint32(cap(buf)) { + return fmt.Errorf("GetFormattedCounterArrayDouble reports buffer too small (%d), but buffer is large enough (%d): %w", uint32(cap(buf)), bytesNeeded, NewPdhError(ret)) + } + + buf = make([]byte, bytesNeeded) + } + + items = unsafe.Slice((*FmtCounterValueItemDouble)(unsafe.Pointer(&buf[0])), itemCount) + + var ( + instanceName string + ok bool + ) + + for _, item := range items { + if item.FmtValue.CStatus != CstatusValidData && item.FmtValue.CStatus != CstatusNewData { + continue + } + + if instanceName, ok = stringMap[item.SzName]; !ok { + instanceName = windows.UTF16PtrToString(item.SzName) + stringMap[item.SzName] = instanceName + } + + if strings.HasSuffix(instanceName, InstanceTotal) && !c.totalCounterRequested { + continue + } + + if instanceName == "" || instanceName == "*" { + instanceName = InstanceEmpty + } + + var ( + index int + ok bool + ) + + if index, ok = indexMap[instanceName]; !ok { + index = dv.Len() + 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)) + } + + if counter.FieldIndexValue != -1 { + dv.Index(index). + Field(counter.FieldIndexValue). + SetFloat(item.FmtValue.DoubleValue) + } + } + } + } + + if dv.Len() == 0 { + return ErrNoData + } + + return nil + })() + + c.errorCh <- err + } +} + func (c *Collector) Close() { if c == nil { return diff --git a/internal/pdh/collector_bench_test.go b/internal/pdh/collector_bench_test.go index 70d3ac9ba..873f203eb 100644 --- a/internal/pdh/collector_bench_test.go +++ b/internal/pdh/collector_bench_test.go @@ -56,7 +56,7 @@ type processFull struct { } func BenchmarkTestCollector(b *testing.B) { - performanceData, err := pdh.NewCollector[processFull]("Process", []string{"*"}) + performanceData, err := pdh.NewCollector[processFull](pdh.CounterTypeRaw, "Process", []string{"*"}) require.NoError(b, err) var data []processFull diff --git a/internal/pdh/collector_test.go b/internal/pdh/collector_test.go index 11259a10b..9ae75a89d 100644 --- a/internal/pdh/collector_test.go +++ b/internal/pdh/collector_test.go @@ -44,7 +44,7 @@ func TestCollector(t *testing.T) { t.Run(tc.object, func(t *testing.T) { t.Parallel() - performanceData, err := pdh.NewCollector[process](tc.object, tc.instances) + performanceData, err := pdh.NewCollector[process](pdh.CounterTypeRaw, tc.object, tc.instances) require.NoError(t, err) time.Sleep(100 * time.Millisecond) diff --git a/internal/pdh/pdh.go b/internal/pdh/pdh.go index 6260d476c..2ef8341e2 100644 --- a/internal/pdh/pdh.go +++ b/internal/pdh/pdh.go @@ -452,7 +452,7 @@ func GetFormattedCounterValueDouble(hCounter pdhCounterHandle, lpdwType *uint32, func GetFormattedCounterArrayDouble(hCounter pdhCounterHandle, lpdwBufferSize *uint32, lpdwBufferCount *uint32, itemBuffer *byte) uint32 { ret, _, _ := pdhGetFormattedCounterArrayW.Call( uintptr(hCounter), - uintptr(FmtDouble|FmtNocap100), + uintptr(FmtDouble), uintptr(unsafe.Pointer(lpdwBufferSize)), uintptr(unsafe.Pointer(lpdwBufferCount)), uintptr(unsafe.Pointer(itemBuffer))) diff --git a/internal/pdh/types.go b/internal/pdh/types.go index 5e6efdcbd..a113e6004 100644 --- a/internal/pdh/types.go +++ b/internal/pdh/types.go @@ -20,6 +20,13 @@ import ( "golang.org/x/sys/windows" ) +type CounterType string + +const ( + CounterTypeRaw CounterType = "raw" + CounterTypeFormatted CounterType = "formatted" +) + const ( InstanceEmpty = "------" InstanceTotal = "_Total" diff --git a/pkg/collector/collection.go b/pkg/collector/collection.go index 3bc331cd2..111a22692 100644 --- a/pkg/collector/collection.go +++ b/pkg/collector/collection.go @@ -78,6 +78,7 @@ import ( "github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sys/windows/registry" ) // NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse. @@ -231,6 +232,7 @@ func (c *Collection) Build(logger *slog.Logger) error { for err := range errCh { if errors.Is(err, pdh.ErrNoData) || + errors.Is(err, registry.ErrNotExist) || errors.Is(err, pdh.NewPdhError(pdh.CstatusNoObject)) || errors.Is(err, pdh.NewPdhError(pdh.CstatusNoCounter)) || errors.Is(err, mi.MI_RESULT_INVALID_NAMESPACE) {