Compare commits

...

13 Commits

Author SHA1 Message Date
Jan-Otto Kröpke
4534c2a6ae mssql: fix performance counter with additional server instance (#1753)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-21 22:52:30 +01:00
Jan-Otto Kröpke
3b378136f5 logical_disk: Get Volume ID for NTFS Volume Mounts (#1752)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-21 20:59:11 +01:00
Jan-Otto Kröpke
85845f4780 exchange: Extend Transport Queue metrics (#1749)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-20 02:05:31 +01:00
Jan-Otto Kröpke
fdee2d8613 hyperv: Refactor collector, added DataStore, Virtual SMB and Dynamic Memory Balancer metrics (click PR number for more information) (#1712)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-19 23:36:37 +01:00
Jan-Otto Kröpke
8c90961c10 mssql: expose server version info (#1741)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-19 23:35:55 +01:00
Jan-Otto Kröpke
2335fba18a logicaldisk: fix base counter values (#1747)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-19 21:35:32 +01:00
Jan-Otto Kröpke
c6ee794598 service: fixed buffer too low error (#1745)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-18 17:39:42 +01:00
Jan-Otto Kröpke
9f29fc8a9c service: parallelize api calls (#1744)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-18 02:07:03 +01:00
Jan-Otto Kröpke
e6a15d4ec4 chore: Remove registry based perfdata collector (#1742)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-17 21:51:12 +01:00
Jan-Otto Kröpke
6206b695c6 smb: refactor collector (#1740)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-15 21:27:28 +01:00
Jan-Otto Kröpke
b209ab6d6a smtp: refactor collector (#1739)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-15 20:39:56 +01:00
Jan-Otto Kröpke
78bd720e88 remote_fx: refactor collector (#1738)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-15 19:34:00 +01:00
Jan-Otto Kröpke
a4ec0a96f1 chore: use slog instead gokit for logging style (#1737)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-11-14 23:12:28 +01:00
235 changed files with 13949 additions and 15094 deletions

View File

@@ -23,4 +23,4 @@ jobs:
check_filenames: true
# When using this Action in other repos, the --skip option below can be removed
skip: ./.git,go.mod,go.sum
ignore_words_list: calle
ignore_words_list: calle,Entires

3
.gitignore vendored
View File

@@ -8,4 +8,5 @@ output/
*.syso
installer/*.msi
installer/*.wixpdb
local/
local/
!.idea/inspectionProfiles/Project_Default.xml

View File

@@ -36,7 +36,7 @@ linters-settings:
gci:
sections:
- prefix(github.com/prometheus-community/windows_exporter/internal/initiate)
- prefix(github.com/prometheus-community/windows_exporter/internal/windowsservice)
- standard # Standard section: captures all standard packages.
- default # Default section: contains all imports that could not be matched to another section type.
custom-order: true

View File

@@ -1,14 +1,13 @@
# exchange collector
The exchange collector collects metrics from MS Exchange hosts through perflib
The exchange collector collects metrics from MS Exchange hosts through Performance Counter
=======
|||
-|-
Metric name prefix | `exchange`
Classes | [Win32_PerfRawData_MSExchangeADAccess_MSExchangeADAccessProcesses](https://docs.microsoft.com/en-us/exchange/)<br/> [Win32_PerfRawData_MSExchangeTransportQueues_MSExchangeTransportQueues](https://docs.microsoft.com/en-us/exchange/)<br/> [Win32_PerfRawData_ESE_MSExchangeDatabaseInstances](https://docs.microsoft.com/en-us/exchange/)<br/> [Win32_PerfRawData_MSExchangeHttpProxy_MSExchangeHttpProxy](https://docs.microsoft.com/en-us/exchange/)<br/> [Win32_PerfRawData_MSExchangeActiveSync_MSExchangeActiveSync](https://docs.microsoft.com/en-us/exchange/)<br/> [Win32_PerfRawData_MSExchangeAvailabilityService_MSExchangeAvailabilityService](https://docs.microsoft.com/en-us/exchange/)<br/> [Win32_PerfRawData_MSExchangeOWA_MSExchangeOWA](https://docs.microsoft.com/en-us/exchange/)<br/> [Win32_PerfRawData_MSExchangeAutodiscover_MSExchangeAutodiscover](https://docs.microsoft.com/en-us/exchange/)<br/> [Win32_PerfRawData_MSExchangeWorkloadManagementWorkloads_MSExchangeWorkloadManagementWorkloads](https://docs.microsoft.com/en-us/exchange/)<br/> [Win32_PerfRawData_MSExchangeRpcClientAccess_MSExchangeRpcClientAccess](https://docs.microsoft.com/en-us/exchange/)<br/>
Enabled by default? | No
| | |
|---------------------|---------------------|
| Metric name prefix | `exchange` |
| Source | Performance Counter |
| Enabled by default? | No |
## Flags
@@ -19,45 +18,56 @@ Lists the Perflib Objects that are queried for data along with the perlfib objec
Comma-separated list of collectors to use, for example: `--collectors.exchange.enabled=AvailabilityService,OutlookWebAccess`. Matching is case-sensitive. Depending on the exchange installation not all performance counters are available. Use `--collectors.exchange.list` to obtain a list of supported collectors.
## Metrics
Name | Description
--------------|---------------
`windows_exchange_rpc_avg_latency_sec` | The latency (sec), averaged for the past 1024 packets
`windows_exchange_rpc_requests` | Number of client requests currently being processed by the RPC Client Access service
`windows_exchange_rpc_active_user_count` | Number of unique users that have shown some kind of activity in the last 2 minutes
`windows_exchange_rpc_connection_count` | Total number of client connections maintained
`windows_exchange_rpc_operations_total` | The rate at which RPC operations occur
`windows_exchange_rpc_user_count` | Number of users
`windows_exchange_ldap_read_time_sec` | Time (sec) to send an LDAP read request and receive a response
`windows_exchange_ldap_search_time_sec` | Time (sec) to send an LDAP search request and receive a response
`windows_exchange_ldap_write_time_sec` | Time (sec) to send an LDAP Add/Modify/Delete request and receive a response
`windows_exchange_ldap_timeout_errors_total` | Total number of LDAP timeout errors
`windows_exchange_ldap_long_running_ops_per_sec` | Long Running LDAP operations per second
`windows_exchange_transport_queues_external_active_remote_delivery` | External Active Remote Delivery Queue length
`windows_exchange_transport_queues_internal_active_remote_delivery` | Internal Active Remote Delivery Queue length
`windows_exchange_transport_queues_active_mailbox_delivery` | Active Mailbox Delivery Queue length
`windows_exchange_transport_queues_retry_mailbox_delivery` | Retry Mailbox Delivery Queue length
`windows_exchange_transport_queues_unreachable` | Unreachable Queue length
`windows_exchange_transport_queues_external_largest_delivery` | External Largest Delivery Queue length
`windows_exchange_transport_queues_internal_largest_delivery` | Internal Largest Delivery Queue length
`windows_exchange_transport_queues_poison` | Poison Queue length
`windows_exchange_http_proxy_mailbox_server_locator_avg_latency_sec` | Average latency (sec) of MailboxServerLocator web service calls
`windows_exchange_http_proxy_avg_auth_latency` | Average time spent authenticating CAS requests over the last 200 samples
`windows_exchange_http_proxy_outstanding_proxy_requests` | Number of concurrent outstanding proxy requests
`windows_exchange_http_proxy_requests_total` | Number of proxy requests processed each second
`windows_exchange_avail_service_requests_per_sec` | Number of requests serviced per second
`windows_exchange_owa_current_unique_users` | Number of unique users currently logged on to Outlook Web App
`windows_exchange_owa_requests_total` | Number of requests handled by Outlook Web App per second
`windows_exchange_autodiscover_requests_total` | Number of autodiscover service requests processed each second
`windows_exchange_workload_active_tasks` | Number of active tasks currently running in the background for workload management
`windows_exchange_workload_completed_tasks` | Number of workload management tasks that have been completed
`windows_exchange_workload_queued_tasks` | Number of workload management tasks that are currently queued up waiting to be processed
`windows_exchange_workload_yielded_tasks` | The total number of tasks that have been yielded by a workload
`windows_exchange_workload_is_active` | Active indicates whether the workload is in an active (1) or paused (0) state
`windows_exchange_activesync_requests_total` | Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load
`windows_exchange_http_proxy_avg_cas_proccessing_latency_sec` | Average latency (sec) of CAS processing time over the last 200 reqs
`windows_exchange_http_proxy_mailbox_proxy_failure_rate` | % of failures between this CAS and MBX servers over the last 200 sample
`windows_exchange_activesync_ping_cmds_pending` | Number of ping commands currently pending in the queue
`windows_exchange_activesync_sync_cmds_total` | Number of sync commands processed per second. Clients use this command to synchronize items within a folder
| Name | Description |
|-----------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|
| `windows_exchange_rpc_avg_latency_sec` | The latency (sec), averaged for the past 1024 packets |
| `windows_exchange_rpc_requests` | Number of client requests currently being processed by the RPC Client Access service |
| `windows_exchange_rpc_active_user_count` | Number of unique users that have shown some kind of activity in the last 2 minutes |
| `windows_exchange_rpc_connection_count` | Total number of client connections maintained |
| `windows_exchange_rpc_operations_total` | The rate at which RPC operations occur |
| `windows_exchange_rpc_user_count` | Number of users |
| `windows_exchange_ldap_read_time_sec` | Time (sec) to send an LDAP read request and receive a response |
| `windows_exchange_ldap_search_time_sec` | Time (sec) to send an LDAP search request and receive a response |
| `windows_exchange_ldap_write_time_sec` | Time (sec) to send an LDAP Add/Modify/Delete request and receive a response |
| `windows_exchange_ldap_timeout_errors_total` | Total number of LDAP timeout errors |
| `windows_exchange_ldap_long_running_ops_per_sec` | Long Running LDAP operations per second |
| `windows_exchange_transport_queues_external_active_remote_delivery` | External Active Remote Delivery Queue length |
| `windows_exchange_transport_queues_internal_active_remote_delivery` | Internal Active Remote Delivery Queue length |
| `windows_exchange_transport_queues_active_mailbox_delivery` | Active Mailbox Delivery Queue length |
| `windows_exchange_transport_queues_retry_mailbox_delivery` | Retry Mailbox Delivery Queue length |
| `windows_exchange_transport_queues_unreachable` | Unreachable Queue length |
| `windows_exchange_transport_queues_external_largest_delivery` | External Largest Delivery Queue length |
| `windows_exchange_transport_queues_internal_largest_delivery` | Internal Largest Delivery Queue length |
| `windows_exchange_transport_queues_poison` | Poison Queue length |
| `windows_exchange_transport_queues_messages_queued_for_delivery_total` | Messages Queued For Delivery Total |
| `windows_exchange_transport_queues_messages_submitted_total` | Messages Submitted Total |
| `windows_exchange_transport_queues_messages_delayed_total` | Messages Delayed Total |
| `windows_exchange_transport_queues_messages_completed_delivery_total` | Messages Completed Delivery Total |
| `windows_exchange_transport_queues_shadow_queue_length` | Shadow Queue Length |
| `windows_exchange_transport_queues_submission_queue_length` | Submission Queue Length |
| `windows_exchange_transport_queues_delay_queue_length` | Delay Queue Length |
| `windows_exchange_transport_queues_items_completed_delivery_total` | Items Completed Delivery Total |
| `windows_exchange_transport_queues_items_queued_for_delivery_expired_total` | Items Queued For Delivery Expired Total |
| `windows_exchange_transport_queues_items_queued_for_delivery_total` | Items Queued For Delivery Total |
| `windows_exchange_transport_queues_items_resubmitted_total` | Items Resubmitted Total |
| `windows_exchange_http_proxy_mailbox_server_locator_avg_latency_sec` | Average latency (sec) of MailboxServerLocator web service calls |
| `windows_exchange_http_proxy_avg_auth_latency` | Average time spent authenticating CAS requests over the last 200 samples |
| `windows_exchange_http_proxy_outstanding_proxy_requests` | Number of concurrent outstanding proxy requests |
| `windows_exchange_http_proxy_requests_total` | Number of proxy requests processed each second |
| `windows_exchange_avail_service_requests_per_sec` | Number of requests serviced per second |
| `windows_exchange_owa_current_unique_users` | Number of unique users currently logged on to Outlook Web App |
| `windows_exchange_owa_requests_total` | Number of requests handled by Outlook Web App per second |
| `windows_exchange_autodiscover_requests_total` | Number of autodiscover service requests processed each second |
| `windows_exchange_workload_active_tasks` | Number of active tasks currently running in the background for workload management |
| `windows_exchange_workload_completed_tasks` | Number of workload management tasks that have been completed |
| `windows_exchange_workload_queued_tasks` | Number of workload management tasks that are currently queued up waiting to be processed |
| `windows_exchange_workload_yielded_tasks` | The total number of tasks that have been yielded by a workload |
| `windows_exchange_workload_is_active` | Active indicates whether the workload is in an active (1) or paused (0) state |
| `windows_exchange_activesync_requests_total` | Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load |
| `windows_exchange_http_proxy_avg_cas_proccessing_latency_sec` | Average latency (sec) of CAS processing time over the last 200 reqs |
| `windows_exchange_http_proxy_mailbox_proxy_failure_rate` | % of failures between this CAS and MBX servers over the last 200 sample |
| `windows_exchange_activesync_ping_cmds_pending` | Number of ping commands currently pending in the queue |
| `windows_exchange_activesync_sync_cmds_total` | Number of sync commands processed per second. Clients use this command to synchronize items within a folder |
### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_

View File

@@ -2,110 +2,262 @@
The hyperv collector exposes metrics about the Hyper-V hypervisor
|||
-|-
Metric name prefix | `hyperv`
Classes | `Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary`<br/>`Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition`<br/>`Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition`<br/>`Win32_PerfRawData_HvStats_HyperVHypervisor`<br/>`Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor`<br/>`Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor`<br/>`Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor`<br/>`Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch`<br/>`Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter`<br/>`Win32_PerfRawData_Counters_HyperVVirtualStorageDevice`<br/>`Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter`
Enabled by default? | No
| | |
|---------------------|----------------------|
| Metric name prefix | `hyperv` |
| Source | Performance counters |
| Enabled by default? | No |
## Flags
None
### `--collectors.hyperv.enabled`
Comma-separated list of collectors to use, for example:
`--collectors.hyperv.enabled=dynamic_memory_balancer,dynamic_memory_vm,hypervisor_logical_processor,hypervisor_root_partition,hypervisor_root_virtual_processor,hypervisor_virtual_processor,legacy_network_adapter,virtual_machine_health_summary,virtual_machine_vid_partition,virtual_network_adapter,virtual_storage_device,virtual_switch`.
Matching is case-sensitive.
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`windows_hyperv_health_critical` | _Not yet documented_ | counter | None
`windows_hyperv_health_ok` | _Not yet documented_ | counter | None
`windows_hyperv_vid_physical_pages_allocated` | _Not yet documented_ | counter | `vm`
`windows_hyperv_vid_preferred_numa_node_index` | _Not yet documented_ | counter | `vm`
`windows_hyperv_vid_remote_physical_pages` | _Not yet documented_ | counter | `vm`
`windows_hyperv_root_partition_address_spaces` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_attached_devices` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_deposited_pages` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_device_dma_errors` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_device_interrupt_errors` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_device_interrupt_mappings` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_device_interrupt_throttle_events` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_preferred_numa_node_index` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_gpa_space_modifications` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_io_tlb_flush_cost` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_io_tlb_flush` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_recommended_virtual_tlb_size` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_physical_pages_allocated` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_1G_device_pages` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_1G_gpa_pages` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_2M_device_pages` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_2M_gpa_pages` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_4K_device_pages` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_4K_gpa_pages` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_virtual_tlb_flush_entires` | _Not yet documented_ | counter | None
`windows_hyperv_root_partition_virtual_tlb_pages` | _Not yet documented_ | counter | None
`windows_hyperv_hypervisor_virtual_processors` | _Not yet documented_ | counter | None
`windows_hyperv_hypervisor_logical_processors` | _Not yet documented_ | counter | None
`windows_hyperv_host_lp_guest_run_time_percent` | _Not yet documented_ | counter | `core`
`windows_hyperv_host_lp_hypervisor_run_time_percent` | _Not yet documented_ | counter | `core`
`windows_hyperv_host_lp_total_run_time_percent` | _Not yet documented_ | counter | `core`
`windows_hyperv_host_cpu_guest_run_time` | _Not yet documented_ | counter | `core`
`windows_hyperv_host_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `core`
`windows_hyperv_host_cpu_remote_run_time` | _Not yet documented_ | counter | `core`
`windows_hyperv_host_cpu_total_run_time` | _Not yet documented_ | counter | `core`
`windows_hyperv_host_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `core`
`windows_hyperv_vm_cpu_guest_run_time` | _Not yet documented_ | counter | `vm`, `core`
`windows_hyperv_vm_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `vm`, `core`
`windows_hyperv_vm_cpu_remote_run_time` | _Not yet documented_ | counter | `vm`, `core`
`windows_hyperv_vm_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `vm`, `core`
`windows_hyperv_vm_memory_added_total` | _Not yet documented_ | counter | `vm`
`windows_hyperv_vm_memory_pressure_average` | _Not yet documented_ | gauge | `vm`
`windows_hyperv_vm_memory_pressure_current` | _Not yet documented_ | counter | `vm`
`windows_hyperv_vm_memory_physical_guest_visible` | _Not yet documented_ | gauge | `vm`
`windows_hyperv_vm_memory_pressure_maximum` | _Not yet documented_ | gauge | `vm`
`windows_hyperv_vm_memory_add_operations_total` | _Not yet documented_ | counter | `vm`
`windows_hyperv_vm_memory_remove_operations_total` | _Not yet documented_ | counter | `vm`
`windows_hyperv_vm_memory_pressure_minumim` | _Not yet documented_ | gauge | `vm`
`windows_hyperv_vm_memory_physical` | _Not yet documented_ | gauge | `vm`
`windows_hyperv_vm_memory_removed_total` | _Not yet documented_ | counter | `vm`
`windows_hyperv_vm_cpu_total_run_time` | _Not yet documented_ | counter | `vm`, `core`
`windows_hyperv_vswitch_broadcast_packets_received_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_broadcast_packets_sent_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_bytes_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_bytes_received_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_bytes_sent_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_directed_packets_received_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_directed_packets_send_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_dropped_packets_incoming_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_dropped_packets_outcoming_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_extensions_dropped_packets_incoming_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_extensions_dropped_packets_outcoming_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_learned_mac_addresses_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_multicast_packets_received_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_multicast_packets_sent_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_number_of_send_channel_moves_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_number_of_vmq_moves_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_packets_flooded_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_packets_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_packets_received_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_packets_sent_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_vswitch_purged_mac_addresses_total` | _Not yet documented_ | counter | `vswitch`
`windows_hyperv_ethernet_bytes_dropped` | _Not yet documented_ | counter | `adapter`
`windows_hyperv_ethernet_bytes_received` | _Not yet documented_ | counter | `adapter`
`windows_hyperv_ethernet_bytes_sent` | _Not yet documented_ | counter | `adapter`
`windows_hyperv_ethernet_frames_dropped` | _Not yet documented_ | counter | `adapter`
`windows_hyperv_ethernet_frames_received` | _Not yet documented_ | counter | `adapter`
`windows_hyperv_ethernet_frames_sent` | _Not yet documented_ | counter | `adapter`
`windows_hyperv_vm_device_error_count` | _Not yet documented_ | counter | `vm_device`
`windows_hyperv_vm_device_queue_length` | _Not yet documented_ | counter | `vm_device`
`windows_hyperv_vm_device_bytes_read` | _Not yet documented_ | counter | `vm_device`
`windows_hyperv_vm_device_operations_read` | _Not yet documented_ | counter | `vm_device`
`windows_hyperv_vm_device_bytes_written` | _Not yet documented_ | counter | `vm_device`
`windows_hyperv_vm_device_operations_written` | _Not yet documented_ | counter | `vm_device`
`windows_hyperv_vm_interface_bytes_received` | _Not yet documented_ | counter | `vm_interface`
`windows_hyperv_vm_interface_bytes_sent` | _Not yet documented_ | counter | `vm_interface`
`windows_hyperv_vm_interface_packets_incoming_dropped` | _Not yet documented_ | counter | `vm_interface`
`windows_hyperv_vm_interface_packets_outgoing_dropped` | _Not yet documented_ | counter | `vm_interface`
`windows_hyperv_vm_interface_packets_received` | _Not yet documented_ | counter | `vm_interface`
`windows_hyperv_vm_interface_packets_sent` | _Not yet documented_ | counter | `vm_interface`
### Hyper-V Datastore
### Hyper-V Datastore Metrics Documentation
This documentation outlines the available metrics for monitoring Hyper-V Datastore performance and resource usage using Prometheus. All metrics are prefixed with `windows_hyperv_datastore`.
| Metric Name | Description | Type | Labels |
|------------------------------------------------------------------------|---------------------------------------------------------------------------------|---------|-----------|
| `windows_hyperv_datastore_fragmentation_ratio` | Represents the fragmentation ratio of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_sector_size_bytes` | Represents the sector size of the DataStore in bytes. | gauge | datastore |
| `windows_hyperv_datastore_data_alignment_bytes` | Represents the data alignment of the DataStore in bytes. | gauge | datastore |
| `windows_hyperv_datastore_current_replay_log_size_bytes` | Represents the current replay log size of the DataStore in bytes. | gauge | datastore |
| `windows_hyperv_datastore_available_entries` | Represents the number of available entries inside object tables. | gauge | datastore |
| `windows_hyperv_datastore_empty_entries` | Represents the number of empty entries inside object tables. | gauge | datastore |
| `windows_hyperv_datastore_free_bytes` | Represents the number of free bytes inside key tables. | gauge | datastore |
| `windows_hyperv_datastore_data_end_bytes` | Represents the data end of the DataStore in bytes. | gauge | datastore |
| `windows_hyperv_datastore_file_objects` | Represents the number of file objects in the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_object_tables` | Represents the number of object tables in the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_key_tables` | Represents the number of key tables in the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_file_data_size_bytes` | Represents the file data size in bytes of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_table_data_size_bytes` | Represents the table data size in bytes of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_names_size_bytes` | Represents the names size in bytes of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_number_of_keys` | Represents the number of keys in the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_reconnect_latency_microseconds` | Represents the reconnect latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_disconnect_count` | Represents the disconnect count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_write_to_file_byte_latency_microseconds` | Represents the write-to-file byte latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_write_to_file_byte_count` | Represents the write-to-file byte count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_write_to_file_count` | Represents the write-to-file count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_read_from_file_byte_latency_microseconds` | Represents the read-from-file byte latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_read_from_file_byte_count` | Represents the read-from-file byte count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_read_from_file_count` | Represents the read-from-file count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_write_to_storage_byte_latency_microseconds` | Represents the write-to-storage byte latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_write_to_storage_byte_count` | Represents the write-to-storage byte count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_write_to_storage_count` | Represents the write-to-storage count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_read_from_storage_byte_latency_microseconds` | Represents the read-from-storage byte latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_read_from_storage_byte_count` | Represents the read-from-storage byte count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_read_from_storage_count` | Represents the read-from-storage count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_commit_byte_latency_microseconds` | Represents the commit byte latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_commit_byte_count` | Represents the commit byte count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_commit_count` | Represents the commit count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_cache_update_operation_latency_microseconds` | Represents the cache update operation latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_cache_update_operation_count` | Represents the cache update operation count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_commit_operation_latency_microseconds` | Represents the commit operation latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_commit_operation_count` | Represents the commit operation count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_compact_operation_latency_microseconds` | Represents the compact operation latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_compact_operation_count` | Represents the compact operation count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_load_file_operation_latency_microseconds` | Represents the load file operation latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_load_file_operation_count` | Represents the load file operation count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_remove_operation_latency_microseconds` | Represents the remove operation latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_remove_operation_count` | Represents the remove operation count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_query_size_operation_latency_microseconds` | Represents the query size operation latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_query_size_operation_count` | Represents the query size operation count of the DataStore. | counter | datastore |
| `windows_hyperv_datastore_set_operation_latency_microseconds` | Represents the set operation latency in microseconds of the DataStore. | gauge | datastore |
| `windows_hyperv_datastore_set_operation_count` | Represents the set operation count of the DataStore. | counter | datastore |
### Hyper-V Dynamic Memory Balancer
Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012
| Name | Description | Type | Labels |
|-------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|-------|------------|
| `windows_hyperv_dynamic_memory_balancer_available_memory_bytes` | Represents the amount of memory left on the node. | gauge | `balancer` |
| `windows_hyperv_dynamic_memory_balancer_available_memory_for_balancing_bytes` | Represents the available memory for balancing purposes. | gauge | `balancer` |
| `windows_hyperv_dynamic_memory_balancer_average_pressure_ratio` | Represents the average system pressure on the balancer node among all balanced objects. | gauge | `balancer` |
| `windows_hyperv_dynamic_memory_balancer_system_current_pressure_ratio` | Represents the current pressure in the system. | gauge | `balancer` |
### Hyper-V Dynamic Memory VM
| Name | Description | Type | Labels |
|------------------------------------------------------------------------|-----------------------------------------------------------------------------------|---------|--------|
| `windows_hyperv_dynamic_memory_vm_added_bytes_total` | Represents the cumulative amount of memory added to the VM. | counter | `vm` |
| `windows_hyperv_dynamic_memory_vm_pressure_current_ratio` | Represents the current pressure in the VM. | gauge | `vm` |
| `windows_hyperv_dynamic_memory_vm_guest_available_bytes` | Represents the current amount of available memory in the VM (reported by the VM). | gauge | `vm` |
| `windows_hyperv_dynamic_memory_vm_guest_visible_physical_memory_bytes` | Represents the amount of memory visible in the VM | gauge | `vm` |
| `windows_hyperv_dynamic_memory_vm_pressure_maximum_ratio` | Represents the maximum pressure band in the VM. | gauge | `vm` |
| `windows_hyperv_dynamic_memory_vm_add_operations_total` | Represents the total number of add operations for the VM. | counter | `vm` |
| `windows_hyperv_dynamic_memory_vm_remove_operations_total` | Represents the total number of remove operations for the VM. | counter | `vm` |
| `windows_hyperv_dynamic_memory_vm_pressure_minimum_ratio` | Represents the minimum pressure band in the VM. | gauge | `vm` |
| `windows_hyperv_dynamic_memory_vm_physical` | Represents the current amount of memory in the VM. | gauge | `vm` |
| `windows_hyperv_dynamic_memory_vm_removed_bytes_total` | Represents the cumulative amount of memory removed from the VM. | counter | `vm` |
### Hyper-V Hypervisor Logical Processor
| Name | Description | Type | Labels |
|----------------------------------------------------------------------|------------------------------------------------------------------------|---------|----------------|
| `windows_hyperv_hypervisor_logical_processor_time_total` | Time that processor spent in different modes (hypervisor, guest, idle) | counter | `core`.`state` |
| `windows_hyperv_hypervisor_logical_processor_context_switches_total` | The rate of virtual processor context switches on the processor. | counter | `core` |
### Hyper-V Hypervisor Root Partition
| Name | Description | Type | Labels |
|------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|
| `windows_hyperv_root_partition_address_spaces` | The number of address spaces in the virtual TLB of the partition | gauge | None |
| `windows_hyperv_root_partition_attached_devices` | The number of devices attached to the partition | gauge | None |
| `windows_hyperv_root_partition_deposited_pages` | The number of pages deposited into the partition | gauge | None |
| `windows_hyperv_root_partition_device_dma_errors` | An indicator of illegal DMA requests generated by all devices assigned to the partition | gauge | None |
| `windows_hyperv_root_partition_device_interrupt_errors` | An indicator of illegal interrupt requests generated by all devices assigned to the partition | gauge | None |
| `windows_hyperv_root_partition_device_interrupt_mappings` | The number of device interrupt mappings used by the partition | gauge | None |
| `windows_hyperv_root_partition_device_interrupt_throttle_events` | The number of times an interrupt from a device assigned to the partition was temporarily throttled because the device was generating too many interrupts | gauge | None |
| `windows_hyperv_root_partition_preferred_numa_node_index` | The number of pages present in the GPA space of the partition (zero for root partition) | gauge | None |
| `windows_hyperv_root_partition_gpa_space_modifications` | The rate of modifications to the GPA space of the partition | counter | None |
| `windows_hyperv_root_partition_io_tlb_flush_cost` | The average time (in nanoseconds) spent processing an I/O TLB flush | gauge | None |
| `windows_hyperv_root_partition_io_tlb_flush` | The rate of flushes of I/O TLBs of the partition | counter | None |
| `windows_hyperv_root_partition_recommended_virtual_tlb_size` | The recommended number of pages to be deposited for the virtual TLB | gauge | None |
| `windows_hyperv_root_partition_physical_pages_allocated` | The number of timer interrupts skipped for the partition | gauge | None |
| `windows_hyperv_root_partition_1G_device_pages` | The number of 1G pages present in the device space of the partition | gauge | None |
| `windows_hyperv_root_partition_1G_gpa_pages` | The number of 1G pages present in the GPA space of the partition | gauge | None |
| `windows_hyperv_root_partition_2M_device_pages` | The number of 2M pages present in the device space of the partition | gauge | None |
| `windows_hyperv_root_partition_2M_gpa_pages` | The number of 2M pages present in the GPA space of the partition | gauge | None |
| `windows_hyperv_root_partition_4K_device_pages` | The number of 4K pages present in the device space of the partition | gauge | None |
| `windows_hyperv_root_partition_4K_gpa_pages` | The number of 4K pages present in the GPA space of the partition | gauge | None |
| `windows_hyperv_root_partition_virtual_tlb_flush_entries` | The rate of flushes of the entire virtual TLB | counter | None |
| `windows_hyperv_root_partition_virtual_tlb_pages` | The number of pages used by the virtual TLB of the partition | gauge | None |
### Hyper-V Hypervisor Root Virtual Processor
| Name | Description | Type | Labels |
|---------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|---------|----------------|
| `windows_hyperv_hypervisor_root_virtual_processor_time_total` | Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote, total) | counter | `core`.`state` |
| `windows_hyperv_hypervisor_root_virtual_cpu_wait_time_per_dispatch_total` | The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor | counter | `core` |
### Hyper-V Legacy Network Adapter
| Name | Description | Type | Labels |
|---------------------------------------------------------------|-------------------------------------------------------------------------|---------|-----------|
| `windows_hyperv_legacy_network_adapter_bytes_dropped_total` | Bytes Dropped is the number of bytes dropped on the network adapter | counter | `adapter` |
| `windows_hyperv_legacy_network_adapter_bytes_received_total` | Bytes received is the number of bytes received on the network adapter | counter | `adapter` |
| `windows_hyperv_legacy_network_adapter_bytes_sent_total` | Bytes sent is the number of bytes sent over the network adapter | counter | `adapter` |
| `windows_hyperv_legacy_network_adapter_frames_dropped_total` | Frames Dropped is the number of frames dropped on the network adapter | counter | `adapter` |
| `windows_hyperv_legacy_network_adapter_frames_received_total` | Frames received is the number of frames received on the network adapter | counter | `adapter` |
| `windows_hyperv_legacy_network_adapter_frames_sent_total` | Frames sent is the number of frames sent over the network adapter | counter | `adapter` |
### Hyper-V Hypervisor Virtual Processor
| Name | Description | Type | Labels |
|--------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|---------|--------------|
| `windows_hyperv_hypervisor_virtual_processor_time_total` | Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote) | counter | `vm`, `core` |
| `windows_hyperv_hypervisor_virtual_processor_total_run_time_total` | Time that processor spent | counter | `vm`, `core` |
| `windows_hyperv_hypervisor_virtual_processor_cpu_wait_time_per_dispatch_total` | The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor. | counter | `vm`, `core` |
### Hyper-V Virtual Network Adapter
| Name | Description | Type | Labels |
|-------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|---------|-----------|
| `windows_hyperv_virtual_network_adapter_received_bytes_total` | Represents the total number of bytes received per second by the network adapter | counter | `adapter` |
| `windows_hyperv_virtual_network_adapter_sent_bytes_total` | Represents the total number of bytes sent per second by the network adapter | counter | `adapter` |
| `windows_hyperv_virtual_network_adapter_incoming_dropped_packets_total` | Represents the total number of dropped packets per second in the incoming direction of the network adapter | counter | `adapter` |
| `windows_hyperv_virtual_network_adapter_outgoing_dropped_packets_total` | Represents the total number of dropped packets per second in the outgoing direction of the network adapter | counter | `adapter` |
| `windows_hyperv_virtual_network_adapter_received_packets_total` | Represents the total number of packets received per second by the network adapter | counter | `adapter` |
| `windows_hyperv_virtual_network_adapter_sent_packets_total` | Represents the total number of packets sent per second by the network adapter | counter | `adapter` |
### Hyper-V Virtual Network Adapter Drop Reasons
| Name | Description | Type | Labels |
|-------------------------------------------------------|----------------------------------------------|---------|--------------------------------|
| `windows_hyperv_virtual_network_adapter_drop_reasons` | Hyper-V Virtual Network Adapter Drop Reasons | counter | `adapter`,`direction`,`reason` |
### Hyper-V Virtual SMB
| Name | Description | Type | Labels |
|-------------------------------------------------------|-----------------------------------------------------------------------------------|---------|------------|
| `windows_hyperv_virtual_smb_direct_mapped_sections` | Represents the number of direct-mapped sections in the virtual SMB` | gauge | `instance` |
| `windows_hyperv_virtual_smb_direct_mapped_pages` | Represents the number of direct-mapped pages in the virtual SMB` | gauge | `instance` |
| `windows_hyperv_virtual_smb_write_bytes_rdma` | Represents the number of bytes written per second using RDMA in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_write_bytes` | Represents the number of bytes written per second in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_read_bytes_rdma` | Represents the number of bytes read per second using RDMA in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_read_bytes` | Represents the number of bytes read per second in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_flush_requests` | Represents the number of flush requests per second in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_write_requests_rdma` | Represents the number of write requests per second using RDMA in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_write_requests` | Represents the number of write requests per second in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_read_requests_rdma` | Represents the number of read requests per second using RDMA in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_read_requests` | Represents the number of read requests per second in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_current_pending_requests` | Represents the current number of pending requests in the virtual SMB` | gauge | `instance` |
| `windows_hyperv_virtual_smb_current_open_file_count` | Represents the current number of open files in the virtual SMB` | gauge | `instance` |
| `windows_hyperv_virtual_smb_tree_connect_count` | Represents the number of tree connects in the virtual SMB` | gauge | `instance` |
| `windows_hyperv_virtual_smb_requests` | Represents the number of requests per second in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_sent_bytes` | Represents the number of bytes sent per second in the virtual SMB` | counter | `instance` |
| `windows_hyperv_virtual_smb_received_bytes` | Represents the number of bytes received per second in the virtual SMB` | counter | `instance` |
### Hyper-V Virtual Switch
| Name | Description | Type | Labels |
|---------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|---------|-----------|
| `windows_hyperv_vswitch_broadcast_packets_received_total` | Represents the total number of broadcast packets received per second by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_broadcast_packets_sent_total` | Represents the total number of broadcast packets sent per second by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_bytes_total` | Represents the total number of bytes per second traversing the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_bytes_received_total` | Represents the total number of bytes received per second by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_bytes_sent_total` | Represents the total number of bytes sent per second by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_directed_packets_received_total` | Represents the total number of directed packets received per second by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_directed_packets_send_total` | Represents the total number of directed packets sent per second by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_dropped_packets_incoming_total` | Represents the total number of packet dropped per second by the virtual switch in the incoming direction | counter | `vswitch` |
| `windows_hyperv_vswitch_dropped_packets_outcoming_total` | Represents the total number of packet dropped per second by the virtual switch in the outgoing direction | counter | `vswitch` |
| `windows_hyperv_vswitch_extensions_dropped_packets_incoming_total` | Represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction | counter | `vswitch` |
| `windows_hyperv_vswitch_extensions_dropped_packets_outcoming_total` | Represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction | counter | `vswitch` |
| `windows_hyperv_vswitch_learned_mac_addresses_total` | Represents the total number of learned MAC addresses of the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_multicast_packets_received_total` | Represents the total number of multicast packets received per second by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_multicast_packets_sent_total` | Represents the total number of multicast packets sent per second by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_number_of_send_channel_moves_total` | Represents the total number of send channel moves per second on this virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_number_of_vmq_moves_total` | Represents the total number of VMQ moves per second on this virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_packets_flooded_total` | Represents the total number of packets flooded by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_packets_total` | Represents the total number of packets per second traversing the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_packets_received_total` | Represents the total number of packets received per second by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_packets_sent_total` | Represents the total number of packets send per second by the virtual switch | counter | `vswitch` |
| `windows_hyperv_vswitch_purged_mac_addresses_total` | Represents the total number of purged MAC addresses of the virtual switch | counter | `vswitch` |
### Hyper-V Virtual Storage Device
| Name | Description | Type | Labels |
|---------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|---------|----------|
| `windows_hyperv_virtual_storage_device_error_count_total` | Represents the total number of errors that have occurred on this virtual device. | counter | `device` |
| `windows_hyperv_virtual_storage_device_queue_length` | Represents the average queue length on this virtual device. | gauge | `device` |
| `windows_hyperv_virtual_storage_device_bytes_read` | Represents the total number of bytes that have been read on this virtual device. | counter | `device` |
| `windows_hyperv_virtual_storage_device_operations_read_total` | Represents the total number of read operations that have occurred on this virtual device. | counter | `device` |
| `windows_hyperv_virtual_storage_device_bytes_written` | Represents the total number of bytes that have been written on this virtual device. | counter | `device` |
| `windows_hyperv_virtual_storage_device_operations_written_total` | Represents the total number of write operations that have occurred on this virtual device. | counter | `device` |
| `windows_hyperv_virtual_storage_device_latency_seconds` | Represents the average IO transfer latency for this virtual device. | gauge | `device` |
| `windows_hyperv_virtual_storage_device_throughput` | Represents the average number of 8KB IO transfers completed by this virtual device. | gauge | `device` |
| `windows_hyperv_virtual_storage_device_normalized_throughput` | Represents the average number of IO transfers completed by this virtual device. | gauge | `device` |
| `windows_hyperv_virtual_storage_device_lower_queue_length` | Represents the average queue length on the underlying storage subsystem for this device. | gauge | `device` |
| `windows_hyperv_virtual_storage_device_lower_latency_seconds` | Represents the average IO transfer latency on the underlying storage subsystem for this virtual device. | gauge | `device` |
| `windows_hyperv_virtual_storage_device_io_quota_replenishment_rate` | Represents the IO quota replenishment rate for this virtual device. | gauge | `device` |
### Hyper-V VM Vid Partition
| Name | Description | Type | Labels |
|------------------------------------------------|-------------------------------------------------------------------------|-------|--------|
| `windows_hyperv_vid_physical_pages_allocated` | The number of physical pages allocated | gauge | `vm` |
| `windows_hyperv_vid_preferred_numa_node_index` | The preferred NUMA node index associated with this partition | gauge | `vm` |
| `windows_hyperv_vid_remote_physical_pages` | The number of physical pages not allocated from the preferred NUMA node | gauge | `vm` |
### Hyper-V Virtual Machine Health Summary
| Name | Description | Type | Labels |
|------------------------------------------------------|-------------------------------------------------------|-------|--------|
| `windows_hyperv_virtual_machine_health_total_count` | Represents the number of virtual machines with health | gauge | None |
### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_
@@ -113,19 +265,19 @@ _This collector does not yet have explained examples, we would appreciate your h
## Useful queries
Percent of physical CPU resources used per VM (on instance "localhost")
```
(sum (rate(windows_hyperv_vm_cpu_hypervisor_run_time{instance="localhost"}[1m]))) / ignoring(vm) group_left max (windows_cs_logical_processors{instance="localhost"}) / 100000
(sum (rate(windows_hyperv_hypervisor_virtual_processor_time_total{state="hypervisor",instance="localhost"}[1m]))) / ignoring(state,vm) group_left max (windows_cpu_logical_processor{instance="localhost"}) / 100000
```
Percent of physical CPU resources used by all VMs (on all monitored hosts)
```
(sum by (instance)(rate(windows_hyperv_vm_cpu_total_run_time{}[1m]))) / max by (instance)(windows_cs_logical_processors{}) / 100000
(sum by (instance)(rate(windows_hyperv_hypervisor_virtual_processor_total_run_time_total{}[1m]))) / max by (instance)(windows_cpu_logical_processor{}) / 100000
```
Percent of physical CPU resources by the hosts themselves (on all monitored hosts)
```
(sum by (instance)(rate(windows_hyperv_host_cpu_total_run_time{}[1m]))) / sum by (instance)(windows_cs_logical_processors{}) / 100000
(sum by (instance)(rate(windows_hyperv_hypervisor_root_virtual_processor_total_run_time_total{state="total"}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) / 100000
```
Percent of physical CPU resources by the hypervisor (on all monitored hosts)
```
(sum by (instance)(rate(windows_hyperv_host_lp_total_run_time_percent{}[1m]))) / sum by (instance)(windows_hyperv_hypervisor_logical_processors{}) / 100000
(sum by (instance)(rate(windows_hyperv_hypervisor_logical_processor_total_run_time_total{}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) / 100000
```
## Alerting examples

View File

@@ -16,246 +16,251 @@ Comma-separated list of MSSQL WMI classes to use. Supported values are `accessme
### `--collectors.mssql.class-print`
If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.
If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.fman`, `databases`, `dbreplica`, `genstats`, `locks`, `memmgr`, `sqlstats`, `sqlerrors`, `transactions`, and `waitstats`.
### `--collector.mssql.port`
Port of MSSQL server used for `windows_mssql_info` metric. Default is `1433`.
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`windows_mssql_collector_duration_seconds` | The time taken for each sub-collector to return | gauge | `collector`, `mssql_instance`
`windows_mssql_collector_success` | 1 if sub-collector succeeded, 0 otherwise | gauge | `collector`, `mssql_instance`
`windows_mssql_accessmethods_au_batch_cleanups` | The total number of batches that were completed successfully by the background task that cleans up deferred dropped allocation units | counter | `mssql_instance`
`windows_mssql_accessmethods_au_cleanups` | The total number of allocation units that were successfully dropped the background task that cleans up deferred dropped allocation units. Each allocation unit drop requires multiple batches | counter | `mssql_instance`
`windows_mssql_accessmethods_by_reference_lob_creates` | The total count of large object (lob) values that were passed by reference. By-reference lobs are used in certain bulk operations to avoid the cost of passing them by value | counter | `mssql_instance`
`windows_mssql_accessmethods_by_reference_lob_uses` | The total count of by-reference lob values that were used. By-reference lobs are used in certain bulk operations to avoid the cost of passing them by-value | counter | `mssql_instance`
`windows_mssql_accessmethods_lob_read_aheads` | The total count of lob pages on which readahead was issued | counter | `mssql_instance`
`windows_mssql_accessmethods_column_value_pulls` | The total count of column values that were pulled in-row from off-row | counter | `mssql_instance`
`windows_mssql_accessmethods_column_value_pushes` | The total count of column values that were pushed from in-row to off-row | counter | `mssql_instance`
`windows_mssql_accessmethods_deferred_dropped_aus` | The total number of allocation units waiting to be dropped by the background task that cleans up deferred dropped allocation units | gauge | `mssql_instance`
`windows_mssql_accessmethods_deferred_dropped_rowsets` | The number of rowsets created as a result of aborted online index build operations that are waiting to be dropped by the background task that cleans up deferred dropped rowsets | gauge | `mssql_instance`
`windows_mssql_accessmethods_dropped_rowset_cleanups` | The number of rowsets per second created as a result of aborted online index build operations that were successfully dropped by the background task that cleans up deferred dropped rowsets | counter | `mssql_instance`
`windows_mssql_accessmethods_dropped_rowset_skips` | The number of rowsets per second created as a result of aborted online index build operations that were skipped by the background task that cleans up deferred dropped rowsets created | counter | `mssql_instance`
`windows_mssql_accessmethods_extent_deallocations` | Number of extents deallocated per second in all databases in this instance of SQL Server | counter | `mssql_instance`
`windows_mssql_accessmethods_extent_allocations` | Number of extents allocated per second in all databases in this instance of SQL Server | counter | `mssql_instance`
`windows_mssql_accessmethods_au_batch_cleanup_failures` | The number of batches per second that failed and required retry, by the background task that cleans up deferred dropped allocation units. Failure could be due to lack of memory or disk space, hardware failure and other reasons | counter | `mssql_instance`
`windows_mssql_accessmethods_leaf_page_cookie_failures` | The number of times that a leaf page cookie could not be used during an index search since changes happened on the leaf page. The cookie is used to speed up index search | counter | `mssql_instance`
`windows_mssql_accessmethods_tree_page_cookie_failures` | The number of times that a tree page cookie could not be used during an index search since changes happened on the parent pages of those tree pages. The cookie is used to speed up index search | counter | `mssql_instance`
`windows_mssql_accessmethods_forwarded_records` | Number of records per second fetched through forwarded record pointers | counter | `mssql_instance`
`windows_mssql_accessmethods_free_space_page_fetches` | Number of pages fetched per second by free space scans. These scans search for free space within pages already allocated to an allocation unit, to satisfy requests to insert or modify record fragments | counter | `mssql_instance`
`windows_mssql_accessmethods_free_space_scans` | Number of scans per second that were initiated to search for free space within pages already allocated to an allocation unit to insert or modify record fragment. Each scan may find multiple pages | counter | `mssql_instance`
`windows_mssql_accessmethods_full_scans` | Number of unrestricted full scans per second. These can be either base-table or full-index scans | counter | `mssql_instance`
`windows_mssql_accessmethods_index_searches` | Number of index searches per second. These are used to start a range scan, reposition a range scan, revalidate a scan point, fetch a single index record, and search down the index to locate where to insert a new row | counter | `mssql_instance`
`windows_mssql_accessmethods_insysxact_waits` | Number of times a reader needs to wait for a page because the InSysXact bit is set | counter | `mssql_instance`
`windows_mssql_accessmethods_lob_handle_creates` | Count of temporary lobs created | counter | `mssql_instance`
`windows_mssql_accessmethods_lob_handle_destroys` | Count of temporary lobs destroyed | counter | `mssql_instance`
`windows_mssql_accessmethods_lob_ss_provider_creates` | Count of LOB Storage Service Providers (LobSSP) created. One worktable created per LobSSP | counter | `mssql_instance`
`windows_mssql_accessmethods_lob_ss_provider_destroys` | Count of LobSSP destroyed | counter | `mssql_instance`
`windows_mssql_accessmethods_lob_ss_provider_truncations` | Count of LobSSP truncated | counter | `mssql_instance`
`windows_mssql_accessmethods_mixed_page_allocations` | Number of pages allocated per second from mixed extents. These could be used for storing the IAM pages and the first eight pages that are allocated to an allocation unit | counter | `mssql_instance`
`windows_mssql_accessmethods_page_compression_attempts` | Number of pages evaluated for page-level compression. Includes pages that were not compressed because significant savings could be achieved. Includes all objects in the instance of SQL Server | counter | `mssql_instance`
`windows_mssql_accessmethods_page_deallocations` | Number of pages deallocated per second in all databases in this instance of SQL Server. These include pages from mixed extents and uniform extents | counter | `mssql_instance`
`windows_mssql_accessmethods_page_allocations` | Number of pages allocated per second in all databases in this instance of SQL Server. These include pages allocations from both mixed extents and uniform extents | counter | `mssql_instance`
`windows_mssql_accessmethods_page_compressions` | Number of data pages that are compressed by using PAGE compression. Includes all objects in the instance of SQL Server | counter | `mssql_instance`
`windows_mssql_accessmethods_page_splits` | Number of page splits per second that occur as the result of overflowing index pages | counter | `mssql_instance`
`windows_mssql_accessmethods_probe_scans` | Number of probe scans per second that are used to find at most one single qualified row in an index or base table directly | counter | `mssql_instance`
`windows_mssql_accessmethods_range_scans` | Number of qualified range scans through indexes per second | counter | `mssql_instance`
`windows_mssql_accessmethods_scan_point_revalidations` | Number of times per second that the scan point had to be revalidated to continue the scan | counter | `mssql_instance`
`windows_mssql_accessmethods_ghost_record_skips` | Number of ghosted records per second skipped during scans | counter | `mssql_instance`
`windows_mssql_accessmethods_table_lock_escalations` | Number of times locks on a table were escalated to the TABLE or HoBT granularity | counter | `mssql_instance`
`windows_mssql_accessmethods_leaf_page_cookie_uses` | Number of times a leaf page cookie is used successfully during an index search since no change happened on the leaf page. The cookie is used to speed up index search | counter | `mssql_instance`
`windows_mssql_accessmethods_tree_page_cookie_uses` | Number of times a tree page cookie is used successfully during an index search since no change happened on the parent page of the tree page. The cookie is used to speed up index search | counter | `mssql_instance`
`windows_mssql_accessmethods_workfile_creates` | Number of work files created per second. For example, work files could be used to store temporary results for hash joins and hash aggregates | counter | `mssql_instance`
`windows_mssql_accessmethods_worktables_creates` | Number of work tables created per second. For example, work tables could be used to store temporary results for query spool, lob variables, XML variables, and cursors | counter | `mssql_instance`
`windows_mssql_accessmethods_worktables_from_cache_ratio` | Percentage of work tables created where the initial two pages of the work table were not allocated but were immediately available from the work table cache | counter | `mssql_instance`
`windows_mssql_availreplica_received_from_replica_bytes` | Number of bytes received from the availability replica per second. Pings and status updates will generate network traffic even on databases with no user updates | counter | `mssql_instance`, `replica`
`windows_mssql_availreplica_sent_to_replica_bytes` | Number of bytes sent to the remote availability replica per second. On the primary replica this is the number of bytes sent to the secondary replica. On the secondary replica this is the number of bytes sent to the primary replica | counter | `mssql_instance`, `replica`
`windows_mssql_availreplica_sent_to_transport_bytes` | Actual number of bytes sent per second over the network to the remote availability replica. On the primary replica this is the number of bytes sent to the secondary replica. On the secondary replica this is the number of bytes sent to the primary replica | counter | `mssql_instance`, `replica`
`windows_mssql_availreplica_initiated_flow_controls` | Time in milliseconds that log stream messages waited for send flow control, in the last second | counter | `mssql_instance`, `replica`
`windows_mssql_availreplica_flow_control_wait_seconds` | Number of times flow-control initiated in the last second. Flow Control Time (ms/sec) divided by Flow Control/sec is the average time per wait | counter | `mssql_instance`, `replica`
`windows_mssql_availreplica_receives_from_replica` | Number of Always On messages received from thereplica per second | counter | `mssql_instance`, `replica`
`windows_mssql_availreplica_resent_messages` | Number of Always On messages resent in the last second | counter | `mssql_instance`, `replica`
`windows_mssql_availreplica_sends_to_replica` | Number of Always On messages sent to this availability replica per second | counter | `mssql_instance`, `replica`
`windows_mssql_availreplica_sends_to_transport` | Actual number of Always On messages sent per second over the network to the remote availability replica | counter | `mssql_instance`, `replica`
`windows_mssql_bufman_background_writer_pages` | Number of pages flushed to enforce the recovery interval settings | counter | `mssql_instance`
`windows_mssql_bufman_buffer_cache_hit_ratio` | Indicates the percentage of pages found in the buffer cache without having to read from disk. The ratio is the total number of cache hits divided by the total number of cache lookups over the last few thousand page accesses | gauge | `mssql_instance`
`windows_mssql_bufman_checkpoint_pages` | Indicates the number of pages flushed to disk per second by a checkpoint or other operation that require all dirty pages to be flushed | counter | `mssql_instance`
`windows_mssql_bufman_database_pages` | Indicates the number of pages in the buffer pool with database content | gauge | `mssql_instance`
`windows_mssql_bufman_extension_allocated_pages` | Total number of non-free cache pages in the buffer pool extension file | gauge | `mssql_instance`
`windows_mssql_bufman_extension_free_pages` | Total number of free cache pages in the buffer pool extension file | gauge | `mssql_instance`
`windows_mssql_bufman_extension_in_use_as_percentage` | _Not yet documented_ | gauge | `mssql_instance`
`windows_mssql_bufman_extension_outstanding_io` | Percentage of the buffer pool extension paging file occupied by buffer manager pages | gauge | `mssql_instance`
`windows_mssql_bufman_extension_page_evictions` | Number of pages evicted from the buffer pool extension file per second | counter | `mssql_instance`
`windows_mssql_bufman_extension_page_reads` | Number of pages read from the buffer pool extension file per second | counter | `mssql_instance`
`windows_mssql_bufman_extension_page_unreferenced_seconds` | Average seconds a page will stay in the buffer pool extension without references to it | gauge | `mssql_instance`
`windows_mssql_bufman_extension_page_writes` | Number of pages written to the buffer pool extension file per second | counter | `mssql_instance`
`windows_mssql_bufman_free_list_stalls` | Indicates the number of requests per second that had to wait for a free page | counter | `mssql_instance`
`windows_mssql_bufman_integral_controller_slope` | The slope that integral controller for the buffer pool last used, times -10 billion | gauge | `mssql_instance`
`windows_mssql_bufman_lazywrites` | Indicates the number of buffers written per second by the buffer manager's lazy writer | counter | `mssql_instance`
`windows_mssql_bufman_page_life_expectancy_seconds` | Indicates the number of seconds a page will stay in the buffer pool without references | gauge | `mssql_instance`
`windows_mssql_bufman_page_lookups` | Indicates the number of requests per second to find a page in the buffer pool | counter | `mssql_instance`
`windows_mssql_bufman_page_reads` | Indicates the number of physical database page reads that are issued per second | counter | `mssql_instance`
`windows_mssql_bufman_page_writes` | Indicates the number of physical database page writes that are issued per second | counter | `mssql_instance`
`windows_mssql_bufman_read_ahead_pages` | Indicates the number of pages read per second in anticipation of use | counter | `mssql_instance`
`windows_mssql_bufman_read_ahead_issuing_seconds` | Time (microseconds) spent issuing readahead | counter | `mssql_instance`
`windows_mssql_bufman_target_pages` | Ideal number of pages in the buffer pool | gauge | `mssql_instance`
`windows_mssql_dbreplica_database_flow_control_wait_seconds` | _Not yet documented_ | gauge | `mssql_instance`, `replica`
`windows_mssql_dbreplica_database_initiated_flow_controls` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_received_file_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_group_commits` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_group_commit_stall_seconds` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_apply_pending_queue` | _Not yet documented_ | gauge | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_apply_ready_queue` | _Not yet documented_ | gauge | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_compressed_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_decompressed_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_received_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_compression_cachehits` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_compression_cachemisses` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_compressions` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_decompressions` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_remaining_for_undo` | The amount of log, in bytes, remaining to complete the undo phase | gauge | `mssql_instance`, `replica`
`windows_mssql_dbreplica_log_send_queue` | Amount of log records in the log files of the primary database, in kilobytes, that haven't been sent to the secondary replica | gauge | `mssql_instance`, `replica`
`windows_mssql_dbreplica_mirrored_write_transactions` | Number of transactions that were written to the primary database and then waited to commit until the log was sent to the secondary database, in the last second | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_recovery_queue_records` | Amount of log records in the log files of the secondary replica that have not been redone | gauge | `mssql_instance`, `replica`
`windows_mssql_dbreplica_redo_blocks` | Number of times the redo thread was blocked on locks held by readers of the database | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_redo_remaining_bytes` | The amount of log, in kilobytes, remaining to be redone to finish the reverting phase | gauge | `mssql_instance`, `replica`
`windows_mssql_dbreplica_redone_bytes` | Amount of log records redone on the secondary database in the last second | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_redones` | _Not yet documented_ | counter | `mssql_instance`, `replica`
`windows_mssql_dbreplica_total_log_requiring_undo` | Total kilobytes of log that must be undone | gauge | `mssql_instance`, `replica`
`windows_mssql_dbreplica_transaction_delay_seconds` | Delay in waiting for unterminated commit acknowledgment for all the current transactions | gauge | `mssql_instance`, `replica`
`windows_mssql_databases_active_transactions` | Number of active transactions for the database | gauge | `mssql_instance`, `database`
`windows_mssql_databases_backup_restore_operations` | Read/write throughput for backup and restore operations of a database per second | counter | `mssql_instance`, `database`
`windows_mssql_databases_bulk_copy_rows` | Number of rows bulk copied per second | counter | `mssql_instance`, `database`
`windows_mssql_databases_bulk_copy_bytes` | Amount of data bulk copied (in kilobytes) per second | counter | `mssql_instance`, `database`
`windows_mssql_databases_commit_table_entries` | he size (row count) of the in-memory portion of the commit table for the database | gauge | `mssql_instance`, `database`
`windows_mssql_databases_data_files_size_bytes` | Cumulative size (in kilobytes) of all the data files in the database including any automatic growth. Monitoring this counter is useful, for example, for determining the correct size of tempdb | gauge | `mssql_instance`, `database`
`windows_mssql_databases_dbcc_logical_scan_bytes` | Number of logical read scan bytes per second for database console commands (DBCC) | counter | `mssql_instance`, `database`
`windows_mssql_databases_group_commit_stall_seconds` | Group stall time (microseconds) per second | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_flushed_bytes` | Total number of log bytes flushed | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_cache_hit_ratio` | Percentage of log cache reads satisfied from the log cache | gauge | `mssql_instance`, `database`
`windows_mssql_databases_log_cache_reads` | Reads performed per second through the log manager cache | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_files_size_bytes` | Cumulative size (in kilobytes) of all the transaction log files in the database | gauge | `mssql_instance`, `database`
`windows_mssql_databases_log_files_used_size_bytes` | The cumulative used size of all the log files in the database | gauge | `mssql_instance`, `database`
`windows_mssql_databases_log_flushes` | Total wait time (in milliseconds) to flush the log. On an Always On secondary database, this value indicates the wait time for log records to be hardened to disk | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_flush_waits` | Number of commits per second waiting for the log flush | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_flush_wait_seconds` | Number of commits per second waiting for the log flush | gauge | `mssql_instance`, `database`
`windows_mssql_databases_log_flush_write_seconds` | Time in milliseconds for performing writes of log flushes that were completed in the last second | gauge | `mssql_instance`, `database`
`windows_mssql_databases_log_growths` | Total number of times the transaction log for the database has been expanded | gauge | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_cache_misses` | Number of requests for which the log block was not available in the log pool | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_disk_reads` | Number of disk reads that the log pool issued to fetch log blocks | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_hash_deletes` | Rate of raw hash entry deletes from the Log Pool | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_hash_inserts` | Rate of raw hash entry inserts into the Log Pool | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_invalid_hash_entries` | Rate of hash lookups failing due to being invalid | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_log_scan_pushes` | Rate of Log block pushes by log scans, which may come from disk or memory | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_log_writer_pushes` | Rate of Log block pushes by log writer thread | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_empty_free_pool_pushes` | Rate of Log block push fails due to empty free pool | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_low_memory_pushes` | Rate of Log block push fails due to being low on memory | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_no_free_buffer_pushes` | Rate of Log block push fails due to free buffer unavailable | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_req_behind_trunc` | Log pool cache misses due to block requested being behind truncation LSN | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_requests_old_vlf` | Log Pool requests that were not in the last VLF of the log | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_requests` | The number of log-block requests processed by the log pool | counter | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_total_active_log_bytes` | Current total active log stored in the shared cache buffer manager in bytes | gauge | `mssql_instance`, `database`
`windows_mssql_databases_log_pool_total_shared_pool_bytes` | Current total memory usage of the shared cache buffer manager in bytes | gauge | `mssql_instance`, `database`
`windows_mssql_databases_log_shrinks` | Total number of log shrinks for this database | gauge | `mssql_instance`, `database`
`windows_mssql_databases_log_truncations` | The number of times the transaction log has been truncated (in Simple Recovery Model) | gauge | `mssql_instance`, `database`
`windows_mssql_databases_log_used_percent` | Percentage of space in the log that is in use | gauge | `mssql_instance`, `database`
`windows_mssql_databases_pending_repl_transactions` | Number of transactions in the transaction log of the publication database marked for replication, but not yet delivered to the distribution database | gauge | `mssql_instance`, `database`
`windows_mssql_databases_repl_transactions` | Number of transactions per second read out of the transaction log of the publication database and delivered to the distribution database | counter | `mssql_instance`, `database`
`windows_mssql_databases_shrink_data_movement_bytes` | Amount of data being moved per second by autoshrink operations, or DBCC SHRINKDATABASE or DBCC SHRINKFILE statements | counter | `mssql_instance`, `database`
`windows_mssql_databases_tracked_transactions` | Number of committed transactions recorded in the commit table for the database | counter | `mssql_instance`, `database`
`windows_mssql_databases_transactions` | Number of transactions started for the database per second | counter | `mssql_instance`, `database`
`windows_mssql_databases_write_transactions` | Number of transactions that wrote to the database and committed, in the last second | counter | `mssql_instance`, `database`
`windows_mssql_databases_xtp_controller_dlc_fetch_latency_seconds` | Average latency in microseconds between log blocks entering the Direct Log Consumer and being retrieved by the XTP controller, per second | gauge | `mssql_instance`, `database`
`windows_mssql_databases_xtp_controller_dlc_peak_latency_seconds` | The largest recorded latency, in microseconds, of a fetch from the Direct Log Consumer by the XTP controller | gauge | `mssql_instance`, `database`
`windows_mssql_databases_xtp_controller_log_processed_bytes` | The amount of log bytes processed by the XTP controller thread, per second | counter | `mssql_instance`, `database`
`windows_mssql_databases_xtp_memory_used_bytes` | The amount of memory used by XTP in the database | gauge | `mssql_instance`, `database`
`windows_mssql_genstats_active_temp_tables` | Number of temporary tables/table variables in use | gauge | `mssql_instance`
`windows_mssql_genstats_connection_resets` | Total number of logins started from the connection pool | counter | `mssql_instance`
`windows_mssql_genstats_event_notifications_delayed_drop` | Number of event notifications waiting to be dropped by a system thread | gauge | `mssql_instance`
`windows_mssql_genstats_http_authenticated_requests` | Number of authenticated HTTP requests started per second | gauge | `mssql_instance`
`windows_mssql_genstats_logical_connections` | Number of logical connections to the system | gauge | `mssql_instance`
`windows_mssql_genstats_logins` | Total number of logins started per second. This does not include pooled connections | counter | `mssql_instance`
`windows_mssql_genstats_logouts` | Total number of logout operations started per second | counter | `mssql_instance`
`windows_mssql_genstats_mars_deadlocks` | Number of MARS deadlocks detected | gauge | `mssql_instance`
`windows_mssql_genstats_non_atomic_yields` | Number of non-atomic yields per second | counter | `mssql_instance`
`windows_mssql_genstats_blocked_processes` | Number of currently blocked processes | gauge | `mssql_instance`
`windows_mssql_genstats_soap_empty_requests` | Number of empty SOAP requests started per second | gauge | `mssql_instance`
`windows_mssql_genstats_soap_method_invocations` | Number of SOAP method invocations started per second | gauge | `mssql_instance`
`windows_mssql_genstats_soap_session_initiate_requests` | Number of SOAP Session initiate requests started per second | gauge | `mssql_instance`
`windows_mssql_genstats_soap_session_terminate_requests` | Number of SOAP Session terminate requests started per second | gauge | `mssql_instance`
`windows_mssql_genstats_soapsql_requests` | Number of SOAP SQL requests started per second | gauge | `mssql_instance`
`windows_mssql_genstats_soapwsdl_requests` | Number of SOAP Web Service Description Language requests started per second | gauge | `mssql_instance`
`windows_mssql_genstats_sql_trace_io_provider_lock_waits` | Number of waits for the File IO Provider lock per second | gauge | `mssql_instance`
`windows_mssql_genstats_tempdb_recovery_unit_ids_generated` | Number of duplicate tempdb recovery unit id generated | gauge | `mssql_instance`
`windows_mssql_genstats_tempdb_rowset_ids_generated` | Number of duplicate tempdb rowset id generated | gauge | `mssql_instance`
`windows_mssql_genstats_temp_tables_creations` | Number of temporary tables/table variables created per second | counter | `mssql_instance`
`windows_mssql_genstats_temp_tables_awaiting_destruction` | Number of temporary tables/table variables waiting to be destroyed by the cleanup system thread | gauge | `mssql_instance`
`windows_mssql_genstats_trace_event_notification_queue_size` | Number of trace event notification instances waiting in the internal queue to be sent through Service Broker | gauge | `mssql_instance`
`windows_mssql_genstats_transactions` | Number of transaction enlistments (local, DTC, bound all combined) | gauge | `mssql_instance`
`windows_mssql_genstats_user_connections` | Counts the number of users currently connected to SQL Server | gauge | `mssql_instance`
`windows_mssql_locks_average_wait_seconds` | Average amount of wait time (in milliseconds) for each lock request that resulted in a wait | gauge | `mssql_instance`, `resource`
`windows_mssql_locks_lock_requests` | Number of new locks and lock conversions per second requested from the lock manager | counter | `mssql_instance`, `resource`
`windows_mssql_locks_lock_timeouts` | Number of lock requests per second that timed out, including requests for NOWAIT locks | counter | `mssql_instance`, `resource`
`windows_mssql_locks_lock_timeouts_excluding_NOWAIT` | Number of lock requests per second that timed out, but excluding requests for NOWAIT locks | counter | `mssql_instance`, `resource`
`windows_mssql_locks_lock_waits` | Total wait time (in milliseconds) for locks in the last second | counter | `mssql_instance`, `resource`
`windows_mssql_locks_lock_wait_seconds` | Number of lock requests per second that required the caller to wait | gauge | `mssql_instance`, `resource`
`windows_mssql_locks_deadlocks` | Number of lock requests per second that resulted in a deadlock | counter | `mssql_instance`, `resource`
`windows_mssql_memmgr_connection_memory_bytes` | Specifies the total amount of dynamic memory the server is using for maintaining connections | gauge | `mssql_instance`
`windows_mssql_memmgr_database_cache_memory_bytes` | Specifies the amount of memory the server is currently using for the database pages cache | gauge | `mssql_instance`
`windows_mssql_memmgr_external_benefit_of_memory` | An internal estimation of the performance benefit from adding memory to a specific cache | gauge | `mssql_instance`
`windows_mssql_memmgr_free_memory_bytes` | Specifies the amount of committed memory currently not used by the server | gauge | `mssql_instance`
`windows_mssql_memmgr_granted_workspace_memory_bytes` | Specifies the total amount of memory currently granted to executing processes, such as hash, sort, bulk copy, and index creation operations | gauge | `mssql_instance`
`windows_mssql_memmgr_lock_blocks` | Specifies the current number of lock blocks in use on the server (refreshed periodically). A lock block represents an individual locked resource, such as a table, page, or row | gauge | `mssql_instance`
`windows_mssql_memmgr_allocated_lock_blocks` | Specifies the current number of allocated lock blocks. At server startup, the number of allocated lock blocks plus the number of allocated lock owner blocks depends on the SQL Server Locks configuration option. If more lock blocks are needed, the value increases | gauge | `mssql_instance`
`windows_mssql_memmgr_lock_memory_bytes` | Specifies the total amount of dynamic memory the server is using for locks | gauge | `mssql_instance`
`windows_mssql_memmgr_lock_owner_blocks` | Specifies the current number of allocated lock owner blocks. At server startup, the number of allocated lock owner blocks and the number of allocated lock blocks depend on the SQL Server Locks configuration option. If more lock owner blocks are needed, the value increases dynamically | gauge | `mssql_instance`
`windows_mssql_memmgr_allocated_lock_owner_blocks` | _Not yet documented_ | gauge | `mssql_instance`
`windows_mssql_memmgr_log_pool_memory_bytes` | Total amount of dynamic memory the server is using for Log Pool | gauge | `mssql_instance`
`windows_mssql_memmgr_maximum_workspace_memory_bytes` | Indicates the maximum amount of memory available for executing processes, such as hash, sort, bulk copy, and index creation operations | gauge | `mssql_instance`
`windows_mssql_memmgr_outstanding_memory_grants` | Specifies the total number of processes that have successfully acquired a workspace memory grant | gauge | `mssql_instance`
`windows_mssql_memmgr_pending_memory_grants` | Specifies the total number of processes waiting for a workspace memory grant | gauge | `mssql_instance`
`windows_mssql_memmgr_optimizer_memory_bytes` | Specifies the total amount of dynamic memory the server is using for query optimization | gauge | `mssql_instance`
`windows_mssql_memmgr_reserved_server_memory_bytes` | ndicates the amount of memory the server has reserved for future usage. This counter shows the current unused amount of memory initially granted that is shown in Granted Workspace Memory | gauge | `mssql_instance`
`windows_mssql_memmgr_sql_cache_memory_bytes` | Specifies the total amount of dynamic memory the server is using for the dynamic SQL cache | gauge | `mssql_instance`
`windows_mssql_memmgr_stolen_server_memory_bytes` | Specifies the amount of memory the server is using for purposes other than database pages | gauge | `mssql_instance`
`windows_mssql_memmgr_target_server_memory_bytes` | Indicates the ideal amount of memory the server can consume | gauge | `mssql_instance`
`windows_mssql_memmgr_total_server_memory_bytes` | Specifies the amount of memory the server has committed using the memory manager | gauge | `mssql_instance`
`windows_mssql_sqlstats_auto_parameterization_attempts` | Number of failed auto-parameterization attempts per second. This should be small. Note that auto-parameterizations are also known as simple parameterizations in later versions of SQL Server | counter | `mssql_instance`
`windows_mssql_sqlstats_batch_requests` | _Not yet documented_ | counter | `mssql_instance`
`windows_mssql_sqlstats_failed_auto_parameterization_attempts` | _Not yet documented_ | counter | `mssql_instance`
`windows_mssql_sqlstats_forced_parameterizations` | Number of successful forced parameterizations per second | counter | `mssql_instance`
`windows_mssql_sqlstats_guided_plan_executions` | Number of plan executions per second in which the query plan has been generated by using a plan guide | counter | `mssql_instance`
`windows_mssql_sqlstats_misguided_plan_executions` | Number of plan executions per second in which a plan guide could not be honored during plan generation | counter | `mssql_instance`
`windows_mssql_sqlstats_safe_auto_parameterization_attempts` | Number of safe auto-parameterization attempts per second | counter | `mssql_instance`
`windows_mssql_sqlstats_sql_attentions` | Number of attentions per second | counter | `mssql_instance`
`windows_mssql_sqlstats_sql_compilations` | Number of SQL compilations per second | counter | `mssql_instance`
`windows_mssql_sqlstats_sql_recompilations` | Number of statement recompiles per second | counter | `mssql_instance`
`windows_mssql_sqlstats_unsafe_auto_parameterization_attempts` | Number of unsafe auto-parameterization attempts per second. | counter | `mssql_instance`
`windows_mssql_sql_errors_total` | Information for all errors | counter | `mssql_instance`, `resource`
`windows_mssql_transactions_tempdb_free_space_bytes` | The amount of space (in kilobytes) available in tempdb | gauge | `mssql_instance`
`windows_mssql_transactions_longest_transaction_running_seconds` | The length of time (in seconds) since the start of the transaction that has been active longer than any other current transaction | gauge | `mssql_instance`
`windows_mssql_transactions_nonsnapshot_version_active_total` | The number of currently active transactions that are not using snapshot isolation level and have made data modifications that have generated row versions in the tempdb version store | counter | `mssql_instance`
`windows_mssql_transactions_snapshot_active_total` | The number of currently active transactions using the snapshot isolation level | counter | `mssql_instance`
`windows_mssql_transactions_active` | The number of currently active transactions of all types | gauge | `mssql_instance`
`windows_mssql_transactions_update_conflicts_total` | The percentage of those transactions using the snapshot isolation level that have encountered update conflicts within the last second | counter | `mssql_instance`
`windows_mssql_transactions_update_snapshot_active_total` | The number of currently active transactions using the snapshot isolation level and have modified data | counter | `mssql_instance`
`windows_mssql_transactions_version_cleanup_rate_bytes` | The rate (in kilobytes per second) at which row versions are removed from the snapshot isolation version store in tempdb | gauge | `mssql_instance`
`windows_mssql_transactions_version_generation_rate_bytes` | The rate (in kilobytes per second) at which new row versions are added to the snapshot isolation version store in tempdb | gauge | `mssql_instance`
`windows_mssql_transactions_version_store_size_bytes` | he amount of space (in kilobytes) in tempdb being used to store snapshot isolation level row versions | gauge | `mssql_instance`
`windows_mssql_transactions_version_store_units` | The number of active allocation units in the snapshot isolation version store in tempdb | counter | `mssql_instance`
`windows_mssql_transactions_version_store_creation_units` | The number of allocation units that have been created in the snapshot isolation store since the instance of the Database Engine was started | counter | `mssql_instance`
`windows_mssql_transactions_version_store_truncation_units` | The number of allocation units that have been removed from the snapshot isolation store since the instance of the Database Engine was started | counter | `mssql_instance`
`windows_mssql_waitstats_lock_waits` | Statistics for processes waiting on a lock | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_memory_grant_queue_waits` | Statistics for processes waiting for memory grant to become available | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_thread_safe_memory_objects_waits` | Statistics for processes waiting on thread-safe memory allocators | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_log_write_waits` | Statistics for processes waiting for log buffer to be written | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_log_buffer_waits` | Statistics for processes waiting for log buffer to be available | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_network_io_waits` | Statistics relevant to wait on network I/O | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_page_io_latch_waits` | Statistics relevant to page I/O latches | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_page_latch_waits` | Statistics relevant to page latches, not including I/O latches | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_nonpage_latch_waits` | Statistics relevant to non-page latches | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_wait_for_the_worker_waits` | Statistics relevant to processes waiting for worker to become available | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_workspace_synchronization_waits` | Statistics relevant to processes synchronizing access to workspace | gauge | `mssql_instance`, `item`
`windows_mssql_waitstats_transaction_ownership_waits` | Statistics relevant to processes synchronizing access to transaction | gauge | `mssql_instance`, `item`
| Name | Description | Type | Labels |
|--------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-------------------------------|
| `windows_mssql_info` | Returns information about the MSSQL server running on port 1433 | gauge | `version` |
| `windows_mssql_collector_duration_seconds` | The time taken for each sub-collector to return | gauge | `collector`, `mssql_instance` |
| `windows_mssql_collector_success` | 1 if sub-collector succeeded, 0 otherwise | gauge | `collector`, `mssql_instance` |
| `windows_mssql_accessmethods_au_batch_cleanups` | The total number of batches that were completed successfully by the background task that cleans up deferred dropped allocation units | counter | `mssql_instance` |
| `windows_mssql_accessmethods_au_cleanups` | The total number of allocation units that were successfully dropped the background task that cleans up deferred dropped allocation units. Each allocation unit drop requires multiple batches | counter | `mssql_instance` |
| `windows_mssql_accessmethods_by_reference_lob_creates` | The total count of large object (lob) values that were passed by reference. By-reference lobs are used in certain bulk operations to avoid the cost of passing them by value | counter | `mssql_instance` |
| `windows_mssql_accessmethods_by_reference_lob_uses` | The total count of by-reference lob values that were used. By-reference lobs are used in certain bulk operations to avoid the cost of passing them by-value | counter | `mssql_instance` |
| `windows_mssql_accessmethods_lob_read_aheads` | The total count of lob pages on which readahead was issued | counter | `mssql_instance` |
| `windows_mssql_accessmethods_column_value_pulls` | The total count of column values that were pulled in-row from off-row | counter | `mssql_instance` |
| `windows_mssql_accessmethods_column_value_pushes` | The total count of column values that were pushed from in-row to off-row | counter | `mssql_instance` |
| `windows_mssql_accessmethods_deferred_dropped_aus` | The total number of allocation units waiting to be dropped by the background task that cleans up deferred dropped allocation units | gauge | `mssql_instance` |
| `windows_mssql_accessmethods_deferred_dropped_rowsets` | The number of rowsets created as a result of aborted online index build operations that are waiting to be dropped by the background task that cleans up deferred dropped rowsets | gauge | `mssql_instance` |
| `windows_mssql_accessmethods_dropped_rowset_cleanups` | The number of rowsets per second created as a result of aborted online index build operations that were successfully dropped by the background task that cleans up deferred dropped rowsets | counter | `mssql_instance` |
| `windows_mssql_accessmethods_dropped_rowset_skips` | The number of rowsets per second created as a result of aborted online index build operations that were skipped by the background task that cleans up deferred dropped rowsets created | counter | `mssql_instance` |
| `windows_mssql_accessmethods_extent_deallocations` | Number of extents deallocated per second in all databases in this instance of SQL Server | counter | `mssql_instance` |
| `windows_mssql_accessmethods_extent_allocations` | Number of extents allocated per second in all databases in this instance of SQL Server | counter | `mssql_instance` |
| `windows_mssql_accessmethods_au_batch_cleanup_failures` | The number of batches per second that failed and required retry, by the background task that cleans up deferred dropped allocation units. Failure could be due to lack of memory or disk space, hardware failure and other reasons | counter | `mssql_instance` |
| `windows_mssql_accessmethods_leaf_page_cookie_failures` | The number of times that a leaf page cookie could not be used during an index search since changes happened on the leaf page. The cookie is used to speed up index search | counter | `mssql_instance` |
| `windows_mssql_accessmethods_tree_page_cookie_failures` | The number of times that a tree page cookie could not be used during an index search since changes happened on the parent pages of those tree pages. The cookie is used to speed up index search | counter | `mssql_instance` |
| `windows_mssql_accessmethods_forwarded_records` | Number of records per second fetched through forwarded record pointers | counter | `mssql_instance` |
| `windows_mssql_accessmethods_free_space_page_fetches` | Number of pages fetched per second by free space scans. These scans search for free space within pages already allocated to an allocation unit, to satisfy requests to insert or modify record fragments | counter | `mssql_instance` |
| `windows_mssql_accessmethods_free_space_scans` | Number of scans per second that were initiated to search for free space within pages already allocated to an allocation unit to insert or modify record fragment. Each scan may find multiple pages | counter | `mssql_instance` |
| `windows_mssql_accessmethods_full_scans` | Number of unrestricted full scans per second. These can be either base-table or full-index scans | counter | `mssql_instance` |
| `windows_mssql_accessmethods_index_searches` | Number of index searches per second. These are used to start a range scan, reposition a range scan, revalidate a scan point, fetch a single index record, and search down the index to locate where to insert a new row | counter | `mssql_instance` |
| `windows_mssql_accessmethods_insysxact_waits` | Number of times a reader needs to wait for a page because the InSysXact bit is set | counter | `mssql_instance` |
| `windows_mssql_accessmethods_lob_handle_creates` | Count of temporary lobs created | counter | `mssql_instance` |
| `windows_mssql_accessmethods_lob_handle_destroys` | Count of temporary lobs destroyed | counter | `mssql_instance` |
| `windows_mssql_accessmethods_lob_ss_provider_creates` | Count of LOB Storage Service Providers (LobSSP) created. One worktable created per LobSSP | counter | `mssql_instance` |
| `windows_mssql_accessmethods_lob_ss_provider_destroys` | Count of LobSSP destroyed | counter | `mssql_instance` |
| `windows_mssql_accessmethods_lob_ss_provider_truncations` | Count of LobSSP truncated | counter | `mssql_instance` |
| `windows_mssql_accessmethods_mixed_page_allocations` | Number of pages allocated per second from mixed extents. These could be used for storing the IAM pages and the first eight pages that are allocated to an allocation unit | counter | `mssql_instance` |
| `windows_mssql_accessmethods_page_compression_attempts` | Number of pages evaluated for page-level compression. Includes pages that were not compressed because significant savings could be achieved. Includes all objects in the instance of SQL Server | counter | `mssql_instance` |
| `windows_mssql_accessmethods_page_deallocations` | Number of pages deallocated per second in all databases in this instance of SQL Server. These include pages from mixed extents and uniform extents | counter | `mssql_instance` |
| `windows_mssql_accessmethods_page_allocations` | Number of pages allocated per second in all databases in this instance of SQL Server. These include pages allocations from both mixed extents and uniform extents | counter | `mssql_instance` |
| `windows_mssql_accessmethods_page_compressions` | Number of data pages that are compressed by using PAGE compression. Includes all objects in the instance of SQL Server | counter | `mssql_instance` |
| `windows_mssql_accessmethods_page_splits` | Number of page splits per second that occur as the result of overflowing index pages | counter | `mssql_instance` |
| `windows_mssql_accessmethods_probe_scans` | Number of probe scans per second that are used to find at most one single qualified row in an index or base table directly | counter | `mssql_instance` |
| `windows_mssql_accessmethods_range_scans` | Number of qualified range scans through indexes per second | counter | `mssql_instance` |
| `windows_mssql_accessmethods_scan_point_revalidations` | Number of times per second that the scan point had to be revalidated to continue the scan | counter | `mssql_instance` |
| `windows_mssql_accessmethods_ghost_record_skips` | Number of ghosted records per second skipped during scans | counter | `mssql_instance` |
| `windows_mssql_accessmethods_table_lock_escalations` | Number of times locks on a table were escalated to the TABLE or HoBT granularity | counter | `mssql_instance` |
| `windows_mssql_accessmethods_leaf_page_cookie_uses` | Number of times a leaf page cookie is used successfully during an index search since no change happened on the leaf page. The cookie is used to speed up index search | counter | `mssql_instance` |
| `windows_mssql_accessmethods_tree_page_cookie_uses` | Number of times a tree page cookie is used successfully during an index search since no change happened on the parent page of the tree page. The cookie is used to speed up index search | counter | `mssql_instance` |
| `windows_mssql_accessmethods_workfile_creates` | Number of work files created per second. For example, work files could be used to store temporary results for hash joins and hash aggregates | counter | `mssql_instance` |
| `windows_mssql_accessmethods_worktables_creates` | Number of work tables created per second. For example, work tables could be used to store temporary results for query spool, lob variables, XML variables, and cursors | counter | `mssql_instance` |
| `windows_mssql_accessmethods_worktables_from_cache_ratio` | Percentage of work tables created where the initial two pages of the work table were not allocated but were immediately available from the work table cache | counter | `mssql_instance` |
| `windows_mssql_availreplica_received_from_replica_bytes` | Number of bytes received from the availability replica per second. Pings and status updates will generate network traffic even on databases with no user updates | counter | `mssql_instance`, `replica` |
| `windows_mssql_availreplica_sent_to_replica_bytes` | Number of bytes sent to the remote availability replica per second. On the primary replica this is the number of bytes sent to the secondary replica. On the secondary replica this is the number of bytes sent to the primary replica | counter | `mssql_instance`, `replica` |
| `windows_mssql_availreplica_sent_to_transport_bytes` | Actual number of bytes sent per second over the network to the remote availability replica. On the primary replica this is the number of bytes sent to the secondary replica. On the secondary replica this is the number of bytes sent to the primary replica | counter | `mssql_instance`, `replica` |
| `windows_mssql_availreplica_initiated_flow_controls` | Time in milliseconds that log stream messages waited for send flow control, in the last second | counter | `mssql_instance`, `replica` |
| `windows_mssql_availreplica_flow_control_wait_seconds` | Number of times flow-control initiated in the last second. Flow Control Time (ms/sec) divided by Flow Control/sec is the average time per wait | counter | `mssql_instance`, `replica` |
| `windows_mssql_availreplica_receives_from_replica` | Number of Always On messages received from thereplica per second | counter | `mssql_instance`, `replica` |
| `windows_mssql_availreplica_resent_messages` | Number of Always On messages resent in the last second | counter | `mssql_instance`, `replica` |
| `windows_mssql_availreplica_sends_to_replica` | Number of Always On messages sent to this availability replica per second | counter | `mssql_instance`, `replica` |
| `windows_mssql_availreplica_sends_to_transport` | Actual number of Always On messages sent per second over the network to the remote availability replica | counter | `mssql_instance`, `replica` |
| `windows_mssql_bufman_background_writer_pages` | Number of pages flushed to enforce the recovery interval settings | counter | `mssql_instance` |
| `windows_mssql_bufman_buffer_cache_hit_ratio` | Indicates the percentage of pages found in the buffer cache without having to read from disk. The ratio is the total number of cache hits divided by the total number of cache lookups over the last few thousand page accesses | gauge | `mssql_instance` |
| `windows_mssql_bufman_checkpoint_pages` | Indicates the number of pages flushed to disk per second by a checkpoint or other operation that require all dirty pages to be flushed | counter | `mssql_instance` |
| `windows_mssql_bufman_database_pages` | Indicates the number of pages in the buffer pool with database content | gauge | `mssql_instance` |
| `windows_mssql_bufman_extension_allocated_pages` | Total number of non-free cache pages in the buffer pool extension file | gauge | `mssql_instance` |
| `windows_mssql_bufman_extension_free_pages` | Total number of free cache pages in the buffer pool extension file | gauge | `mssql_instance` |
| `windows_mssql_bufman_extension_in_use_as_percentage` | _Not yet documented_ | gauge | `mssql_instance` |
| `windows_mssql_bufman_extension_outstanding_io` | Percentage of the buffer pool extension paging file occupied by buffer manager pages | gauge | `mssql_instance` |
| `windows_mssql_bufman_extension_page_evictions` | Number of pages evicted from the buffer pool extension file per second | counter | `mssql_instance` |
| `windows_mssql_bufman_extension_page_reads` | Number of pages read from the buffer pool extension file per second | counter | `mssql_instance` |
| `windows_mssql_bufman_extension_page_unreferenced_seconds` | Average seconds a page will stay in the buffer pool extension without references to it | gauge | `mssql_instance` |
| `windows_mssql_bufman_extension_page_writes` | Number of pages written to the buffer pool extension file per second | counter | `mssql_instance` |
| `windows_mssql_bufman_free_list_stalls` | Indicates the number of requests per second that had to wait for a free page | counter | `mssql_instance` |
| `windows_mssql_bufman_integral_controller_slope` | The slope that integral controller for the buffer pool last used, times -10 billion | gauge | `mssql_instance` |
| `windows_mssql_bufman_lazywrites` | Indicates the number of buffers written per second by the buffer manager's lazy writer | counter | `mssql_instance` |
| `windows_mssql_bufman_page_life_expectancy_seconds` | Indicates the number of seconds a page will stay in the buffer pool without references | gauge | `mssql_instance` |
| `windows_mssql_bufman_page_lookups` | Indicates the number of requests per second to find a page in the buffer pool | counter | `mssql_instance` |
| `windows_mssql_bufman_page_reads` | Indicates the number of physical database page reads that are issued per second | counter | `mssql_instance` |
| `windows_mssql_bufman_page_writes` | Indicates the number of physical database page writes that are issued per second | counter | `mssql_instance` |
| `windows_mssql_bufman_read_ahead_pages` | Indicates the number of pages read per second in anticipation of use | counter | `mssql_instance` |
| `windows_mssql_bufman_read_ahead_issuing_seconds` | Time (microseconds) spent issuing readahead | counter | `mssql_instance` |
| `windows_mssql_bufman_target_pages` | Ideal number of pages in the buffer pool | gauge | `mssql_instance` |
| `windows_mssql_dbreplica_database_flow_control_wait_seconds` | _Not yet documented_ | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_database_initiated_flow_controls` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_received_file_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_group_commits` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_group_commit_stall_seconds` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_apply_pending_queue` | _Not yet documented_ | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_apply_ready_queue` | _Not yet documented_ | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_compressed_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_decompressed_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_received_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_compression_cachehits` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_compression_cachemisses` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_compressions` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_decompressions` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_remaining_for_undo` | The amount of log, in bytes, remaining to complete the undo phase | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_send_queue` | Amount of log records in the log files of the primary database, in kilobytes, that haven't been sent to the secondary replica | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_mirrored_write_transactions` | Number of transactions that were written to the primary database and then waited to commit until the log was sent to the secondary database, in the last second | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_recovery_queue_records` | Amount of log records in the log files of the secondary replica that have not been redone | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_redo_blocks` | Number of times the redo thread was blocked on locks held by readers of the database | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_redo_remaining_bytes` | The amount of log, in kilobytes, remaining to be redone to finish the reverting phase | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_redone_bytes` | Amount of log records redone on the secondary database in the last second | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_redones` | _Not yet documented_ | counter | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_total_log_requiring_undo` | Total kilobytes of log that must be undone | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_transaction_delay_seconds` | Delay in waiting for unterminated commit acknowledgment for all the current transactions | gauge | `mssql_instance`, `replica` |
| `windows_mssql_databases_active_transactions` | Number of active transactions for the database | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_backup_restore_operations` | Read/write throughput for backup and restore operations of a database per second | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_bulk_copy_rows` | Number of rows bulk copied per second | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_bulk_copy_bytes` | Amount of data bulk copied (in kilobytes) per second | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_commit_table_entries` | he size (row count) of the in-memory portion of the commit table for the database | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_data_files_size_bytes` | Cumulative size (in kilobytes) of all the data files in the database including any automatic growth. Monitoring this counter is useful, for example, for determining the correct size of tempdb | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_dbcc_logical_scan_bytes` | Number of logical read scan bytes per second for database console commands (DBCC) | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_group_commit_stall_seconds` | Group stall time (microseconds) per second | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_flushed_bytes` | Total number of log bytes flushed | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_cache_hit_ratio` | Percentage of log cache reads satisfied from the log cache | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_cache_reads` | Reads performed per second through the log manager cache | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_files_size_bytes` | Cumulative size (in kilobytes) of all the transaction log files in the database | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_files_used_size_bytes` | The cumulative used size of all the log files in the database | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_flushes` | Total wait time (in milliseconds) to flush the log. On an Always On secondary database, this value indicates the wait time for log records to be hardened to disk | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_flush_waits` | Number of commits per second waiting for the log flush | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_flush_wait_seconds` | Number of commits per second waiting for the log flush | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_flush_write_seconds` | Time in milliseconds for performing writes of log flushes that were completed in the last second | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_growths` | Total number of times the transaction log for the database has been expanded | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_cache_misses` | Number of requests for which the log block was not available in the log pool | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_disk_reads` | Number of disk reads that the log pool issued to fetch log blocks | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_hash_deletes` | Rate of raw hash entry deletes from the Log Pool | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_hash_inserts` | Rate of raw hash entry inserts into the Log Pool | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_invalid_hash_entries` | Rate of hash lookups failing due to being invalid | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_log_scan_pushes` | Rate of Log block pushes by log scans, which may come from disk or memory | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_log_writer_pushes` | Rate of Log block pushes by log writer thread | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_empty_free_pool_pushes` | Rate of Log block push fails due to empty free pool | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_low_memory_pushes` | Rate of Log block push fails due to being low on memory | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_no_free_buffer_pushes` | Rate of Log block push fails due to free buffer unavailable | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_req_behind_trunc` | Log pool cache misses due to block requested being behind truncation LSN | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_requests_old_vlf` | Log Pool requests that were not in the last VLF of the log | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_requests` | The number of log-block requests processed by the log pool | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_total_active_log_bytes` | Current total active log stored in the shared cache buffer manager in bytes | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_pool_total_shared_pool_bytes` | Current total memory usage of the shared cache buffer manager in bytes | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_shrinks` | Total number of log shrinks for this database | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_truncations` | The number of times the transaction log has been truncated (in Simple Recovery Model) | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_used_percent` | Percentage of space in the log that is in use | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_pending_repl_transactions` | Number of transactions in the transaction log of the publication database marked for replication, but not yet delivered to the distribution database | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_repl_transactions` | Number of transactions per second read out of the transaction log of the publication database and delivered to the distribution database | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_shrink_data_movement_bytes` | Amount of data being moved per second by autoshrink operations, or DBCC SHRINKDATABASE or DBCC SHRINKFILE statements | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_tracked_transactions` | Number of committed transactions recorded in the commit table for the database | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_transactions` | Number of transactions started for the database per second | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_write_transactions` | Number of transactions that wrote to the database and committed, in the last second | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_xtp_controller_dlc_fetch_latency_seconds` | Average latency in microseconds between log blocks entering the Direct Log Consumer and being retrieved by the XTP controller, per second | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_xtp_controller_dlc_peak_latency_seconds` | The largest recorded latency, in microseconds, of a fetch from the Direct Log Consumer by the XTP controller | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_xtp_controller_log_processed_bytes` | The amount of log bytes processed by the XTP controller thread, per second | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_xtp_memory_used_bytes` | The amount of memory used by XTP in the database | gauge | `mssql_instance`, `database` |
| `windows_mssql_genstats_active_temp_tables` | Number of temporary tables/table variables in use | gauge | `mssql_instance` |
| `windows_mssql_genstats_connection_resets` | Total number of logins started from the connection pool | counter | `mssql_instance` |
| `windows_mssql_genstats_event_notifications_delayed_drop` | Number of event notifications waiting to be dropped by a system thread | gauge | `mssql_instance` |
| `windows_mssql_genstats_http_authenticated_requests` | Number of authenticated HTTP requests started per second | gauge | `mssql_instance` |
| `windows_mssql_genstats_logical_connections` | Number of logical connections to the system | gauge | `mssql_instance` |
| `windows_mssql_genstats_logins` | Total number of logins started per second. This does not include pooled connections | counter | `mssql_instance` |
| `windows_mssql_genstats_logouts` | Total number of logout operations started per second | counter | `mssql_instance` |
| `windows_mssql_genstats_mars_deadlocks` | Number of MARS deadlocks detected | gauge | `mssql_instance` |
| `windows_mssql_genstats_non_atomic_yields` | Number of non-atomic yields per second | counter | `mssql_instance` |
| `windows_mssql_genstats_blocked_processes` | Number of currently blocked processes | gauge | `mssql_instance` |
| `windows_mssql_genstats_soap_empty_requests` | Number of empty SOAP requests started per second | gauge | `mssql_instance` |
| `windows_mssql_genstats_soap_method_invocations` | Number of SOAP method invocations started per second | gauge | `mssql_instance` |
| `windows_mssql_genstats_soap_session_initiate_requests` | Number of SOAP Session initiate requests started per second | gauge | `mssql_instance` |
| `windows_mssql_genstats_soap_session_terminate_requests` | Number of SOAP Session terminate requests started per second | gauge | `mssql_instance` |
| `windows_mssql_genstats_soapsql_requests` | Number of SOAP SQL requests started per second | gauge | `mssql_instance` |
| `windows_mssql_genstats_soapwsdl_requests` | Number of SOAP Web Service Description Language requests started per second | gauge | `mssql_instance` |
| `windows_mssql_genstats_sql_trace_io_provider_lock_waits` | Number of waits for the File IO Provider lock per second | gauge | `mssql_instance` |
| `windows_mssql_genstats_tempdb_recovery_unit_ids_generated` | Number of duplicate tempdb recovery unit id generated | gauge | `mssql_instance` |
| `windows_mssql_genstats_tempdb_rowset_ids_generated` | Number of duplicate tempdb rowset id generated | gauge | `mssql_instance` |
| `windows_mssql_genstats_temp_tables_creations` | Number of temporary tables/table variables created per second | counter | `mssql_instance` |
| `windows_mssql_genstats_temp_tables_awaiting_destruction` | Number of temporary tables/table variables waiting to be destroyed by the cleanup system thread | gauge | `mssql_instance` |
| `windows_mssql_genstats_trace_event_notification_queue_size` | Number of trace event notification instances waiting in the internal queue to be sent through Service Broker | gauge | `mssql_instance` |
| `windows_mssql_genstats_transactions` | Number of transaction enlistments (local, DTC, bound all combined) | gauge | `mssql_instance` |
| `windows_mssql_genstats_user_connections` | Counts the number of users currently connected to SQL Server | gauge | `mssql_instance` |
| `windows_mssql_locks_average_wait_seconds` | Average amount of wait time (in milliseconds) for each lock request that resulted in a wait | gauge | `mssql_instance`, `resource` |
| `windows_mssql_locks_lock_requests` | Number of new locks and lock conversions per second requested from the lock manager | counter | `mssql_instance`, `resource` |
| `windows_mssql_locks_lock_timeouts` | Number of lock requests per second that timed out, including requests for NOWAIT locks | counter | `mssql_instance`, `resource` |
| `windows_mssql_locks_lock_timeouts_excluding_NOWAIT` | Number of lock requests per second that timed out, but excluding requests for NOWAIT locks | counter | `mssql_instance`, `resource` |
| `windows_mssql_locks_lock_waits` | Total wait time (in milliseconds) for locks in the last second | counter | `mssql_instance`, `resource` |
| `windows_mssql_locks_lock_wait_seconds` | Number of lock requests per second that required the caller to wait | gauge | `mssql_instance`, `resource` |
| `windows_mssql_locks_deadlocks` | Number of lock requests per second that resulted in a deadlock | counter | `mssql_instance`, `resource` |
| `windows_mssql_memmgr_connection_memory_bytes` | Specifies the total amount of dynamic memory the server is using for maintaining connections | gauge | `mssql_instance` |
| `windows_mssql_memmgr_database_cache_memory_bytes` | Specifies the amount of memory the server is currently using for the database pages cache | gauge | `mssql_instance` |
| `windows_mssql_memmgr_external_benefit_of_memory` | An internal estimation of the performance benefit from adding memory to a specific cache | gauge | `mssql_instance` |
| `windows_mssql_memmgr_free_memory_bytes` | Specifies the amount of committed memory currently not used by the server | gauge | `mssql_instance` |
| `windows_mssql_memmgr_granted_workspace_memory_bytes` | Specifies the total amount of memory currently granted to executing processes, such as hash, sort, bulk copy, and index creation operations | gauge | `mssql_instance` |
| `windows_mssql_memmgr_lock_blocks` | Specifies the current number of lock blocks in use on the server (refreshed periodically). A lock block represents an individual locked resource, such as a table, page, or row | gauge | `mssql_instance` |
| `windows_mssql_memmgr_allocated_lock_blocks` | Specifies the current number of allocated lock blocks. At server startup, the number of allocated lock blocks plus the number of allocated lock owner blocks depends on the SQL Server Locks configuration option. If more lock blocks are needed, the value increases | gauge | `mssql_instance` |
| `windows_mssql_memmgr_lock_memory_bytes` | Specifies the total amount of dynamic memory the server is using for locks | gauge | `mssql_instance` |
| `windows_mssql_memmgr_lock_owner_blocks` | Specifies the current number of allocated lock owner blocks. At server startup, the number of allocated lock owner blocks and the number of allocated lock blocks depend on the SQL Server Locks configuration option. If more lock owner blocks are needed, the value increases dynamically | gauge | `mssql_instance` |
| `windows_mssql_memmgr_allocated_lock_owner_blocks` | _Not yet documented_ | gauge | `mssql_instance` |
| `windows_mssql_memmgr_log_pool_memory_bytes` | Total amount of dynamic memory the server is using for Log Pool | gauge | `mssql_instance` |
| `windows_mssql_memmgr_maximum_workspace_memory_bytes` | Indicates the maximum amount of memory available for executing processes, such as hash, sort, bulk copy, and index creation operations | gauge | `mssql_instance` |
| `windows_mssql_memmgr_outstanding_memory_grants` | Specifies the total number of processes that have successfully acquired a workspace memory grant | gauge | `mssql_instance` |
| `windows_mssql_memmgr_pending_memory_grants` | Specifies the total number of processes waiting for a workspace memory grant | gauge | `mssql_instance` |
| `windows_mssql_memmgr_optimizer_memory_bytes` | Specifies the total amount of dynamic memory the server is using for query optimization | gauge | `mssql_instance` |
| `windows_mssql_memmgr_reserved_server_memory_bytes` | ndicates the amount of memory the server has reserved for future usage. This counter shows the current unused amount of memory initially granted that is shown in Granted Workspace Memory | gauge | `mssql_instance` |
| `windows_mssql_memmgr_sql_cache_memory_bytes` | Specifies the total amount of dynamic memory the server is using for the dynamic SQL cache | gauge | `mssql_instance` |
| `windows_mssql_memmgr_stolen_server_memory_bytes` | Specifies the amount of memory the server is using for purposes other than database pages | gauge | `mssql_instance` |
| `windows_mssql_memmgr_target_server_memory_bytes` | Indicates the ideal amount of memory the server can consume | gauge | `mssql_instance` |
| `windows_mssql_memmgr_total_server_memory_bytes` | Specifies the amount of memory the server has committed using the memory manager | gauge | `mssql_instance` |
| `windows_mssql_sqlstats_auto_parameterization_attempts` | Number of failed auto-parameterization attempts per second. This should be small. Note that auto-parameterizations are also known as simple parameterizations in later versions of SQL Server | counter | `mssql_instance` |
| `windows_mssql_sqlstats_batch_requests` | _Not yet documented_ | counter | `mssql_instance` |
| `windows_mssql_sqlstats_failed_auto_parameterization_attempts` | _Not yet documented_ | counter | `mssql_instance` |
| `windows_mssql_sqlstats_forced_parameterizations` | Number of successful forced parameterizations per second | counter | `mssql_instance` |
| `windows_mssql_sqlstats_guided_plan_executions` | Number of plan executions per second in which the query plan has been generated by using a plan guide | counter | `mssql_instance` |
| `windows_mssql_sqlstats_misguided_plan_executions` | Number of plan executions per second in which a plan guide could not be honored during plan generation | counter | `mssql_instance` |
| `windows_mssql_sqlstats_safe_auto_parameterization_attempts` | Number of safe auto-parameterization attempts per second | counter | `mssql_instance` |
| `windows_mssql_sqlstats_sql_attentions` | Number of attentions per second | counter | `mssql_instance` |
| `windows_mssql_sqlstats_sql_compilations` | Number of SQL compilations per second | counter | `mssql_instance` |
| `windows_mssql_sqlstats_sql_recompilations` | Number of statement recompiles per second | counter | `mssql_instance` |
| `windows_mssql_sqlstats_unsafe_auto_parameterization_attempts` | Number of unsafe auto-parameterization attempts per second. | counter | `mssql_instance` |
| `windows_mssql_sql_errors_total` | Information for all errors | counter | `mssql_instance`, `resource` |
| `windows_mssql_transactions_tempdb_free_space_bytes` | The amount of space (in kilobytes) available in tempdb | gauge | `mssql_instance` |
| `windows_mssql_transactions_longest_transaction_running_seconds` | The length of time (in seconds) since the start of the transaction that has been active longer than any other current transaction | gauge | `mssql_instance` |
| `windows_mssql_transactions_nonsnapshot_version_active_total` | The number of currently active transactions that are not using snapshot isolation level and have made data modifications that have generated row versions in the tempdb version store | counter | `mssql_instance` |
| `windows_mssql_transactions_snapshot_active_total` | The number of currently active transactions using the snapshot isolation level | counter | `mssql_instance` |
| `windows_mssql_transactions_active` | The number of currently active transactions of all types | gauge | `mssql_instance` |
| `windows_mssql_transactions_update_conflicts_total` | The percentage of those transactions using the snapshot isolation level that have encountered update conflicts within the last second | counter | `mssql_instance` |
| `windows_mssql_transactions_update_snapshot_active_total` | The number of currently active transactions using the snapshot isolation level and have modified data | counter | `mssql_instance` |
| `windows_mssql_transactions_version_cleanup_rate_bytes` | The rate (in kilobytes per second) at which row versions are removed from the snapshot isolation version store in tempdb | gauge | `mssql_instance` |
| `windows_mssql_transactions_version_generation_rate_bytes` | The rate (in kilobytes per second) at which new row versions are added to the snapshot isolation version store in tempdb | gauge | `mssql_instance` |
| `windows_mssql_transactions_version_store_size_bytes` | he amount of space (in kilobytes) in tempdb being used to store snapshot isolation level row versions | gauge | `mssql_instance` |
| `windows_mssql_transactions_version_store_units` | The number of active allocation units in the snapshot isolation version store in tempdb | counter | `mssql_instance` |
| `windows_mssql_transactions_version_store_creation_units` | The number of allocation units that have been created in the snapshot isolation store since the instance of the Database Engine was started | counter | `mssql_instance` |
| `windows_mssql_transactions_version_store_truncation_units` | The number of allocation units that have been removed from the snapshot isolation store since the instance of the Database Engine was started | counter | `mssql_instance` |
| `windows_mssql_waitstats_lock_waits` | Statistics for processes waiting on a lock | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_memory_grant_queue_waits` | Statistics for processes waiting for memory grant to become available | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_thread_safe_memory_objects_waits` | Statistics for processes waiting on thread-safe memory allocators | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_log_write_waits` | Statistics for processes waiting for log buffer to be written | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_log_buffer_waits` | Statistics for processes waiting for log buffer to be available | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_network_io_waits` | Statistics relevant to wait on network I/O | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_page_io_latch_waits` | Statistics relevant to page I/O latches | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_page_latch_waits` | Statistics relevant to page latches, not including I/O latches | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_nonpage_latch_waits` | Statistics relevant to non-page latches | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_wait_for_the_worker_waits` | Statistics relevant to processes waiting for worker to become available | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_workspace_synchronization_waits` | Statistics relevant to processes synchronizing access to workspace | gauge | `mssql_instance`, `item` |
| `windows_mssql_waitstats_transaction_ownership_waits` | Statistics relevant to processes synchronizing access to transaction | gauge | `mssql_instance`, `item` |
### Example metric
@@ -311,4 +316,4 @@ groups:
summary: "SQl EXpress Database size exceeded 10GB"
description: "The database size has grown larger than 10GB. Instance: {{ $labels.instance }}"
```
```

View File

@@ -7,7 +7,8 @@ package main
//goland:noinspection GoUnsortedImport
//nolint:gofumpt
import (
"github.com/prometheus-community/windows_exporter/internal/initiate"
// Its important that we do these first so that we can register with the Windows service control ASAP to avoid timeouts.
"github.com/prometheus-community/windows_exporter/internal/windowsservice"
"context"
"errors"
@@ -19,7 +20,7 @@ import (
"os/signal"
"os/user"
"runtime"
"sort"
"slices"
"strings"
"time"
@@ -28,9 +29,6 @@ import (
"github.com/prometheus-community/windows_exporter/internal/httphandler"
"github.com/prometheus-community/windows_exporter/internal/log"
"github.com/prometheus-community/windows_exporter/internal/log/flag"
"github.com/prometheus-community/windows_exporter/internal/toggle"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils"
"github.com/prometheus-community/windows_exporter/pkg/collector"
"github.com/prometheus/common/version"
"github.com/prometheus/exporter-toolkit/web"
@@ -42,14 +40,14 @@ func main() {
exitCode := run()
// If we are running as a service, we need to signal the service control manager that we are done.
if !initiate.IsService {
if !windowsservice.IsService {
os.Exit(exitCode)
}
initiate.ExitCodeCh <- exitCode
windowsservice.ExitCodeCh <- exitCode
// Wait for the service control manager to signal that we are done.
<-initiate.StopCh
<-windowsservice.StopCh
}
func run() int {
@@ -80,11 +78,7 @@ func run() int {
enabledCollectors = app.Flag(
"collectors.enabled",
"Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default.").
Default(types.DefaultCollectors).String()
printCollectors = app.Flag(
"collectors.print",
"If true, print available collectors and exit.",
).Bool()
Default(collector.DefaultCollectors).String()
timeoutMargin = app.Flag(
"scrape.timeout-margin",
"Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads.",
@@ -97,11 +91,6 @@ func run() int {
"process.priority",
"Priority of the exporter process. Higher priorities may improve exporter responsiveness during periods of system load. Can be one of [\"realtime\", \"high\", \"abovenormal\", \"normal\", \"belownormal\", \"low\"]",
).Default("normal").String()
togglePDH = app.Flag(
"perfcounter.engine",
"EXPERIMENTAL: Performance counter engine to use. Can be one of \"pdh\", \"registry\". PDH is in experimental state. This flag will be removed in 0.31.",
).Default("registry").String()
)
logConfig := &log.Config{}
@@ -179,18 +168,6 @@ func run() int {
logger.Debug("Logging has Started")
if v, ok := os.LookupEnv("WINDOWS_EXPORTER_PERF_COUNTERS_ENGINE"); ok && v == "pdh" || *togglePDH == "pdh" {
logger.Info("Using performance data helper from PHD.dll for performance counter collection. This is in experimental state.")
toggle.PHDEnabled = true
}
if *printCollectors {
printCollectorsToStdout()
return 0
}
if err = setPriorityWindows(logger, os.Getpid(), *processPriority); err != nil {
logger.Error("failed to set process priority",
slog.Any("err", err),
@@ -199,9 +176,11 @@ func run() int {
return 1
}
enabledCollectorList := utils.ExpandEnabledCollectors(*enabledCollectors)
enabledCollectorList := expandEnabledCollectors(*enabledCollectors)
if err := collectors.Enable(enabledCollectorList); err != nil {
logger.Error(err.Error())
logger.Error("Couldn't enable collectors",
slog.Any("err", err),
)
return 1
}
@@ -215,14 +194,6 @@ func run() int {
return 1
}
if err = collectors.SetPerfCounterQuery(logger); err != nil {
logger.Error("Couldn't set performance counter query",
slog.Any("err", err),
)
return 1
}
logCurrentUser(logger)
logger.Info("Enabled collectors: " + strings.Join(enabledCollectorList, ", "))
@@ -268,7 +239,7 @@ func run() int {
errCh <- err
}
errCh <- nil
close(errCh)
}()
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
@@ -277,7 +248,7 @@ func run() int {
select {
case <-ctx.Done():
logger.Info("Shutting down windows_exporter via kill signal")
case <-initiate.StopCh:
case <-windowsservice.StopCh:
logger.Info("Shutting down windows_exporter via service control")
case err := <-errCh:
if err != nil {
@@ -299,17 +270,6 @@ func run() int {
return 0
}
func printCollectorsToStdout() {
collectorNames := collector.Available()
sort.Strings(collectorNames)
fmt.Println("Available collectors:") //nolint:forbidigo
for _, n := range collectorNames {
fmt.Printf(" - %s\n", n) //nolint:forbidigo
}
}
func logCurrentUser(logger *slog.Logger) {
u, err := user.Current()
if err != nil {
@@ -367,3 +327,9 @@ func setPriorityWindows(logger *slog.Logger, pid int, priority string) error {
return nil
}
func expandEnabledCollectors(enabled string) []string {
expanded := strings.ReplaceAll(enabled, "[defaults]", collector.DefaultCollectors)
return slices.Compact(strings.Split(expanded, ","))
}

2
go.mod
View File

@@ -3,6 +3,7 @@ module github.com/prometheus-community/windows_exporter
go 1.23
require (
github.com/Microsoft/go-winio v0.6.2
github.com/Microsoft/hcsshim v0.12.9
github.com/alecthomas/kingpin/v2 v2.4.0
github.com/bmatcuk/doublestar/v4 v4.7.1
@@ -19,7 +20,6 @@ require (
)
require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect

View File

@@ -20,11 +20,10 @@ type Config struct{}
var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics.
type Collector struct {
config Config
perfDataCollector perfdata.Collector
perfDataCollector *perfdata.Collector
addressBookClientSessions *prometheus.Desc
addressBookOperationsTotal *prometheus.Desc
@@ -110,11 +109,9 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close() error {
c.perfDataCollector.Close()
func (c *Collector) Close(_ *slog.Logger) error {
return nil
}
@@ -268,7 +265,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V1, "DirectoryServices", perfdata.AllInstances, counters)
c.perfDataCollector, err = perfdata.NewCollector("DirectoryServices", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create DirectoryServices collector: %w", err)
}
@@ -652,11 +649,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error {
return c.collect(ch)
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect DirectoryServices (AD) metrics: %w", err)

View File

@@ -1,10 +1,12 @@
//go:build windows
package ad_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/ad"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -205,155 +205,3 @@ const (
_ = "Warning eventlogs since boot"
_ = "Warning events since boot"
)
// Win32_PerfRawData_DirectoryServices_DirectoryServices docs:
// - https://msdn.microsoft.com/en-us/library/ms803980.aspx
type Win32_PerfRawData_DirectoryServices_DirectoryServices struct {
Name string
ABANRPersec uint32
ABBrowsesPersec uint32
ABClientSessions uint32
ABMatchesPersec uint32
ABPropertyReadsPersec uint32
ABProxyLookupsPersec uint32
ABSearchesPersec uint32
ApproximatehighestDNT uint32
ATQEstimatedQueueDelay uint32
ATQOutstandingQueuedRequests uint32
ATQRequestLatency uint32
ATQThreadsLDAP uint32
ATQThreadsOther uint32
ATQThreadsTotal uint32
BasesearchesPersec uint32
DatabaseaddsPersec uint32
DatabasedeletesPersec uint32
DatabasemodifysPersec uint32
DatabaserecyclesPersec uint32
DigestBindsPersec uint32
DRAHighestUSNCommittedHighpart uint64
DRAHighestUSNCommittedLowpart uint64
DRAHighestUSNIssuedHighpart uint64
DRAHighestUSNIssuedLowpart uint64
DRAInboundBytesCompressedBetweenSitesAfterCompressionPersec uint32
DRAInboundBytesCompressedBetweenSitesAfterCompressionSinceBoot uint32
DRAInboundBytesCompressedBetweenSitesBeforeCompressionPersec uint32
DRAInboundBytesCompressedBetweenSitesBeforeCompressionSinceBoot uint32
DRAInboundBytesNotCompressedWithinSitePersec uint32
DRAInboundBytesNotCompressedWithinSiteSinceBoot uint32
DRAInboundBytesTotalPersec uint32
DRAInboundBytesTotalSinceBoot uint32
DRAInboundFullSyncObjectsRemaining uint32
DRAInboundLinkValueUpdatesRemaininginPacket uint32
DRAInboundObjectsAppliedPersec uint32
DRAInboundObjectsFilteredPersec uint32
DRAInboundObjectsPersec uint32
DRAInboundObjectUpdatesRemaininginPacket uint32
DRAInboundPropertiesAppliedPersec uint32
DRAInboundPropertiesFilteredPersec uint32
DRAInboundPropertiesTotalPersec uint32
DRAInboundTotalUpdatesRemaininginPacket uint32
DRAInboundValuesDNsonlyPersec uint32
DRAInboundValuesTotalPersec uint32
DRAOutboundBytesCompressedBetweenSitesAfterCompressionPersec uint32
DRAOutboundBytesCompressedBetweenSitesAfterCompressionSinceBoot uint32
DRAOutboundBytesCompressedBetweenSitesBeforeCompressionPersec uint32
DRAOutboundBytesCompressedBetweenSitesBeforeCompressionSinceBoot uint32
DRAOutboundBytesNotCompressedWithinSitePersec uint32
DRAOutboundBytesNotCompressedWithinSiteSinceBoot uint32
DRAOutboundBytesTotalPersec uint32
DRAOutboundBytesTotalSinceBoot uint32
DRAOutboundObjectsFilteredPersec uint32
DRAOutboundObjectsPersec uint32
DRAOutboundPropertiesPersec uint32
DRAOutboundValuesDNsonlyPersec uint32
DRAOutboundValuesTotalPersec uint32
DRAPendingReplicationOperations uint32
DRAPendingReplicationSynchronizations uint32
DRASyncFailuresonSchemaMismatch uint32
DRASyncRequestsMade uint32
DRASyncRequestsSuccessful uint32
DRAThreadsGettingNCChanges uint32
DRAThreadsGettingNCChangesHoldingSemaphore uint32
DSClientBindsPersec uint32
DSClientNameTranslationsPersec uint32
DSDirectoryReadsPersec uint32
DSDirectorySearchesPersec uint32
DSDirectoryWritesPersec uint32
DSMonitorListSize uint32
DSNameCachehitrate uint32
DSNameCachehitrate_Base uint32
DSNotifyQueueSize uint32
DSPercentReadsfromDRA uint32
DSPercentReadsfromKCC uint32
DSPercentReadsfromLSA uint32
DSPercentReadsfromNSPI uint32
DSPercentReadsfromNTDSAPI uint32
DSPercentReadsfromSAM uint32
DSPercentReadsOther uint32
DSPercentSearchesfromDRA uint32
DSPercentSearchesfromKCC uint32
DSPercentSearchesfromLDAP uint32
DSPercentSearchesfromLSA uint32
DSPercentSearchesfromNSPI uint32
DSPercentSearchesfromNTDSAPI uint32
DSPercentSearchesfromSAM uint32
DSPercentSearchesOther uint32
DSPercentWritesfromDRA uint32
DSPercentWritesfromKCC uint32
DSPercentWritesfromLDAP uint32
DSPercentWritesfromLSA uint32
DSPercentWritesfromNSPI uint32
DSPercentWritesfromNTDSAPI uint32
DSPercentWritesfromSAM uint32
DSPercentWritesOther uint32
DSSearchsuboperationsPersec uint32
DSSecurityDescriptorPropagationsEvents uint32
DSSecurityDescriptorPropagatorAverageExclusionTime uint32
DSSecurityDescriptorPropagatorRuntimeQueue uint32
DSSecurityDescriptorsuboperationsPersec uint32
DSServerBindsPersec uint32
DSServerNameTranslationsPersec uint32
DSThreadsinUse uint32
ExternalBindsPersec uint32
FastBindsPersec uint32
LDAPActiveThreads uint32
LDAPBindTime uint32
LDAPClientSessions uint32
LDAPClosedConnectionsPersec uint32
LDAPNewConnectionsPersec uint32
LDAPNewSSLConnectionsPersec uint32
LDAPSearchesPersec uint32
LDAPSuccessfulBindsPersec uint32
LDAPUDPoperationsPersec uint32
LDAPWritesPersec uint32
LinkValuesCleanedPersec uint32
NegotiatedBindsPersec uint32
NTLMBindsPersec uint32
OnelevelsearchesPersec uint32
PhantomsCleanedPersec uint32
PhantomsVisitedPersec uint32
SAMAccountGroupEvaluationLatency uint32
SAMDisplayInformationQueriesPersec uint32
SAMDomainLocalGroupMembershipEvaluationsPersec uint32
SAMEnumerationsPersec uint32
SAMGCEvaluationsPersec uint32
SAMGlobalGroupMembershipEvaluationsPersec uint32
SAMMachineCreationAttemptsPersec uint32
SAMMembershipChangesPersec uint32
SAMNonTransitiveMembershipEvaluationsPersec uint32
SAMPasswordChangesPersec uint32
SAMResourceGroupEvaluationLatency uint32
SAMSuccessfulComputerCreationsPersecIncludesallrequests uint32
SAMSuccessfulUserCreationsPersec uint32
SAMTransitiveMembershipEvaluationsPersec uint32
SAMUniversalGroupMembershipEvaluationsPersec uint32
SAMUserCreationAttemptsPersec uint32
SimpleBindsPersec uint32
SubtreesearchesPersec uint32
TombstonesGarbageCollectedPersec uint32
TombstonesVisitedPersec uint32
Transitiveoperationsmillisecondsrun uint32
TransitiveoperationsPersec uint32
TransitivesuboperationsPersec uint32
}

View File

@@ -10,8 +10,6 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/toggle"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils"
"github.com/prometheus/client_golang/prometheus"
@@ -26,7 +24,7 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config
perfDataCollector perfdata.Collector
perfDataCollector *perfdata.Collector
challengeResponseProcessingTime *prometheus.Desc
challengeResponsesPerSecond *prometheus.Desc
@@ -63,42 +61,32 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
if toggle.IsPDHEnabled() {
return []string{}, nil
}
func (c *Collector) Close() error {
c.perfDataCollector.Close()
return []string{"Certification Authority"}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
if toggle.IsPDHEnabled() {
counters := []string{
requestsPerSecond,
requestProcessingTime,
retrievalsPerSecond,
retrievalProcessingTime,
failedRequestsPerSecond,
issuedRequestsPerSecond,
pendingRequestsPerSecond,
requestCryptographicSigningTime,
requestPolicyModuleProcessingTime,
challengeResponsesPerSecond,
challengeResponseProcessingTime,
signedCertificateTimestampListsPerSecond,
signedCertificateTimestampListProcessingTime,
}
var err error
var err error
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V1, "Certification Authority", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create Certification Authority collector: %w", err)
}
c.perfDataCollector, err = perfdata.NewCollector("Certification Authority", perfdata.InstanceAll, []string{
requestsPerSecond,
requestProcessingTime,
retrievalsPerSecond,
retrievalProcessingTime,
failedRequestsPerSecond,
issuedRequestsPerSecond,
pendingRequestsPerSecond,
requestCryptographicSigningTime,
requestPolicyModuleProcessingTime,
challengeResponsesPerSecond,
challengeResponseProcessingTime,
signedCertificateTimestampListsPerSecond,
signedCertificateTimestampListProcessingTime,
})
if err != nil {
return fmt.Errorf("failed to create Certification Authority collector: %w", err)
}
c.requestsPerSecond = prometheus.NewDesc(
@@ -183,128 +171,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
return nil
}
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
if toggle.IsPDHEnabled() {
return c.collectPDH(ch)
}
logger = logger.With(slog.String("collector", Name))
if err := c.collectADCSCounters(ctx, logger, ch); err != nil {
logger.Error("failed collecting ADCS metrics",
slog.Any("err", err),
)
return err
}
return nil
}
func (c *Collector) collectADCSCounters(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
dst := make([]perflibADCS, 0)
if _, ok := ctx.PerfObjects["Certification Authority"]; !ok {
return errors.New("perflib did not contain an entry for Certification Authority")
}
err := v1.UnmarshalObject(ctx.PerfObjects["Certification Authority"], &dst, logger)
if err != nil {
return err
}
if len(dst) == 0 {
return errors.New("perflib query for Certification Authority (ADCS) returned empty result set")
}
for _, d := range dst {
if d.Name == "" {
continue
}
ch <- prometheus.MustNewConstMetric(
c.requestsPerSecond,
prometheus.CounterValue,
d.RequestsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.requestProcessingTime,
prometheus.GaugeValue,
utils.MilliSecToSec(d.RequestProcessingTime),
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.retrievalsPerSecond,
prometheus.CounterValue,
d.RetrievalsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.retrievalProcessingTime,
prometheus.GaugeValue,
utils.MilliSecToSec(d.RetrievalProcessingTime),
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.failedRequestsPerSecond,
prometheus.CounterValue,
d.FailedRequestsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.issuedRequestsPerSecond,
prometheus.CounterValue,
d.IssuedRequestsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.pendingRequestsPerSecond,
prometheus.CounterValue,
d.PendingRequestsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.requestCryptographicSigningTime,
prometheus.GaugeValue,
utils.MilliSecToSec(d.RequestCryptographicSigningTime),
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.requestPolicyModuleProcessingTime,
prometheus.GaugeValue,
utils.MilliSecToSec(d.RequestPolicyModuleProcessingTime),
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.challengeResponsesPerSecond,
prometheus.CounterValue,
d.ChallengeResponsesPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.challengeResponseProcessingTime,
prometheus.GaugeValue,
utils.MilliSecToSec(d.ChallengeResponseProcessingTime),
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.signedCertificateTimestampListsPerSecond,
prometheus.CounterValue,
d.SignedCertificateTimestampListsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.signedCertificateTimestampListProcessingTime,
prometheus.GaugeValue,
utils.MilliSecToSec(d.SignedCertificateTimestampListProcessingTime),
d.Name,
)
}
return nil
}
func (c *Collector) collectPDH(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect Certification Authority (ADCS) metrics: %w", err)

View File

@@ -1,10 +1,12 @@
//go:build windows
package adcs_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/adcs"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,3 +1,5 @@
//go:build windows
package adcs
const (
@@ -15,20 +17,3 @@ const (
signedCertificateTimestampListProcessingTime = "Signed Certificate Timestamp List processing time (ms)"
signedCertificateTimestampListsPerSecond = "Signed Certificate Timestamp Lists/sec"
)
type perflibADCS struct {
Name string
RequestsPerSecond float64 `perflib:"Requests/sec"`
RequestProcessingTime float64 `perflib:"Request processing time (ms)"`
RetrievalsPerSecond float64 `perflib:"Retrievals/sec"`
RetrievalProcessingTime float64 `perflib:"Retrieval processing time (ms)"`
FailedRequestsPerSecond float64 `perflib:"Failed Requests/sec"`
IssuedRequestsPerSecond float64 `perflib:"Issued Requests/sec"`
PendingRequestsPerSecond float64 `perflib:"Pending Requests/sec"`
RequestCryptographicSigningTime float64 `perflib:"Request cryptographic signing time (ms)"`
RequestPolicyModuleProcessingTime float64 `perflib:"Request policy module processing time (ms)"`
ChallengeResponsesPerSecond float64 `perflib:"Challenge Responses/sec"`
ChallengeResponseProcessingTime float64 `perflib:"Challenge Response processing time (ms)"`
SignedCertificateTimestampListsPerSecond float64 `perflib:"Signed Certificate Timestamp Lists/sec"`
SignedCertificateTimestampListProcessingTime float64 `perflib:"Signed Certificate Timestamp List processing time (ms)"`
}

View File

@@ -13,8 +13,6 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/toggle"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -28,7 +26,7 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config
perfDataCollector perfdata.Collector
perfDataCollector *perfdata.Collector
adLoginConnectionFailures *prometheus.Desc
artifactDBFailures *prometheus.Desc
@@ -95,72 +93,62 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
if toggle.IsPDHEnabled() {
return []string{}, nil
}
func (c *Collector) Close() error {
c.perfDataCollector.Close()
return []string{"AD FS"}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
if toggle.IsPDHEnabled() {
counters := []string{
adLoginConnectionFailures,
certificateAuthentications,
deviceAuthentications,
extranetAccountLockouts,
federatedAuthentications,
passportAuthentications,
passiveRequests,
passwordChangeFailed,
passwordChangeSucceeded,
tokenRequests,
windowsIntegratedAuthentications,
oAuthAuthZRequests,
oAuthClientAuthentications,
oAuthClientAuthenticationFailures,
oAuthClientCredentialRequestFailures,
oAuthClientCredentialRequests,
oAuthClientPrivateKeyJWTAuthenticationFailures,
oAuthClientPrivateKeyJWTAuthentications,
oAuthClientBasicAuthenticationFailures,
oAuthClientBasicAuthentications,
oAuthClientSecretPostAuthenticationFailures,
oAuthClientSecretPostAuthentications,
oAuthClientWindowsAuthenticationFailures,
oAuthClientWindowsAuthentications,
oAuthLogonCertRequestFailures,
oAuthLogonCertTokenRequests,
oAuthPasswordGrantRequestFailures,
oAuthPasswordGrantRequests,
oAuthTokenRequests,
samlPTokenRequests,
ssoAuthenticationFailures,
ssoAuthentications,
wsFedTokenRequests,
wsTrustTokenRequests,
usernamePasswordAuthenticationFailures,
usernamePasswordAuthentications,
externalAuthentications,
externalAuthNFailures,
artifactDBFailures,
avgArtifactDBQueryTime,
configDBFailures,
avgConfigDBQueryTime,
federationMetadataRequests,
}
var err error
var err error
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V1, "AD FS", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create AD FS collector: %w", err)
}
c.perfDataCollector, err = perfdata.NewCollector("AD FS", perfdata.InstanceAll, []string{
adLoginConnectionFailures,
certificateAuthentications,
deviceAuthentications,
extranetAccountLockouts,
federatedAuthentications,
passportAuthentications,
passiveRequests,
passwordChangeFailed,
passwordChangeSucceeded,
tokenRequests,
windowsIntegratedAuthentications,
oAuthAuthZRequests,
oAuthClientAuthentications,
oAuthClientAuthenticationFailures,
oAuthClientCredentialRequestFailures,
oAuthClientCredentialRequests,
oAuthClientPrivateKeyJWTAuthenticationFailures,
oAuthClientPrivateKeyJWTAuthentications,
oAuthClientBasicAuthenticationFailures,
oAuthClientBasicAuthentications,
oAuthClientSecretPostAuthenticationFailures,
oAuthClientSecretPostAuthentications,
oAuthClientWindowsAuthenticationFailures,
oAuthClientWindowsAuthentications,
oAuthLogonCertRequestFailures,
oAuthLogonCertTokenRequests,
oAuthPasswordGrantRequestFailures,
oAuthPasswordGrantRequests,
oAuthTokenRequests,
samlPTokenRequests,
ssoAuthenticationFailures,
ssoAuthentications,
wsFedTokenRequests,
wsTrustTokenRequests,
usernamePasswordAuthenticationFailures,
usernamePasswordAuthentications,
externalAuthentications,
externalAuthNFailures,
artifactDBFailures,
avgArtifactDBQueryTime,
configDBFailures,
avgConfigDBQueryTime,
federationMetadataRequests,
})
if err != nil {
return fmt.Errorf("failed to create AD FS collector: %w", err)
}
c.adLoginConnectionFailures = prometheus.NewDesc(
@@ -425,286 +413,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
return nil
}
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
if toggle.IsPDHEnabled() {
return c.collectPDH(ch)
}
logger = logger.With(slog.String("collector", Name))
return c.collect(ctx, logger, ch)
}
func (c *Collector) collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var adfsData []perflibADFS
err := v1.UnmarshalObject(ctx.PerfObjects["AD FS"], &adfsData, logger)
if err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(
c.adLoginConnectionFailures,
prometheus.CounterValue,
adfsData[0].AdLoginConnectionFailures,
)
ch <- prometheus.MustNewConstMetric(
c.certificateAuthentications,
prometheus.CounterValue,
adfsData[0].CertificateAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.deviceAuthentications,
prometheus.CounterValue,
adfsData[0].DeviceAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.extranetAccountLockouts,
prometheus.CounterValue,
adfsData[0].ExtranetAccountLockouts,
)
ch <- prometheus.MustNewConstMetric(
c.federatedAuthentications,
prometheus.CounterValue,
adfsData[0].FederatedAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.passportAuthentications,
prometheus.CounterValue,
adfsData[0].PassportAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.passiveRequests,
prometheus.CounterValue,
adfsData[0].PassiveRequests,
)
ch <- prometheus.MustNewConstMetric(
c.passwordChangeFailed,
prometheus.CounterValue,
adfsData[0].PasswordChangeFailed,
)
ch <- prometheus.MustNewConstMetric(
c.passwordChangeSucceeded,
prometheus.CounterValue,
adfsData[0].PasswordChangeSucceeded,
)
ch <- prometheus.MustNewConstMetric(
c.tokenRequests,
prometheus.CounterValue,
adfsData[0].TokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.windowsIntegratedAuthentications,
prometheus.CounterValue,
adfsData[0].WindowsIntegratedAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthAuthZRequests,
prometheus.CounterValue,
adfsData[0].OAuthAuthZRequests,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientAuthentications,
prometheus.CounterValue,
adfsData[0].OAuthClientAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientAuthenticationsFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientAuthenticationFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientCredentialsRequestFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientCredentialRequestFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientCredentialsRequests,
prometheus.CounterValue,
adfsData[0].OAuthClientCredentialRequests,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientPrivateKeyJwtAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientPrivKeyJWTAuthnFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientPrivateKeyJwtAuthentications,
prometheus.CounterValue,
adfsData[0].OAuthClientPrivKeyJWTAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientSecretBasicAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientBasicAuthnFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientSecretBasicAuthentications,
prometheus.CounterValue,
adfsData[0].OAuthClientBasicAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientSecretPostAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientSecretPostAuthnFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientSecretPostAuthentications,
prometheus.CounterValue,
adfsData[0].OAuthClientSecretPostAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientWindowsIntegratedAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientWindowsAuthnFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientWindowsIntegratedAuthentications,
prometheus.CounterValue,
adfsData[0].OAuthClientWindowsAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthLogonCertificateRequestFailures,
prometheus.CounterValue,
adfsData[0].OAuthLogonCertRequestFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthLogonCertificateTokenRequests,
prometheus.CounterValue,
adfsData[0].OAuthLogonCertTokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthPasswordGrantRequestFailures,
prometheus.CounterValue,
adfsData[0].OAuthPasswordGrantRequestFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthPasswordGrantRequests,
prometheus.CounterValue,
adfsData[0].OAuthPasswordGrantRequests,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthTokenRequests,
prometheus.CounterValue,
adfsData[0].OAuthTokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.samlPTokenRequests,
prometheus.CounterValue,
adfsData[0].SAMLPTokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.ssoAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].SSOAuthenticationFailures,
)
ch <- prometheus.MustNewConstMetric(
c.ssoAuthentications,
prometheus.CounterValue,
adfsData[0].SSOAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.wsFedTokenRequests,
prometheus.CounterValue,
adfsData[0].WSFedTokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.wsTrustTokenRequests,
prometheus.CounterValue,
adfsData[0].WSTrustTokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.upAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].UsernamePasswordAuthnFailures,
)
ch <- prometheus.MustNewConstMetric(
c.upAuthentications,
prometheus.CounterValue,
adfsData[0].UsernamePasswordAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.externalAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].ExternalAuthNFailures,
)
ch <- prometheus.MustNewConstMetric(
c.externalAuthentications,
prometheus.CounterValue,
adfsData[0].ExternalAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.artifactDBFailures,
prometheus.CounterValue,
adfsData[0].ArtifactDBFailures,
)
ch <- prometheus.MustNewConstMetric(
c.avgArtifactDBQueryTime,
prometheus.CounterValue,
adfsData[0].AvgArtifactDBQueryTime*math.Pow(10, -8),
)
ch <- prometheus.MustNewConstMetric(
c.configDBFailures,
prometheus.CounterValue,
adfsData[0].ConfigDBFailures,
)
ch <- prometheus.MustNewConstMetric(
c.avgConfigDBQueryTime,
prometheus.CounterValue,
adfsData[0].AvgConfigDBQueryTime*math.Pow(10, -8),
)
ch <- prometheus.MustNewConstMetric(
c.federationMetadataRequests,
prometheus.CounterValue,
adfsData[0].FederationMetadataRequests,
)
return nil
}
func (c *Collector) collectPDH(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect ADFS metrics: %w", err)

View File

@@ -1,10 +1,12 @@
//go:build windows
package adfs_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/adfs"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,3 +1,5 @@
//go:build windows
package adfs
const (
@@ -45,49 +47,3 @@ const (
wsFedTokenRequests = "WS-Fed Token Requests"
wsTrustTokenRequests = "WS-Trust Token Requests"
)
type perflibADFS struct {
AdLoginConnectionFailures float64 `perflib:"AD Login Connection Failures"`
CertificateAuthentications float64 `perflib:"Certificate Authentications"`
DeviceAuthentications float64 `perflib:"Device Authentications"`
ExtranetAccountLockouts float64 `perflib:"Extranet Account Lockouts"`
FederatedAuthentications float64 `perflib:"Federated Authentications"`
PassportAuthentications float64 `perflib:"Microsoft Passport Authentications"`
PassiveRequests float64 `perflib:"Passive Requests"`
PasswordChangeFailed float64 `perflib:"Password Change Failed Requests"`
PasswordChangeSucceeded float64 `perflib:"Password Change Successful Requests"`
TokenRequests float64 `perflib:"Token Requests"`
WindowsIntegratedAuthentications float64 `perflib:"Windows Integrated Authentications"`
OAuthAuthZRequests float64 `perflib:"OAuth AuthZ Requests"`
OAuthClientAuthentications float64 `perflib:"OAuth Client Authentications"`
OAuthClientAuthenticationFailures float64 `perflib:"OAuth Client Authentications Failures"`
OAuthClientCredentialRequestFailures float64 `perflib:"OAuth Client Credentials Request Failures"`
OAuthClientCredentialRequests float64 `perflib:"OAuth Client Credentials Requests"`
OAuthClientPrivKeyJWTAuthnFailures float64 `perflib:"OAuth Client Private Key Jwt Authentication Failures"`
OAuthClientPrivKeyJWTAuthentications float64 `perflib:"OAuth Client Private Key Jwt Authentications"`
OAuthClientBasicAuthnFailures float64 `perflib:"OAuth Client Secret Basic Authentication Failures"`
OAuthClientBasicAuthentications float64 `perflib:"OAuth Client Secret Basic Authentication Requests"`
OAuthClientSecretPostAuthnFailures float64 `perflib:"OAuth Client Secret Post Authentication Failures"`
OAuthClientSecretPostAuthentications float64 `perflib:"OAuth Client Secret Post Authentications"`
OAuthClientWindowsAuthnFailures float64 `perflib:"OAuth Client Windows Integrated Authentication Failures"`
OAuthClientWindowsAuthentications float64 `perflib:"OAuth Client Windows Integrated Authentications"`
OAuthLogonCertRequestFailures float64 `perflib:"OAuth Logon Certificate Request Failures"`
OAuthLogonCertTokenRequests float64 `perflib:"OAuth Logon Certificate Token Requests"`
OAuthPasswordGrantRequestFailures float64 `perflib:"OAuth Password Grant Request Failures"`
OAuthPasswordGrantRequests float64 `perflib:"OAuth Password Grant Requests"`
OAuthTokenRequests float64 `perflib:"OAuth Token Requests"`
SAMLPTokenRequests float64 `perflib:"SAML-P Token Requests"`
SSOAuthenticationFailures float64 `perflib:"SSO Authentication Failures"`
SSOAuthentications float64 `perflib:"SSO Authentications"`
WSFedTokenRequests float64 `perflib:"WS-Fed Token Requests"`
WSTrustTokenRequests float64 `perflib:"WS-Trust Token Requests"`
UsernamePasswordAuthnFailures float64 `perflib:"U/P Authentication Failures"`
UsernamePasswordAuthentications float64 `perflib:"U/P Authentications"`
ExternalAuthentications float64 `perflib:"External Authentications"`
ExternalAuthNFailures float64 `perflib:"External Authentication Failures"`
ArtifactDBFailures float64 `perflib:"Artifact Database Connection Failures"`
AvgArtifactDBQueryTime float64 `perflib:"Average Artifact Database Query Time"`
ConfigDBFailures float64 `perflib:"Configuration Database Connection Failures"`
AvgConfigDBQueryTime float64 `perflib:"Average Config Database Query Time"`
FederationMetadataRequests float64 `perflib:"Federation Metadata Requests"`
}

View File

@@ -10,9 +10,6 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/toggle"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -27,7 +24,7 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config
perfDataCollector perfdata.Collector
perfDataCollector *perfdata.Collector
asyncCopyReadsTotal *prometheus.Desc
asyncDataMapsTotal *prometheus.Desc
@@ -80,58 +77,48 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
if toggle.IsPDHEnabled() {
return []string{}, nil
}
func (c *Collector) Close() error {
c.perfDataCollector.Close()
return []string{"Cache"}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
if toggle.IsPDHEnabled() {
counters := []string{
asyncCopyReadsTotal,
asyncDataMapsTotal,
asyncFastReadsTotal,
asyncMDLReadsTotal,
asyncPinReadsTotal,
copyReadHitsTotal,
copyReadsTotal,
dataFlushesTotal,
dataFlushPagesTotal,
dataMapHitsPercent,
dataMapPinsTotal,
dataMapsTotal,
dirtyPages,
dirtyPageThreshold,
fastReadNotPossiblesTotal,
fastReadResourceMissesTotal,
fastReadsTotal,
lazyWriteFlushesTotal,
lazyWritePagesTotal,
mdlReadHitsTotal,
mdlReadsTotal,
pinReadHitsTotal,
pinReadsTotal,
readAheadsTotal,
syncCopyReadsTotal,
syncDataMapsTotal,
syncFastReadsTotal,
syncMDLReadsTotal,
syncPinReadsTotal,
}
var err error
var err error
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V1, "Cache", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create Cache collector: %w", err)
}
c.perfDataCollector, err = perfdata.NewCollector("Cache", perfdata.InstanceAll, []string{
asyncCopyReadsTotal,
asyncDataMapsTotal,
asyncFastReadsTotal,
asyncMDLReadsTotal,
asyncPinReadsTotal,
copyReadHitsTotal,
copyReadsTotal,
dataFlushesTotal,
dataFlushPagesTotal,
dataMapHitsPercent,
dataMapPinsTotal,
dataMapsTotal,
dirtyPages,
dirtyPageThreshold,
fastReadNotPossiblesTotal,
fastReadResourceMissesTotal,
fastReadsTotal,
lazyWriteFlushesTotal,
lazyWritePagesTotal,
mdlReadHitsTotal,
mdlReadsTotal,
pinReadHitsTotal,
pinReadsTotal,
readAheadsTotal,
syncCopyReadsTotal,
syncDataMapsTotal,
syncFastReadsTotal,
syncMDLReadsTotal,
syncPinReadsTotal,
})
if err != nil {
return fmt.Errorf("failed to create Cache collector: %w", err)
}
c.asyncCopyReadsTotal = prometheus.NewDesc(
@@ -313,218 +300,13 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
}
// Collect implements the Collector interface.
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
if toggle.IsPDHEnabled() {
return c.collectPDH(ch)
}
logger = logger.With(slog.String("collector", Name))
if err := c.collect(ctx, logger, ch); err != nil {
logger.Error("failed collecting cache metrics",
slog.Any("err", err),
)
return err
}
return nil
}
func (c *Collector) collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var dst []perflibCache // Single-instance class, array is required but will have single entry.
if err := v1.UnmarshalObject(ctx.PerfObjects["Cache"], &dst, logger); err != nil {
return err
}
if len(dst) != 1 {
return errors.New("expected single instance of Cache")
}
ch <- prometheus.MustNewConstMetric(
c.asyncCopyReadsTotal,
prometheus.CounterValue,
dst[0].AsyncCopyReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.asyncDataMapsTotal,
prometheus.CounterValue,
dst[0].AsyncDataMapsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.asyncFastReadsTotal,
prometheus.CounterValue,
dst[0].AsyncFastReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.asyncMDLReadsTotal,
prometheus.CounterValue,
dst[0].AsyncMDLReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.asyncPinReadsTotal,
prometheus.CounterValue,
dst[0].AsyncPinReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.copyReadHitsTotal,
prometheus.GaugeValue,
dst[0].CopyReadHitsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.copyReadsTotal,
prometheus.CounterValue,
dst[0].CopyReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.dataFlushesTotal,
prometheus.CounterValue,
dst[0].DataFlushesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.dataFlushPagesTotal,
prometheus.CounterValue,
dst[0].DataFlushPagesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.dataMapHitsPercent,
prometheus.GaugeValue,
dst[0].DataMapHitsPercent,
)
ch <- prometheus.MustNewConstMetric(
c.dataMapPinsTotal,
prometheus.CounterValue,
dst[0].DataMapPinsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.dataMapsTotal,
prometheus.CounterValue,
dst[0].DataMapsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.dirtyPages,
prometheus.GaugeValue,
dst[0].DirtyPages,
)
ch <- prometheus.MustNewConstMetric(
c.dirtyPageThreshold,
prometheus.GaugeValue,
dst[0].DirtyPageThreshold,
)
ch <- prometheus.MustNewConstMetric(
c.fastReadNotPossiblesTotal,
prometheus.CounterValue,
dst[0].FastReadNotPossiblesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.fastReadResourceMissesTotal,
prometheus.CounterValue,
dst[0].FastReadResourceMissesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.fastReadsTotal,
prometheus.CounterValue,
dst[0].FastReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.lazyWriteFlushesTotal,
prometheus.CounterValue,
dst[0].LazyWriteFlushesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.lazyWritePagesTotal,
prometheus.CounterValue,
dst[0].LazyWritePagesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.mdlReadHitsTotal,
prometheus.CounterValue,
dst[0].MDLReadHitsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.mdlReadsTotal,
prometheus.CounterValue,
dst[0].MDLReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.pinReadHitsTotal,
prometheus.CounterValue,
dst[0].PinReadHitsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.pinReadsTotal,
prometheus.CounterValue,
dst[0].PinReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.readAheadsTotal,
prometheus.CounterValue,
dst[0].ReadAheadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.syncCopyReadsTotal,
prometheus.CounterValue,
dst[0].SyncCopyReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.syncDataMapsTotal,
prometheus.CounterValue,
dst[0].SyncDataMapsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.syncFastReadsTotal,
prometheus.CounterValue,
dst[0].SyncFastReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.syncMDLReadsTotal,
prometheus.CounterValue,
dst[0].SyncMDLReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.syncPinReadsTotal,
prometheus.CounterValue,
dst[0].SyncPinReadsTotal,
)
return nil
}
func (c *Collector) collectPDH(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect Cache metrics: %w", err)
}
cacheData, ok := data[perftypes.EmptyInstance]
cacheData, ok := data[perfdata.EmptyInstance]
if !ok {
return errors.New("perflib query for Cache returned empty result set")

View File

@@ -1,10 +1,12 @@
//go:build windows
package cache_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/cache"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,3 +1,5 @@
//go:build windows
package cache
// Perflib "Cache":
@@ -33,37 +35,3 @@ const (
syncMDLReadsTotal = "Sync MDL Reads/sec"
syncPinReadsTotal = "Sync Pin Reads/sec"
)
// Perflib "Cache":
// - https://docs.microsoft.com/en-us/previous-versions/aa394267(v=vs.85)
type perflibCache struct {
AsyncCopyReadsTotal float64 `perflib:"Async Copy Reads/sec"`
AsyncDataMapsTotal float64 `perflib:"Async Data Maps/sec"`
AsyncFastReadsTotal float64 `perflib:"Async Fast Reads/sec"`
AsyncMDLReadsTotal float64 `perflib:"Async MDL Reads/sec"`
AsyncPinReadsTotal float64 `perflib:"Async Pin Reads/sec"`
CopyReadHitsTotal float64 `perflib:"Copy Read Hits %"`
CopyReadsTotal float64 `perflib:"Copy Reads/sec"`
DataFlushesTotal float64 `perflib:"Data Flushes/sec"`
DataFlushPagesTotal float64 `perflib:"Data Flush Pages/sec"`
DataMapHitsPercent float64 `perflib:"Data Map Hits %"`
DataMapPinsTotal float64 `perflib:"Data Map Pins/sec"`
DataMapsTotal float64 `perflib:"Data Maps/sec"`
DirtyPages float64 `perflib:"Dirty Pages"`
DirtyPageThreshold float64 `perflib:"Dirty Page Threshold"`
FastReadNotPossiblesTotal float64 `perflib:"Fast Read Not Possibles/sec"`
FastReadResourceMissesTotal float64 `perflib:"Fast Read Resource Misses/sec"`
FastReadsTotal float64 `perflib:"Fast Reads/sec"`
LazyWriteFlushesTotal float64 `perflib:"Lazy Write Flushes/sec"`
LazyWritePagesTotal float64 `perflib:"Lazy Write Pages/sec"`
MDLReadHitsTotal float64 `perflib:"MDL Read Hits %"`
MDLReadsTotal float64 `perflib:"MDL Reads/sec"`
PinReadHitsTotal float64 `perflib:"Pin Read Hits %"`
PinReadsTotal float64 `perflib:"Pin Reads/sec"`
ReadAheadsTotal float64 `perflib:"Read Aheads/sec"`
SyncCopyReadsTotal float64 `perflib:"Sync Copy Reads/sec"`
SyncDataMapsTotal float64 `perflib:"Sync Data Maps/sec"`
SyncFastReadsTotal float64 `perflib:"Sync Fast Reads/sec"`
SyncMDLReadsTotal float64 `perflib:"Sync MDL Reads/sec"`
SyncPinReadsTotal float64 `perflib:"Sync Pin Reads/sec"`
}

View File

@@ -11,7 +11,7 @@ import (
"github.com/Microsoft/hcsshim"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -26,6 +26,8 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config
logger *slog.Logger
// Presence
containerAvailable *prometheus.Desc
@@ -78,15 +80,13 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name))
c.containerAvailable = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "available"),
"Available",
@@ -201,28 +201,11 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
if err := c.collect(logger, ch); err != nil {
logger.Error("failed collecting collector metrics",
slog.Any("err", err),
)
return err
}
return nil
}
func (c *Collector) collect(logger *slog.Logger, ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
// Types Container is passed to get the containers compute systems only
containers, err := hcsshim.GetContainers(hcsshim.ComputeSystemQuery{Types: []string{"Container"}})
if err != nil {
logger.Error("Err in Getting containers",
slog.Any("err", err),
)
return err
return fmt.Errorf("error in fetching containers: %w", err)
}
count := len(containers)
@@ -243,14 +226,14 @@ func (c *Collector) collect(logger *slog.Logger, ch chan<- prometheus.Metric) er
for _, containerDetails := range containers {
containerIdWithPrefix := getContainerIdWithPrefix(containerDetails)
if err = c.collectContainer(logger, ch, containerDetails, containerIdWithPrefix); err != nil {
if err = c.collectContainer(ch, containerDetails, containerIdWithPrefix); err != nil {
if hcsshim.IsNotExist(err) {
logger.Debug("err in fetching container statistics",
c.logger.Debug("err in fetching container statistics",
slog.String("container_id", containerDetails.ID),
slog.Any("err", err),
)
} else {
logger.Error("err in fetching container statistics",
c.logger.Error("err in fetching container statistics",
slog.String("container_id", containerDetails.ID),
slog.Any("err", err),
)
@@ -264,7 +247,7 @@ func (c *Collector) collect(logger *slog.Logger, ch chan<- prometheus.Metric) er
containerPrefixes[containerDetails.ID] = containerIdWithPrefix
}
if err = c.collectNetworkMetrics(logger, ch, containerPrefixes); err != nil {
if err = c.collectNetworkMetrics(ch, containerPrefixes); err != nil {
return fmt.Errorf("error in fetching container network statistics: %w", err)
}
@@ -275,7 +258,7 @@ func (c *Collector) collect(logger *slog.Logger, ch chan<- prometheus.Metric) er
return nil
}
func (c *Collector) collectContainer(logger *slog.Logger, ch chan<- prometheus.Metric, containerDetails hcsshim.ContainerProperties, containerIdWithPrefix string) error {
func (c *Collector) collectContainer(ch chan<- prometheus.Metric, containerDetails hcsshim.ContainerProperties, containerIdWithPrefix string) error {
container, err := hcsshim.OpenContainer(containerDetails.ID)
if err != nil {
return fmt.Errorf("error in opening container: %w", err)
@@ -287,7 +270,7 @@ func (c *Collector) collectContainer(logger *slog.Logger, ch chan<- prometheus.M
}
if err := container.Close(); err != nil {
logger.Error("error in closing container",
c.logger.Error("error in closing container",
slog.Any("err", err),
)
}
@@ -325,19 +308,19 @@ func (c *Collector) collectContainer(logger *slog.Logger, ch chan<- prometheus.M
ch <- prometheus.MustNewConstMetric(
c.runtimeTotal,
prometheus.CounterValue,
float64(containerStats.Processor.TotalRuntime100ns)*perftypes.TicksToSecondScaleFactor,
float64(containerStats.Processor.TotalRuntime100ns)*perfdata.TicksToSecondScaleFactor,
containerIdWithPrefix,
)
ch <- prometheus.MustNewConstMetric(
c.runtimeUser,
prometheus.CounterValue,
float64(containerStats.Processor.RuntimeUser100ns)*perftypes.TicksToSecondScaleFactor,
float64(containerStats.Processor.RuntimeUser100ns)*perfdata.TicksToSecondScaleFactor,
containerIdWithPrefix,
)
ch <- prometheus.MustNewConstMetric(
c.runtimeKernel,
prometheus.CounterValue,
float64(containerStats.Processor.RuntimeKernel100ns)*perftypes.TicksToSecondScaleFactor,
float64(containerStats.Processor.RuntimeKernel100ns)*perfdata.TicksToSecondScaleFactor,
containerIdWithPrefix,
)
ch <- prometheus.MustNewConstMetric(
@@ -372,24 +355,20 @@ func (c *Collector) collectContainer(logger *slog.Logger, ch chan<- prometheus.M
// With HNSv2, the network stats must be collected from hcsshim.HNSListEndpointRequest.
// Network statistics from the container.Statistics() are providing data only, if HNSv1 is used.
// Ref: https://github.com/prometheus-community/windows_exporter/pull/1218
func (c *Collector) collectNetworkMetrics(logger *slog.Logger, ch chan<- prometheus.Metric, containerPrefixes map[string]string) error {
func (c *Collector) collectNetworkMetrics(ch chan<- prometheus.Metric, containerPrefixes map[string]string) error {
hnsEndpoints, err := hcsshim.HNSListEndpointRequest()
if err != nil {
logger.Warn("Failed to collect network stats for containers")
return err
return fmt.Errorf("error in fetching HNS endpoints: %w", err)
}
if len(hnsEndpoints) == 0 {
logger.Info("No network stats for containers to collect")
return nil
return errors.New("no network stats for containers to collect")
}
for _, endpoint := range hnsEndpoints {
endpointStats, err := hcsshim.GetHNSEndpointStats(endpoint.Id)
if err != nil {
logger.Warn("Failed to collect network stats for interface "+endpoint.Id,
c.logger.Warn("Failed to collect network stats for interface "+endpoint.Id,
slog.Any("err", err),
)
@@ -400,7 +379,7 @@ func (c *Collector) collectNetworkMetrics(logger *slog.Logger, ch chan<- prometh
containerIdWithPrefix, ok := containerPrefixes[containerId]
if !ok {
logger.Debug("Failed to collect network stats for container " + containerId)
c.logger.Debug("Failed to collect network stats for container " + containerId)
continue
}

View File

@@ -1,10 +1,12 @@
//go:build windows
package container_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/container"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,3 +1,5 @@
//go:build windows
package cpu
// Processor performance counters.
@@ -26,32 +28,3 @@ const (
processorUtilityRate = "% Processor Utility"
userTimeSeconds = "% User Time"
)
type perflibProcessorInformation struct {
Name string
C1TimeSeconds float64 `perflib:"% C1 Time"`
C2TimeSeconds float64 `perflib:"% C2 Time"`
C3TimeSeconds float64 `perflib:"% C3 Time"`
C1TransitionsTotal float64 `perflib:"C1 Transitions/sec"`
C2TransitionsTotal float64 `perflib:"C2 Transitions/sec"`
C3TransitionsTotal float64 `perflib:"C3 Transitions/sec"`
ClockInterruptsTotal float64 `perflib:"Clock Interrupts/sec"`
DPCsQueuedTotal float64 `perflib:"DPCs Queued/sec"`
DPCTimeSeconds float64 `perflib:"% DPC Time"`
IdleBreakEventsTotal float64 `perflib:"Idle Break Events/sec"`
IdleTimeSeconds float64 `perflib:"% Idle Time"`
InterruptsTotal float64 `perflib:"Interrupts/sec"`
InterruptTimeSeconds float64 `perflib:"% Interrupt Time"`
ParkingStatus float64 `perflib:"Parking Status"`
PerformanceLimitPercent float64 `perflib:"% Performance Limit"`
PriorityTimeSeconds float64 `perflib:"% Priority Time"`
PrivilegedTimeSeconds float64 `perflib:"% Privileged Time"`
PrivilegedUtilitySeconds float64 `perflib:"% Privileged Utility"`
ProcessorFrequencyMHz float64 `perflib:"Processor Frequency"`
ProcessorPerformance float64 `perflib:"% Processor Performance"`
ProcessorMPerf float64 `perflib:"% Processor Performance,secondvalue"`
ProcessorTimeSeconds float64 `perflib:"% Processor Time"`
ProcessorUtilityRate float64 `perflib:"% Processor Utility"`
ProcessorRTC float64 `perflib:"% Processor Utility,secondvalue"`
UserTimeSeconds float64 `perflib:"% User Time"`
}

View File

@@ -5,13 +5,11 @@ package cpu
import (
"fmt"
"log/slog"
"strings"
"sync"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/toggle"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils"
"github.com/prometheus/client_golang/prometheus"
@@ -26,7 +24,9 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config
perfDataCollector perfdata.Collector
perfDataCollector *perfdata.Collector
mu sync.Mutex
processorRTCValues map[string]utils.Counter
processorMPerfValues map[string]utils.Counter
@@ -67,52 +67,44 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
if toggle.IsPDHEnabled() {
return []string{}, nil
}
func (c *Collector) Close() error {
c.perfDataCollector.Close()
return []string{"Processor Information"}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
if toggle.IsPDHEnabled() {
counters := []string{
c1TimeSeconds,
c2TimeSeconds,
c3TimeSeconds,
c1TransitionsTotal,
c2TransitionsTotal,
c3TransitionsTotal,
clockInterruptsTotal,
dpcQueuedPerSecond,
dpcTimeSeconds,
idleBreakEventsTotal,
idleTimeSeconds,
interruptsTotal,
interruptTimeSeconds,
parkingStatus,
performanceLimitPercent,
priorityTimeSeconds,
privilegedTimeSeconds,
privilegedUtilitySeconds,
processorFrequencyMHz,
processorPerformance,
processorTimeSeconds,
processorUtilityRate,
userTimeSeconds,
}
var err error
var err error
c.mu = sync.Mutex{}
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V2, "Processor Information", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create Processor Information collector: %w", err)
}
c.perfDataCollector, err = perfdata.NewCollector("Processor Information", perfdata.InstanceAll, []string{
c1TimeSeconds,
c2TimeSeconds,
c3TimeSeconds,
c1TransitionsTotal,
c2TransitionsTotal,
c3TransitionsTotal,
clockInterruptsTotal,
dpcQueuedPerSecond,
dpcTimeSeconds,
idleBreakEventsTotal,
idleTimeSeconds,
interruptsTotal,
interruptTimeSeconds,
parkingStatus,
performanceLimitPercent,
priorityTimeSeconds,
privilegedTimeSeconds,
privilegedUtilitySeconds,
processorFrequencyMHz,
processorPerformance,
processorTimeSeconds,
processorUtilityRate,
userTimeSeconds,
})
if err != nil {
return fmt.Errorf("failed to create Processor Information collector: %w", err)
}
c.logicalProcessors = prometheus.NewDesc(
@@ -121,31 +113,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
nil,
nil,
)
c.cStateSecondsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cstate_seconds_total"),
"Time spent in low-power idle state",
[]string{"core", "state"},
nil,
)
c.timeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "time_total"),
"Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)",
[]string{"core", "mode"},
nil,
)
c.interruptsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "interrupts_total"),
"Total number of received and serviced hardware interrupts",
[]string{"core"},
nil,
)
c.dpcsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dpcs_total"),
"Total number of received and serviced deferred procedure calls (DPCs)",
[]string{"core"},
nil,
)
c.cStateSecondsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cstate_seconds_total"),
"Time spent in low-power idle state",
@@ -231,187 +198,10 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
return nil
}
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
if toggle.IsPDHEnabled() {
return c.collectPDH(ch)
}
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
c.mu.Lock() // Lock is needed to prevent concurrent map access to c.processorRTCValues
defer c.mu.Unlock()
logger = logger.With(slog.String("collector", Name))
return c.collectFull(ctx, logger, ch)
}
func (c *Collector) collectFull(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
data := make([]perflibProcessorInformation, 0)
err := v1.UnmarshalObject(ctx.PerfObjects["Processor Information"], &data, logger)
if err != nil {
return err
}
var coreCount float64
for _, cpu := range data {
if strings.Contains(strings.ToLower(cpu.Name), "_total") {
continue
}
core := cpu.Name
var (
counterProcessorRTCValues utils.Counter
counterProcessorMPerfValues utils.Counter
ok bool
)
if counterProcessorRTCValues, ok = c.processorRTCValues[core]; ok {
counterProcessorRTCValues.AddValue(uint32(cpu.ProcessorRTC))
} else {
counterProcessorRTCValues = utils.NewCounter(uint32(cpu.ProcessorRTC))
}
c.processorRTCValues[core] = counterProcessorRTCValues
if counterProcessorMPerfValues, ok = c.processorMPerfValues[core]; ok {
counterProcessorMPerfValues.AddValue(uint32(cpu.ProcessorMPerf))
} else {
counterProcessorMPerfValues = utils.NewCounter(uint32(cpu.ProcessorMPerf))
}
c.processorMPerfValues[core] = counterProcessorMPerfValues
coreCount++
ch <- prometheus.MustNewConstMetric(
c.cStateSecondsTotal,
prometheus.CounterValue,
cpu.C1TimeSeconds,
core, "c1",
)
ch <- prometheus.MustNewConstMetric(
c.cStateSecondsTotal,
prometheus.CounterValue,
cpu.C2TimeSeconds,
core, "c2",
)
ch <- prometheus.MustNewConstMetric(
c.cStateSecondsTotal,
prometheus.CounterValue,
cpu.C3TimeSeconds,
core, "c3",
)
ch <- prometheus.MustNewConstMetric(
c.timeTotal,
prometheus.CounterValue,
cpu.IdleTimeSeconds,
core, "idle",
)
ch <- prometheus.MustNewConstMetric(
c.timeTotal,
prometheus.CounterValue,
cpu.InterruptTimeSeconds,
core, "interrupt",
)
ch <- prometheus.MustNewConstMetric(
c.timeTotal,
prometheus.CounterValue,
cpu.DPCTimeSeconds,
core, "dpc",
)
ch <- prometheus.MustNewConstMetric(
c.timeTotal,
prometheus.CounterValue,
cpu.PrivilegedTimeSeconds,
core, "privileged",
)
ch <- prometheus.MustNewConstMetric(
c.timeTotal,
prometheus.CounterValue,
cpu.UserTimeSeconds,
core, "user",
)
ch <- prometheus.MustNewConstMetric(
c.interruptsTotal,
prometheus.CounterValue,
cpu.InterruptsTotal,
core,
)
ch <- prometheus.MustNewConstMetric(
c.dpcsTotal,
prometheus.CounterValue,
cpu.DPCsQueuedTotal,
core,
)
ch <- prometheus.MustNewConstMetric(
c.clockInterruptsTotal,
prometheus.CounterValue,
cpu.ClockInterruptsTotal,
core,
)
ch <- prometheus.MustNewConstMetric(
c.idleBreakEventsTotal,
prometheus.CounterValue,
cpu.IdleBreakEventsTotal,
core,
)
ch <- prometheus.MustNewConstMetric(
c.parkingStatus,
prometheus.GaugeValue,
cpu.ParkingStatus,
core,
)
ch <- prometheus.MustNewConstMetric(
c.processorFrequencyMHz,
prometheus.GaugeValue,
cpu.ProcessorFrequencyMHz,
core,
)
ch <- prometheus.MustNewConstMetric(
c.processorPerformance,
prometheus.CounterValue,
cpu.ProcessorPerformance,
core,
)
ch <- prometheus.MustNewConstMetric(
c.processorMPerf,
prometheus.CounterValue,
counterProcessorMPerfValues.Value(),
core,
)
ch <- prometheus.MustNewConstMetric(
c.processorRTC,
prometheus.CounterValue,
counterProcessorRTCValues.Value(),
core,
)
ch <- prometheus.MustNewConstMetric(
c.processorUtility,
prometheus.CounterValue,
cpu.ProcessorUtilityRate,
core,
)
ch <- prometheus.MustNewConstMetric(
c.processorPrivilegedUtility,
prometheus.CounterValue,
cpu.PrivilegedUtilitySeconds,
core,
)
}
ch <- prometheus.MustNewConstMetric(
c.logicalProcessors,
prometheus.GaugeValue,
coreCount,
)
return nil
}
func (c *Collector) collectPDH(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect Processor Information metrics: %w", err)

View File

@@ -6,7 +6,7 @@ import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/cpu"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -56,11 +56,7 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
@@ -159,20 +155,7 @@ type miProcessor struct {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
if err := c.collect(ch); err != nil {
logger.Error("failed collecting cpu_info metrics",
slog.Any("err", err),
)
return err
}
return nil
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
var dst []miProcessor
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)

View File

@@ -1,10 +1,12 @@
//go:build windows
package cpu_info_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/cpu_info"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -23,10 +23,10 @@ type Collector struct {
config Config
// physicalMemoryBytes
// Deprecated: Use windows_cpu_logical_processor instead
// Deprecated: Use windows_physical_memory_total_bytes instead
physicalMemoryBytes *prometheus.Desc
// logicalProcessors
// Deprecated: Use windows_physical_memory_total_bytes instead
// Deprecated: Use windows_cpu_logical_processor instead
logicalProcessors *prometheus.Desc
// hostname
// Deprecated: Use windows_os_hostname instead
@@ -53,11 +53,7 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
@@ -95,21 +91,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
if err := c.collect(ch); err != nil {
logger.Error("failed collecting cs metrics",
slog.Any("err", err),
)
return err
}
return nil
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
// Get systeminfo for number of processors
systemInfo := sysinfoapi.GetSystemInfo()

View File

@@ -1,10 +1,12 @@
//go:build windows
package cs_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/cs"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,3 +1,5 @@
//go:build windows
package dfsr
const (
@@ -40,62 +42,3 @@ const (
usnJournalRecordsAcceptedTotal = "USN Journal Records Accepted"
usnJournalUnreadPercentage = "USN Journal Records Unread Percentage"
)
// PerflibDFSRConnection Perflib: "DFS Replication Service Connections".
type PerflibDFSRConnection struct {
Name string
BandwidthSavingsUsingDFSReplicationTotal float64 `perflib:"Bandwidth Savings Using DFS Replication"`
BytesReceivedTotal float64 `perflib:"Total Bytes Received"`
CompressedSizeOfFilesReceivedTotal float64 `perflib:"Compressed Size of Files Received"`
FilesReceivedTotal float64 `perflib:"Total Files Received"`
RDCBytesReceivedTotal float64 `perflib:"RDC Bytes Received"`
RDCCompressedSizeOfFilesReceivedTotal float64 `perflib:"RDC Compressed Size of Files Received"`
RDCNumberOfFilesReceivedTotal float64 `perflib:"RDC Number of Files Received"`
RDCSizeOfFilesReceivedTotal float64 `perflib:"RDC Size of Files Received"`
SizeOfFilesReceivedTotal float64 `perflib:"Size of Files Received"`
}
// perflibDFSRFolder Perflib: "DFS Replicated Folder".
type perflibDFSRFolder struct {
Name string
BandwidthSavingsUsingDFSReplicationTotal float64 `perflib:"Bandwidth Savings Using DFS Replication"`
CompressedSizeOfFilesReceivedTotal float64 `perflib:"Compressed Size of Files Received"`
ConflictBytesCleanedUpTotal float64 `perflib:"Conflict Bytes Cleaned Up"`
ConflictBytesGeneratedTotal float64 `perflib:"Conflict Bytes Generated"`
ConflictFilesCleanedUpTotal float64 `perflib:"Conflict Files Cleaned Up"`
ConflictFilesGeneratedTotal float64 `perflib:"Conflict Files Generated"`
ConflictFolderCleanupsCompletedTotal float64 `perflib:"Conflict folder Cleanups Completed"`
ConflictSpaceInUse float64 `perflib:"Conflict Space In Use"`
DeletedSpaceInUse float64 `perflib:"Deleted Space In Use"`
DeletedBytesCleanedUpTotal float64 `perflib:"Deleted Bytes Cleaned Up"`
DeletedBytesGeneratedTotal float64 `perflib:"Deleted Bytes Generated"`
DeletedFilesCleanedUpTotal float64 `perflib:"Deleted Files Cleaned Up"`
DeletedFilesGeneratedTotal float64 `perflib:"Deleted Files Generated"`
FileInstallsRetriedTotal float64 `perflib:"File Installs Retried"`
FileInstallsSucceededTotal float64 `perflib:"File Installs Succeeded"`
FilesReceivedTotal float64 `perflib:"Total Files Received"`
RDCBytesReceivedTotal float64 `perflib:"RDC Bytes Received"`
RDCCompressedSizeOfFilesReceivedTotal float64 `perflib:"RDC Compressed Size of Files Received"`
RDCNumberOfFilesReceivedTotal float64 `perflib:"RDC Number of Files Received"`
RDCSizeOfFilesReceivedTotal float64 `perflib:"RDC Size of Files Received"`
SizeOfFilesReceivedTotal float64 `perflib:"Size of Files Received"`
StagingSpaceInUse float64 `perflib:"Staging Space In Use"`
StagingBytesCleanedUpTotal float64 `perflib:"Staging Bytes Cleaned Up"`
StagingBytesGeneratedTotal float64 `perflib:"Staging Bytes Generated"`
StagingFilesCleanedUpTotal float64 `perflib:"Staging Files Cleaned Up"`
StagingFilesGeneratedTotal float64 `perflib:"Staging Files Generated"`
UpdatesDroppedTotal float64 `perflib:"Updates Dropped"`
}
// perflibDFSRVolume Perflib: "DFS Replication Service Volumes".
type perflibDFSRVolume struct {
Name string
DatabaseCommitsTotal float64 `perflib:"Database Commits"`
DatabaseLookupsTotal float64 `perflib:"Database Lookups"`
USNJournalRecordsReadTotal float64 `perflib:"USN Journal Records Read"`
USNJournalRecordsAcceptedTotal float64 `perflib:"USN Journal Records Accepted"`
USNJournalUnreadPercentage float64 `perflib:"USN Journal Records Unread Percentage"`
}

View File

@@ -12,8 +12,6 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/toggle"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -32,9 +30,9 @@ var ConfigDefaults = Config{
type Collector struct {
config Config
perfDataCollectorConnection perfdata.Collector
perfDataCollectorFolder perfdata.Collector
perfDataCollectorVolume perfdata.Collector
perfDataCollectorConnection *perfdata.Collector
perfDataCollectorFolder *perfdata.Collector
perfDataCollectorVolume *perfdata.Collector
// connection source
connectionBandwidthSavingsUsingDFSReplicationTotal *prometheus.Desc
@@ -82,29 +80,6 @@ type Collector struct {
volumeUSNJournalUnreadPercentage *prometheus.Desc
volumeUSNJournalRecordsAcceptedTotal *prometheus.Desc
volumeUSNJournalRecordsReadTotal *prometheus.Desc
// Map of child Collector functions used during collection
dfsrChildCollectors []dfsrCollectorFunc
}
type dfsrCollectorFunc func(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error
// Map Perflib sources to DFSR Collector names
// e.g, volume -> DFS Replication Service Volumes.
func dfsrGetPerfObjectName(collector string) string {
prefix := "DFS "
suffix := ""
switch collector {
case "connection":
suffix = "Replication Connections"
case "folder":
suffix = "Replicated Folders"
case "volume":
suffix = "Replication Service Volumes"
}
return prefix + suffix
}
func New(config *Config) *Collector {
@@ -147,23 +122,19 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
if toggle.IsPDHEnabled() {
return []string{}, nil
func (c *Collector) Close() error {
if slices.Contains(c.config.CollectorsEnabled, "connection") {
c.perfDataCollectorConnection.Close()
}
// Perflib sources are dynamic, depending on the enabled child collectors
expandedChildCollectors := slices.Compact(c.config.CollectorsEnabled)
perflibDependencies := make([]string, 0, len(expandedChildCollectors))
for _, source := range expandedChildCollectors {
perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source))
if slices.Contains(c.config.CollectorsEnabled, "folder") {
c.perfDataCollectorFolder.Close()
}
return perflibDependencies, nil
}
if slices.Contains(c.config.CollectorsEnabled, "volume") {
c.perfDataCollectorVolume.Close()
}
func (c *Collector) Close(_ *slog.Logger) error {
return nil
}
@@ -172,82 +143,72 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
logger.Info("dfsr collector is in an experimental state! Metrics for this collector have not been tested.")
//nolint:nestif
if toggle.IsPDHEnabled() {
var err error
var err error
if slices.Contains(c.config.CollectorsEnabled, "connection") {
counters := []string{
bandwidthSavingsUsingDFSReplicationTotal,
bytesReceivedTotal,
compressedSizeOfFilesReceivedTotal,
filesReceivedTotal,
rdcBytesReceivedTotal,
rdcCompressedSizeOfFilesReceivedTotal,
rdcNumberOfFilesReceivedTotal,
rdcSizeOfFilesReceivedTotal,
sizeOfFilesReceivedTotal,
}
c.perfDataCollectorConnection, err = perfdata.NewCollector(perfdata.V1, "DFS Replication Connections", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create DFS Replication Connections collector: %w", err)
}
}
if slices.Contains(c.config.CollectorsEnabled, "folder") {
counters := []string{
bandwidthSavingsUsingDFSReplicationTotal,
compressedSizeOfFilesReceivedTotal,
conflictBytesCleanedUpTotal,
conflictBytesGeneratedTotal,
conflictFilesCleanedUpTotal,
conflictFilesGeneratedTotal,
conflictFolderCleanupsCompletedTotal,
conflictSpaceInUse,
deletedSpaceInUse,
deletedBytesCleanedUpTotal,
deletedBytesGeneratedTotal,
deletedFilesCleanedUpTotal,
deletedFilesGeneratedTotal,
fileInstallsRetriedTotal,
fileInstallsSucceededTotal,
filesReceivedTotal,
rdcBytesReceivedTotal,
rdcCompressedSizeOfFilesReceivedTotal,
rdcNumberOfFilesReceivedTotal,
rdcSizeOfFilesReceivedTotal,
sizeOfFilesReceivedTotal,
stagingSpaceInUse,
stagingBytesCleanedUpTotal,
stagingBytesGeneratedTotal,
stagingFilesCleanedUpTotal,
stagingFilesGeneratedTotal,
updatesDroppedTotal,
}
c.perfDataCollectorFolder, err = perfdata.NewCollector(perfdata.V1, "DFS Replicated Folders", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create DFS Replicated Folders collector: %w", err)
}
}
if slices.Contains(c.config.CollectorsEnabled, "volume") {
counters := []string{
databaseCommitsTotal,
databaseLookupsTotal,
usnJournalRecordsReadTotal,
usnJournalRecordsAcceptedTotal,
usnJournalUnreadPercentage,
}
c.perfDataCollectorVolume, err = perfdata.NewCollector(perfdata.V1, "DFS Replication Service Volumes", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create DFS Replication Service Volumes collector: %w", err)
}
if slices.Contains(c.config.CollectorsEnabled, "connection") {
c.perfDataCollectorConnection, err = perfdata.NewCollector("DFS Replication Connections", perfdata.InstanceAll, []string{
bandwidthSavingsUsingDFSReplicationTotal,
bytesReceivedTotal,
compressedSizeOfFilesReceivedTotal,
filesReceivedTotal,
rdcBytesReceivedTotal,
rdcCompressedSizeOfFilesReceivedTotal,
rdcNumberOfFilesReceivedTotal,
rdcSizeOfFilesReceivedTotal,
sizeOfFilesReceivedTotal,
})
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 = perfdata.NewCollector("DFS Replicated Folders", perfdata.InstanceAll, []string{
bandwidthSavingsUsingDFSReplicationTotal,
compressedSizeOfFilesReceivedTotal,
conflictBytesCleanedUpTotal,
conflictBytesGeneratedTotal,
conflictFilesCleanedUpTotal,
conflictFilesGeneratedTotal,
conflictFolderCleanupsCompletedTotal,
conflictSpaceInUse,
deletedSpaceInUse,
deletedBytesCleanedUpTotal,
deletedBytesGeneratedTotal,
deletedFilesCleanedUpTotal,
deletedFilesGeneratedTotal,
fileInstallsRetriedTotal,
fileInstallsSucceededTotal,
filesReceivedTotal,
rdcBytesReceivedTotal,
rdcCompressedSizeOfFilesReceivedTotal,
rdcNumberOfFilesReceivedTotal,
rdcSizeOfFilesReceivedTotal,
sizeOfFilesReceivedTotal,
stagingSpaceInUse,
stagingBytesCleanedUpTotal,
stagingBytesGeneratedTotal,
stagingFilesCleanedUpTotal,
stagingFilesGeneratedTotal,
updatesDroppedTotal,
})
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 = perfdata.NewCollector("DFS Replication Service Volumes", perfdata.InstanceAll, []string{
databaseCommitsTotal,
databaseLookupsTotal,
usnJournalRecordsReadTotal,
usnJournalRecordsAcceptedTotal,
usnJournalUnreadPercentage,
})
if err != nil {
return fmt.Errorf("failed to create DFS Replication Service Volumes collector: %w", err)
}
}
// connection
c.connectionBandwidthSavingsUsingDFSReplicationTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "connection_bandwidth_savings_using_dfs_replication_bytes_total"),
@@ -538,374 +499,12 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
nil,
)
// Perflib sources are dynamic, depending on the enabled child collectors
expandedChildCollectors := slices.Compact(c.config.CollectorsEnabled)
c.dfsrChildCollectors = c.getDFSRChildCollectors(expandedChildCollectors)
return nil
}
// Maps enabled child collectors names to their relevant collection function,
// for use in Collector.Collect().
func (c *Collector) getDFSRChildCollectors(enabledCollectors []string) []dfsrCollectorFunc {
var dfsrCollectors []dfsrCollectorFunc
for _, collector := range enabledCollectors {
switch collector {
case "connection":
dfsrCollectors = append(dfsrCollectors, c.collectConnection)
case "folder":
dfsrCollectors = append(dfsrCollectors, c.collectFolder)
case "volume":
dfsrCollectors = append(dfsrCollectors, c.collectVolume)
}
}
return dfsrCollectors
}
// Collect implements the Collector interface.
// Sends metric values for each metric to the provided prometheus Metric channel.
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
if toggle.IsPDHEnabled() {
return c.collectPDH(ch)
}
logger = logger.With(slog.String("collector", Name))
for _, fn := range c.dfsrChildCollectors {
err := fn(ctx, logger, ch)
if err != nil {
return err
}
}
return nil
}
func (c *Collector) collectConnection(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var dst []PerflibDFSRConnection
if err := v1.UnmarshalObject(ctx.PerfObjects["DFS Replication Connections"], &dst, logger); err != nil {
return err
}
for _, connection := range dst {
ch <- prometheus.MustNewConstMetric(
c.connectionBandwidthSavingsUsingDFSReplicationTotal,
prometheus.CounterValue,
connection.BandwidthSavingsUsingDFSReplicationTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.connectionBytesReceivedTotal,
prometheus.CounterValue,
connection.BytesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.connectionCompressedSizeOfFilesReceivedTotal,
prometheus.CounterValue,
connection.CompressedSizeOfFilesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.connectionFilesReceivedTotal,
prometheus.CounterValue,
connection.FilesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.connectionRDCBytesReceivedTotal,
prometheus.CounterValue,
connection.RDCBytesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.connectionRDCCompressedSizeOfFilesReceivedTotal,
prometheus.CounterValue,
connection.RDCCompressedSizeOfFilesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.connectionRDCSizeOfFilesReceivedTotal,
prometheus.CounterValue,
connection.RDCSizeOfFilesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.connectionRDCNumberOfFilesReceivedTotal,
prometheus.CounterValue,
connection.RDCNumberOfFilesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.connectionSizeOfFilesReceivedTotal,
prometheus.CounterValue,
connection.SizeOfFilesReceivedTotal,
connection.Name,
)
}
return nil
}
func (c *Collector) collectFolder(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var dst []perflibDFSRFolder
if err := v1.UnmarshalObject(ctx.PerfObjects["DFS Replicated Folders"], &dst, logger); err != nil {
return err
}
for _, folder := range dst {
ch <- prometheus.MustNewConstMetric(
c.folderBandwidthSavingsUsingDFSReplicationTotal,
prometheus.CounterValue,
folder.BandwidthSavingsUsingDFSReplicationTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderCompressedSizeOfFilesReceivedTotal,
prometheus.CounterValue,
folder.CompressedSizeOfFilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderConflictBytesCleanedUpTotal,
prometheus.CounterValue,
folder.ConflictBytesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderConflictBytesGeneratedTotal,
prometheus.CounterValue,
folder.ConflictBytesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderConflictFilesCleanedUpTotal,
prometheus.CounterValue,
folder.ConflictFilesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderConflictFilesGeneratedTotal,
prometheus.CounterValue,
folder.ConflictFilesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderConflictFolderCleanupsCompletedTotal,
prometheus.CounterValue,
folder.ConflictFolderCleanupsCompletedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderConflictSpaceInUse,
prometheus.GaugeValue,
folder.ConflictSpaceInUse,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderDeletedSpaceInUse,
prometheus.GaugeValue,
folder.DeletedSpaceInUse,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderDeletedBytesCleanedUpTotal,
prometheus.CounterValue,
folder.DeletedBytesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderDeletedBytesGeneratedTotal,
prometheus.CounterValue,
folder.DeletedBytesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderDeletedFilesCleanedUpTotal,
prometheus.CounterValue,
folder.DeletedFilesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderDeletedFilesGeneratedTotal,
prometheus.CounterValue,
folder.DeletedFilesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderFileInstallsRetriedTotal,
prometheus.CounterValue,
folder.FileInstallsRetriedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderFileInstallsSucceededTotal,
prometheus.CounterValue,
folder.FileInstallsSucceededTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderFilesReceivedTotal,
prometheus.CounterValue,
folder.FilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderRDCBytesReceivedTotal,
prometheus.CounterValue,
folder.RDCBytesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderRDCCompressedSizeOfFilesReceivedTotal,
prometheus.CounterValue,
folder.RDCCompressedSizeOfFilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderRDCNumberOfFilesReceivedTotal,
prometheus.CounterValue,
folder.RDCNumberOfFilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderRDCSizeOfFilesReceivedTotal,
prometheus.CounterValue,
folder.RDCSizeOfFilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderSizeOfFilesReceivedTotal,
prometheus.CounterValue,
folder.SizeOfFilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderStagingSpaceInUse,
prometheus.GaugeValue,
folder.StagingSpaceInUse,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderStagingBytesCleanedUpTotal,
prometheus.CounterValue,
folder.StagingBytesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderStagingBytesGeneratedTotal,
prometheus.CounterValue,
folder.StagingBytesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderStagingFilesCleanedUpTotal,
prometheus.CounterValue,
folder.StagingFilesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderStagingFilesGeneratedTotal,
prometheus.CounterValue,
folder.StagingFilesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.folderUpdatesDroppedTotal,
prometheus.CounterValue,
folder.UpdatesDroppedTotal,
folder.Name,
)
}
return nil
}
func (c *Collector) collectVolume(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var dst []perflibDFSRVolume
if err := v1.UnmarshalObject(ctx.PerfObjects["DFS Replication Service Volumes"], &dst, logger); err != nil {
return err
}
for _, volume := range dst {
ch <- prometheus.MustNewConstMetric(
c.volumeDatabaseLookupsTotal,
prometheus.CounterValue,
volume.DatabaseLookupsTotal,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.volumeDatabaseCommitsTotal,
prometheus.CounterValue,
volume.DatabaseCommitsTotal,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.volumeUSNJournalRecordsAcceptedTotal,
prometheus.CounterValue,
volume.USNJournalRecordsAcceptedTotal,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.volumeUSNJournalRecordsReadTotal,
prometheus.CounterValue,
volume.USNJournalRecordsReadTotal,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.volumeUSNJournalUnreadPercentage,
prometheus.GaugeValue,
volume.USNJournalUnreadPercentage,
volume.Name,
)
}
return nil
}
func (c *Collector) collectPDH(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
errs := make([]error, 0, 3)
if slices.Contains(c.config.CollectorsEnabled, "connection") {

View File

@@ -1,10 +1,12 @@
//go:build windows
package dfsr_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/dfsr"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,3 +1,5 @@
//go:build windows
package dhcp
const (
@@ -27,34 +29,3 @@ const (
releasesTotal = "Releases/sec"
requestsTotal = "Requests/sec"
)
// represents perflib metrics from the DHCP Server class.
// While the name of a number of perflib metrics would indicate a rate is being returned (E.G. Packets Received/sec),
// perflib instead returns a counter, hence the "Total" suffix in some of the variable names.
type dhcpPerf struct {
AcksTotal float64 `perflib:"Acks/sec"`
ActiveQueueLength float64 `perflib:"Active Queue Length"`
ConflictCheckQueueLength float64 `perflib:"Conflict Check Queue Length"`
DeclinesTotal float64 `perflib:"Declines/sec"`
DeniedDueToMatch float64 `perflib:"Denied due to match."`
DeniedDueToNonMatch float64 `perflib:"Denied due to match."`
DiscoversTotal float64 `perflib:"Discovers/sec"`
DuplicatesDroppedTotal float64 `perflib:"Duplicates Dropped/sec"`
FailoverBndAckReceivedTotal float64 `perflib:"Failover: BndAck received/sec."`
FailoverBndAckSentTotal float64 `perflib:"Failover: BndAck sent/sec."`
FailoverBndUpdDropped float64 `perflib:"Failover: BndUpd Dropped."`
FailoverBndUpdPendingOutboundQueue float64 `perflib:"Failover: BndUpd pending in outbound queue."`
FailoverBndUpdReceivedTotal float64 `perflib:"Failover: BndUpd received/sec."`
FailoverBndUpdSentTotal float64 `perflib:"Failover: BndUpd sent/sec."`
FailoverTransitionsCommunicationInterruptedState float64 `perflib:"Failover: Transitions to COMMUNICATION-INTERRUPTED state."`
FailoverTransitionsPartnerDownState float64 `perflib:"Failover: Transitions to PARTNER-DOWN state."`
FailoverTransitionsRecoverState float64 `perflib:"Failover: Transitions to RECOVER state."`
InformsTotal float64 `perflib:"Informs/sec"`
NacksTotal float64 `perflib:"Nacks/sec"`
OfferQueueLength float64 `perflib:"Offer Queue Length"`
OffersTotal float64 `perflib:"Offers/sec"`
PacketsExpiredTotal float64 `perflib:"Packets Expired/sec"`
PacketsReceivedTotal float64 `perflib:"Packets Received/sec"`
ReleasesTotal float64 `perflib:"Releases/sec"`
RequestsTotal float64 `perflib:"Requests/sec"`
}

View File

@@ -10,9 +10,6 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/toggle"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -27,7 +24,7 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config
perfDataCollector perfdata.Collector
perfDataCollector *perfdata.Collector
acksTotal *prometheus.Desc
activeQueueLength *prometheus.Desc
@@ -76,54 +73,44 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
if toggle.IsPDHEnabled() {
return []string{}, nil
}
func (c *Collector) Close() error {
c.perfDataCollector.Close()
return []string{"DHCP Server"}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
if toggle.IsPDHEnabled() {
counters := []string{
acksTotal,
activeQueueLength,
conflictCheckQueueLength,
declinesTotal,
deniedDueToMatch,
deniedDueToNonMatch,
discoversTotal,
duplicatesDroppedTotal,
failoverBndAckReceivedTotal,
failoverBndAckSentTotal,
failoverBndUpdDropped,
failoverBndUpdPendingOutboundQueue,
failoverBndUpdReceivedTotal,
failoverBndUpdSentTotal,
failoverTransitionsCommunicationInterruptedState,
failoverTransitionsPartnerDownState,
failoverTransitionsRecoverState,
informsTotal,
nacksTotal,
offerQueueLength,
offersTotal,
packetsExpiredTotal,
packetsReceivedTotal,
releasesTotal,
requestsTotal,
}
var err error
var err error
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V1, "DHCP Server", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create DHCP Server collector: %w", err)
}
c.perfDataCollector, err = perfdata.NewCollector("DHCP Server", perfdata.InstanceAll, []string{
acksTotal,
activeQueueLength,
conflictCheckQueueLength,
declinesTotal,
deniedDueToMatch,
deniedDueToNonMatch,
discoversTotal,
duplicatesDroppedTotal,
failoverBndAckReceivedTotal,
failoverBndAckSentTotal,
failoverBndUpdDropped,
failoverBndUpdPendingOutboundQueue,
failoverBndUpdReceivedTotal,
failoverBndUpdSentTotal,
failoverTransitionsCommunicationInterruptedState,
failoverTransitionsPartnerDownState,
failoverTransitionsRecoverState,
informsTotal,
nacksTotal,
offerQueueLength,
offersTotal,
packetsExpiredTotal,
packetsReceivedTotal,
releasesTotal,
requestsTotal,
})
if err != nil {
return fmt.Errorf("failed to create DHCP Server collector: %w", err)
}
c.packetsReceivedTotal = prometheus.NewDesc(
@@ -280,183 +267,13 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
return nil
}
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
if toggle.IsPDHEnabled() {
return c.collectPDH(ch)
}
logger = logger.With(slog.String("collector", Name))
return c.collect(ctx, logger, ch)
}
func (c *Collector) collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var dhcpPerfs []dhcpPerf
if err := v1.UnmarshalObject(ctx.PerfObjects["DHCP Server"], &dhcpPerfs, logger); err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(
c.packetsReceivedTotal,
prometheus.CounterValue,
dhcpPerfs[0].PacketsReceivedTotal,
)
ch <- prometheus.MustNewConstMetric(
c.duplicatesDroppedTotal,
prometheus.CounterValue,
dhcpPerfs[0].DuplicatesDroppedTotal,
)
ch <- prometheus.MustNewConstMetric(
c.packetsExpiredTotal,
prometheus.CounterValue,
dhcpPerfs[0].PacketsExpiredTotal,
)
ch <- prometheus.MustNewConstMetric(
c.activeQueueLength,
prometheus.GaugeValue,
dhcpPerfs[0].ActiveQueueLength,
)
ch <- prometheus.MustNewConstMetric(
c.conflictCheckQueueLength,
prometheus.GaugeValue,
dhcpPerfs[0].ConflictCheckQueueLength,
)
ch <- prometheus.MustNewConstMetric(
c.discoversTotal,
prometheus.CounterValue,
dhcpPerfs[0].DiscoversTotal,
)
ch <- prometheus.MustNewConstMetric(
c.offersTotal,
prometheus.CounterValue,
dhcpPerfs[0].OffersTotal,
)
ch <- prometheus.MustNewConstMetric(
c.requestsTotal,
prometheus.CounterValue,
dhcpPerfs[0].RequestsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.informsTotal,
prometheus.CounterValue,
dhcpPerfs[0].InformsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.acksTotal,
prometheus.CounterValue,
dhcpPerfs[0].AcksTotal,
)
ch <- prometheus.MustNewConstMetric(
c.nACKsTotal,
prometheus.CounterValue,
dhcpPerfs[0].NacksTotal,
)
ch <- prometheus.MustNewConstMetric(
c.declinesTotal,
prometheus.CounterValue,
dhcpPerfs[0].DeclinesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.releasesTotal,
prometheus.CounterValue,
dhcpPerfs[0].ReleasesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.offerQueueLength,
prometheus.GaugeValue,
dhcpPerfs[0].OfferQueueLength,
)
ch <- prometheus.MustNewConstMetric(
c.deniedDueToMatch,
prometheus.CounterValue,
dhcpPerfs[0].DeniedDueToMatch,
)
ch <- prometheus.MustNewConstMetric(
c.deniedDueToNonMatch,
prometheus.CounterValue,
dhcpPerfs[0].DeniedDueToNonMatch,
)
ch <- prometheus.MustNewConstMetric(
c.failoverBndUpdSentTotal,
prometheus.CounterValue,
dhcpPerfs[0].FailoverBndUpdSentTotal,
)
ch <- prometheus.MustNewConstMetric(
c.failoverBndUpdReceivedTotal,
prometheus.CounterValue,
dhcpPerfs[0].FailoverBndUpdReceivedTotal,
)
ch <- prometheus.MustNewConstMetric(
c.failoverBndAckSentTotal,
prometheus.CounterValue,
dhcpPerfs[0].FailoverBndAckSentTotal,
)
ch <- prometheus.MustNewConstMetric(
c.failoverBndAckReceivedTotal,
prometheus.CounterValue,
dhcpPerfs[0].FailoverBndAckReceivedTotal,
)
ch <- prometheus.MustNewConstMetric(
c.failoverBndUpdPendingOutboundQueue,
prometheus.GaugeValue,
dhcpPerfs[0].FailoverBndUpdPendingOutboundQueue,
)
ch <- prometheus.MustNewConstMetric(
c.failoverTransitionsCommunicationInterruptedState,
prometheus.CounterValue,
dhcpPerfs[0].FailoverTransitionsCommunicationInterruptedState,
)
ch <- prometheus.MustNewConstMetric(
c.failoverTransitionsPartnerDownState,
prometheus.CounterValue,
dhcpPerfs[0].FailoverTransitionsPartnerDownState,
)
ch <- prometheus.MustNewConstMetric(
c.failoverTransitionsRecoverState,
prometheus.CounterValue,
dhcpPerfs[0].FailoverTransitionsRecoverState,
)
ch <- prometheus.MustNewConstMetric(
c.failoverBndUpdDropped,
prometheus.CounterValue,
dhcpPerfs[0].FailoverBndUpdDropped,
)
return nil
}
func (c *Collector) collectPDH(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect DHCP Server metrics: %w", err)
}
data, ok := perfData[perftypes.EmptyInstance]
data, ok := perfData[perfdata.EmptyInstance]
if !ok {
return errors.New("perflib query for DHCP Server returned empty result set")
}

View File

@@ -1,10 +1,12 @@
//go:build windows
package dhcp_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/dhcp"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -53,11 +53,7 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
@@ -113,7 +109,7 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
return nil
}
type win32_DiskDrive struct {
type diskDrive struct {
DeviceID string `mi:"DeviceID"`
Model string `mi:"Model"`
Size uint64 `mi:"Size"`
@@ -166,21 +162,8 @@ var (
)
// Collect sends the metric values for each metric to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
if err := c.collect(ch); err != nil {
logger.Error("failed collecting disk_drive_info metrics",
slog.Any("err", err),
)
return err
}
return nil
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []win32_DiskDrive
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
var dst []diskDrive
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
@@ -190,14 +173,16 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
}
for _, disk := range dst {
distName := strings.Trim(disk.Name, `\.`)
ch <- prometheus.MustNewConstMetric(
c.diskInfo,
prometheus.GaugeValue,
1.0,
strings.Trim(disk.DeviceID, "\\.\\"), //nolint:staticcheck
strings.Trim(disk.DeviceID, `\.`),
strings.TrimRight(disk.Model, " "),
strings.TrimRight(disk.Caption, " "),
strings.TrimRight(disk.Name, "\\.\\"), //nolint:staticcheck
distName,
)
for _, status := range allDiskStatus {
@@ -210,7 +195,7 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
c.status,
prometheus.GaugeValue,
isCurrentState,
strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
distName,
status,
)
}
@@ -219,14 +204,14 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
c.size,
prometheus.GaugeValue,
float64(disk.Size),
strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
distName,
)
ch <- prometheus.MustNewConstMetric(
c.partitions,
prometheus.GaugeValue,
float64(disk.Partitions),
strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
distName,
)
for availNum, val := range availMap {
@@ -238,7 +223,7 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
c.availability,
prometheus.GaugeValue,
isCurrentState,
strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
distName,
val,
)
}

View File

@@ -1,10 +1,12 @@
//go:build windows
package diskdrive_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/diskdrive"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,3 +1,5 @@
//go:build windows
package dns
const (

View File

@@ -10,7 +10,6 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -25,7 +24,7 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config
perfDataCollector perfdata.Collector
perfDataCollector *perfdata.Collector
dynamicUpdatesFailures *prometheus.Desc
dynamicUpdatesQueued *prometheus.Desc
@@ -71,16 +70,16 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close() error {
c.perfDataCollector.Close()
func (c *Collector) Close(_ *slog.Logger) error {
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
counters := []string{
var err error
c.perfDataCollector, err = perfdata.NewCollector("DNS", perfdata.InstanceAll, []string{
axfrRequestReceived,
axfrRequestSent,
axfrResponseReceived,
@@ -121,11 +120,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
winsReverseResponseSent,
zoneTransferFailure,
zoneTransferSOARequestSent,
}
var err error
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V1, "DNS", perfdata.AllInstances, counters)
})
if err != nil {
return fmt.Errorf("failed to create DNS collector: %w", err)
}
@@ -268,13 +263,13 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect DNS metrics: %w", err)
}
data, ok := perfData[perftypes.EmptyInstance]
data, ok := perfData[perfdata.EmptyInstance]
if !ok {
return errors.New("perflib query for DNS returned empty result set")
}

View File

@@ -1,10 +1,12 @@
//go:build windows
package dns_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/dns"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -12,8 +12,6 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/toggle"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -54,16 +52,16 @@ var ConfigDefaults = Config{
type Collector struct {
config Config
perfDataCollectorADAccessProcesses perfdata.Collector
perfDataCollectorTransportQueues perfdata.Collector
perfDataCollectorHttpProxy perfdata.Collector
perfDataCollectorActiveSync perfdata.Collector
perfDataCollectorAvailabilityService perfdata.Collector
perfDataCollectorOWA perfdata.Collector
perfDataCollectorAutoDiscover perfdata.Collector
perfDataCollectorWorkloadManagementWorkloads perfdata.Collector
perfDataCollectorRpcClientAccess perfdata.Collector
perfDataCollectorMapiHttpEmsmdb perfdata.Collector
perfDataCollectorADAccessProcesses *perfdata.Collector
perfDataCollectorTransportQueues *perfdata.Collector
perfDataCollectorHttpProxy *perfdata.Collector
perfDataCollectorActiveSync *perfdata.Collector
perfDataCollectorAvailabilityService *perfdata.Collector
perfDataCollectorOWA *perfdata.Collector
perfDataCollectorAutoDiscover *perfdata.Collector
perfDataCollectorWorkloadManagementWorkloads *perfdata.Collector
perfDataCollectorRpcClientAccess *perfdata.Collector
perfDataCollectorMapiHttpEmsmdb *perfdata.Collector
activeMailboxDeliveryQueueLength *prometheus.Desc
activeSyncRequestsPerSec *prometheus.Desc
@@ -103,6 +101,17 @@ type Collector struct {
unreachableQueueLength *prometheus.Desc
userCount *prometheus.Desc
yieldedTasks *prometheus.Desc
messagesQueuedForDeliveryTotal *prometheus.Desc
messagesSubmittedTotal *prometheus.Desc
messagesDelayedTotal *prometheus.Desc
messagesCompletedDeliveryTotal *prometheus.Desc
shadowQueueLength *prometheus.Desc
submissionQueueLength *prometheus.Desc
delayQueueLength *prometheus.Desc
itemsCompletedDeliveryTotal *prometheus.Desc
itemsQueuedForDeliveryExpiredTotal *prometheus.Desc
itemsQueuedForDeliveryTotal *prometheus.Desc
itemsResubmittedTotal *prometheus.Desc
}
func New(config *Config) *Collector {
@@ -184,111 +193,36 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
if toggle.IsPDHEnabled() {
return []string{}, nil
}
return []string{
"MSExchange ADAccess Processes",
"MSExchangeTransport Queues",
"MSExchange HttpProxy",
"MSExchange ActiveSync",
"MSExchange Availability Service",
"MSExchange OWA",
"MSExchangeAutodiscover",
"MSExchange WorkloadManagement Workloads",
"MSExchange RpcClientAccess",
"MSExchange MapiHttp Emsmdb",
}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
if toggle.IsPDHEnabled() {
collectorFuncs := map[string]func() error{
adAccessProcesses: c.buildADAccessProcesses,
transportQueues: c.buildTransportQueues,
httpProxy: c.buildHTTPProxy,
activeSync: c.buildActiveSync,
availabilityService: c.buildAvailabilityService,
outlookWebAccess: c.buildOWA,
autoDiscover: c.buildAutoDiscover,
workloadManagement: c.buildWorkloadManagementWorkloads,
rpcClientAccess: c.buildRPC,
mapiHttpEmsmdb: c.buildMapiHttpEmsmdb,
}
for _, collectorName := range c.config.CollectorsEnabled {
if err := collectorFuncs[collectorName](); err != nil {
return err
}
}
collectorFuncs := map[string]func() error{
adAccessProcesses: c.buildADAccessProcesses,
transportQueues: c.buildTransportQueues,
httpProxy: c.buildHTTPProxy,
activeSync: c.buildActiveSync,
availabilityService: c.buildAvailabilityService,
outlookWebAccess: c.buildOWA,
autoDiscover: c.buildAutoDiscover,
workloadManagement: c.buildWorkloadManagementWorkloads,
rpcClientAccess: c.buildRPC,
mapiHttpEmsmdb: c.buildMapiHttpEmsmdb,
}
// desc creates a new prometheus description
desc := func(metricName string, description string, labels ...string) *prometheus.Desc {
return prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, metricName),
description,
labels,
nil,
)
for _, collectorName := range c.config.CollectorsEnabled {
if err := collectorFuncs[collectorName](); err != nil {
return err
}
}
c.rpcAveragedLatency = desc("rpc_avg_latency_sec", "The latency (sec) averaged for the past 1024 packets")
c.rpcRequests = desc("rpc_requests", "Number of client requests currently being processed by the RPC Client Access service")
c.activeUserCount = desc("rpc_active_user_count", "Number of unique users that have shown some kind of activity in the last 2 minutes")
c.connectionCount = desc("rpc_connection_count", "Total number of client connections maintained")
c.rpcOperationsPerSec = desc("rpc_operations_total", "The rate at which RPC operations occur")
c.userCount = desc("rpc_user_count", "Number of users")
c.ldapReadTime = desc("ldap_read_time_sec", "Time (sec) to send an LDAP read request and receive a response", "name")
c.ldapSearchTime = desc("ldap_search_time_sec", "Time (sec) to send an LDAP search request and receive a response", "name")
c.ldapWriteTime = desc("ldap_write_time_sec", "Time (sec) to send an LDAP Add/Modify/Delete request and receive a response", "name")
c.ldapTimeoutErrorsPerSec = desc("ldap_timeout_errors_total", "Total number of LDAP timeout errors", "name")
c.longRunningLDAPOperationsPerMin = desc("ldap_long_running_ops_per_sec", "Long Running LDAP operations per second", "name")
c.externalActiveRemoteDeliveryQueueLength = desc("transport_queues_external_active_remote_delivery", "External Active Remote Delivery Queue length", "name")
c.internalActiveRemoteDeliveryQueueLength = desc("transport_queues_internal_active_remote_delivery", "Internal Active Remote Delivery Queue length", "name")
c.activeMailboxDeliveryQueueLength = desc("transport_queues_active_mailbox_delivery", "Active Mailbox Delivery Queue length", "name")
c.retryMailboxDeliveryQueueLength = desc("transport_queues_retry_mailbox_delivery", "Retry Mailbox Delivery Queue length", "name")
c.unreachableQueueLength = desc("transport_queues_unreachable", "Unreachable Queue length", "name")
c.externalLargestDeliveryQueueLength = desc("transport_queues_external_largest_delivery", "External Largest Delivery Queue length", "name")
c.internalLargestDeliveryQueueLength = desc("transport_queues_internal_largest_delivery", "Internal Largest Delivery Queue length", "name")
c.poisonQueueLength = desc("transport_queues_poison", "Poison Queue length", "name")
c.mailboxServerLocatorAverageLatency = desc("http_proxy_mailbox_server_locator_avg_latency_sec", "Average latency (sec) of MailboxServerLocator web service calls", "name")
c.averageAuthenticationLatency = desc("http_proxy_avg_auth_latency", "Average time spent authenticating CAS requests over the last 200 samples", "name")
c.outstandingProxyRequests = desc("http_proxy_outstanding_proxy_requests", "Number of concurrent outstanding proxy requests", "name")
c.proxyRequestsPerSec = desc("http_proxy_requests_total", "Number of proxy requests processed each second", "name")
c.availabilityRequestsSec = desc("avail_service_requests_per_sec", "Number of requests serviced per second")
c.currentUniqueUsers = desc("owa_current_unique_users", "Number of unique users currently logged on to Outlook Web App")
c.owaRequestsPerSec = desc("owa_requests_total", "Number of requests handled by Outlook Web App per second")
c.autoDiscoverRequestsPerSec = desc("autodiscover_requests_total", "Number of autodiscover service requests processed each second")
c.activeTasks = desc("workload_active_tasks", "Number of active tasks currently running in the background for workload management", "name")
c.completedTasks = desc("workload_completed_tasks", "Number of workload management tasks that have been completed", "name")
c.queuedTasks = desc("workload_queued_tasks", "Number of workload management tasks that are currently queued up waiting to be processed", "name")
c.yieldedTasks = desc("workload_yielded_tasks", "The total number of tasks that have been yielded by a workload", "name")
c.isActive = desc("workload_is_active", "Active indicates whether the workload is in an active (1) or paused (0) state", "name")
c.activeSyncRequestsPerSec = desc("activesync_requests_total", "Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load")
c.averageCASProcessingLatency = desc("http_proxy_avg_cas_processing_latency_sec", "Average latency (sec) of CAS processing time over the last 200 reqs", "name")
c.mailboxServerProxyFailureRate = desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name")
c.pingCommandsPending = desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue")
c.syncCommandsPerSec = desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder")
c.activeUserCountMapiHttpEmsMDB = desc("mapihttp_emsmdb_active_user_count", "Number of unique outlook users that have shown some kind of activity in the last 2 minutes")
return nil
}
// Collect collects exchange metrics and sends them to prometheus.
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
if toggle.IsPDHEnabled() {
return c.collectPDH(ch)
}
logger = logger.With(slog.String("collector", Name))
collectorFuncs := map[string]func(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error{
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
collectorFuncs := map[string]func(ch chan<- prometheus.Metric) error{
adAccessProcesses: c.collectADAccessProcesses,
transportQueues: c.collectTransportQueues,
httpProxy: c.collectHTTPProxy,
@@ -301,34 +235,6 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch ch
mapiHttpEmsmdb: c.collectMapiHttpEmsmdb,
}
for _, collectorName := range c.config.CollectorsEnabled {
if err := collectorFuncs[collectorName](ctx, logger, ch); err != nil {
logger.Error("Error in "+collectorName,
slog.Any("err", err),
)
return err
}
}
return nil
}
// Collect collects exchange metrics and sends them to prometheus.
func (c *Collector) collectPDH(ch chan<- prometheus.Metric) error {
collectorFuncs := map[string]func(ch chan<- prometheus.Metric) error{
adAccessProcesses: c.collectPDHADAccessProcesses,
transportQueues: c.collectPDHTransportQueues,
httpProxy: c.collectPDHHTTPProxy,
activeSync: c.collectPDHActiveSync,
availabilityService: c.collectPDHAvailabilityService,
outlookWebAccess: c.collectPDHOWA,
autoDiscover: c.collectPDHAutoDiscover,
workloadManagement: c.collectPDHWorkloadManagementWorkloads,
rpcClientAccess: c.collectPDHRPC,
mapiHttpEmsmdb: c.collectPDHMapiHttpEmsmdb,
}
errs := make([]error, len(c.config.CollectorsEnabled))
for i, collectorName := range c.config.CollectorsEnabled {

View File

@@ -1,12 +1,12 @@
//go:build windows
package exchange
import (
"errors"
"fmt"
"log/slog"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -17,13 +17,6 @@ const (
syncCommandsPerSec = "Sync Commands/sec"
)
// Perflib: [25138] MSExchange ActiveSync.
type perflibActiveSync struct {
RequestsPerSec float64 `perflib:"Requests/sec"`
PingCommandsPending float64 `perflib:"Ping Commands Pending"`
SyncCommandsPerSec float64 `perflib:"Sync Commands/sec"`
}
func (c *Collector) buildActiveSync() error {
counters := []string{
requestsPerSec,
@@ -33,43 +26,34 @@ func (c *Collector) buildActiveSync() error {
var err error
c.perfDataCollectorActiveSync, err = perfdata.NewCollector(perfdata.V1, "MSExchange ActiveSync", perfdata.AllInstances, counters)
c.perfDataCollectorActiveSync, err = perfdata.NewCollector("MSExchange ActiveSync", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create MSExchange ActiveSync collector: %w", err)
}
return nil
}
func (c *Collector) collectActiveSync(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var data []perflibActiveSync
if err := v1.UnmarshalObject(ctx.PerfObjects["MSExchange ActiveSync"], &data, logger); err != nil {
return err
}
for _, instance := range data {
ch <- prometheus.MustNewConstMetric(
c.activeSyncRequestsPerSec,
prometheus.CounterValue,
instance.RequestsPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.pingCommandsPending,
prometheus.GaugeValue,
instance.PingCommandsPending,
)
ch <- prometheus.MustNewConstMetric(
c.syncCommandsPerSec,
prometheus.CounterValue,
instance.SyncCommandsPerSec,
)
}
c.pingCommandsPending = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "activesync_ping_cmds_pending"),
"Number of ping commands currently pending in the queue",
nil,
nil,
)
c.syncCommandsPerSec = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "activesync_sync_cmds_total"),
"Number of sync commands processed per second. Clients use this command to synchronize items within a folder",
nil,
nil,
)
c.activeSyncRequestsPerSec = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "activesync_requests_total"),
"Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load",
nil,
nil,
)
return nil
}
func (c *Collector) collectPDHActiveSync(ch chan<- prometheus.Metric) error {
func (c *Collector) collectActiveSync(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorActiveSync.Collect()
if err != nil {
return fmt.Errorf("failed to collect MSExchange ActiveSync metrics: %w", err)

View File

@@ -1,13 +1,12 @@
//go:build windows
package exchange
import (
"errors"
"fmt"
"log/slog"
"strings"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -20,17 +19,6 @@ const (
longRunningLDAPOperationsPerMin = "Long Running LDAP Operations/min"
)
// Perflib: [19108] MSExchange ADAccess Processes.
type perflibADAccessProcesses struct {
Name string
LDAPReadTime float64 `perflib:"LDAP Read Time"`
LDAPSearchTime float64 `perflib:"LDAP Search Time"`
LDAPWriteTime float64 `perflib:"LDAP Write Time"`
LDAPTimeoutErrorsPerSec float64 `perflib:"LDAP Timeout Errors/sec"`
LongRunningLDAPOperationsPerMin float64 `perflib:"Long Running LDAP Operations/min"`
}
func (c *Collector) buildADAccessProcesses() error {
counters := []string{
ldapReadTime,
@@ -42,71 +30,46 @@ func (c *Collector) buildADAccessProcesses() error {
var err error
c.perfDataCollectorADAccessProcesses, err = perfdata.NewCollector(perfdata.V1, "MSExchange ADAccess Processes", perfdata.AllInstances, counters)
c.perfDataCollectorADAccessProcesses, err = perfdata.NewCollector("MSExchange ADAccess Processes", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create MSExchange ADAccess Processes collector: %w", err)
}
return nil
}
func (c *Collector) collectADAccessProcesses(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var data []perflibADAccessProcesses
if err := v1.UnmarshalObject(ctx.PerfObjects["MSExchange ADAccess Processes"], &data, logger); err != nil {
return err
}
labelUseCount := make(map[string]int)
for _, proc := range data {
labelName := c.toLabelName(proc.Name)
if strings.HasSuffix(labelName, "_total") {
continue
}
// Since we're not including the PID suffix from the instance names in the label names, we get an occasional duplicate.
// This seems to affect about 4 instances only of this object.
labelUseCount[labelName]++
if labelUseCount[labelName] > 1 {
labelName = fmt.Sprintf("%s_%d", labelName, labelUseCount[labelName])
}
ch <- prometheus.MustNewConstMetric(
c.ldapReadTime,
prometheus.CounterValue,
c.msToSec(proc.LDAPReadTime),
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.ldapSearchTime,
prometheus.CounterValue,
c.msToSec(proc.LDAPSearchTime),
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.ldapWriteTime,
prometheus.CounterValue,
c.msToSec(proc.LDAPWriteTime),
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.ldapTimeoutErrorsPerSec,
prometheus.CounterValue,
proc.LDAPTimeoutErrorsPerSec,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.longRunningLDAPOperationsPerMin,
prometheus.CounterValue,
proc.LongRunningLDAPOperationsPerMin*60,
labelName,
)
}
c.ldapReadTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "ldap_read_time_sec"),
"Time (sec) to send an LDAP read request and receive a response",
[]string{"name"},
nil,
)
c.ldapSearchTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "ldap_search_time_sec"),
"Time (sec) to send an LDAP search request and receive a response",
[]string{"name"},
nil,
)
c.ldapWriteTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "ldap_write_time_sec"),
"Time (sec) to send an LDAP Add/Modify/Delete request and receive a response",
[]string{"name"},
nil,
)
c.ldapTimeoutErrorsPerSec = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "ldap_timeout_errors_total"),
"Total number of LDAP timeout errors",
[]string{"name"},
nil,
)
c.longRunningLDAPOperationsPerMin = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "ldap_long_running_ops_per_sec"),
"Long Running LDAP operations per second",
[]string{"name"},
nil,
)
return nil
}
func (c *Collector) collectPDHADAccessProcesses(ch chan<- prometheus.Metric) error {
func (c *Collector) collectADAccessProcesses(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorADAccessProcesses.Collect()
if err != nil {
return fmt.Errorf("failed to collect MSExchange ADAccess Processes metrics: %w", err)

View File

@@ -1,21 +1,16 @@
//go:build windows
package exchange
import (
"errors"
"fmt"
"log/slog"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// [29240] MSExchangeAutodiscover.
type perflibAutodiscover struct {
RequestsPerSec float64 `perflib:"Requests/sec"`
}
func (c *Collector) buildAutoDiscover() error {
counters := []string{
requestsPerSec,
@@ -23,33 +18,22 @@ func (c *Collector) buildAutoDiscover() error {
var err error
c.perfDataCollectorAutoDiscover, err = perfdata.NewCollector(perfdata.V1, "MSExchange Autodiscover", perfdata.AllInstances, counters)
c.perfDataCollectorAutoDiscover, err = perfdata.NewCollector("MSExchange Autodiscover", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create MSExchange Autodiscover collector: %w", err)
}
return nil
}
func (c *Collector) collectAutoDiscover(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var data []perflibAutodiscover
if err := v1.UnmarshalObject(ctx.PerfObjects["MSExchangeAutodiscover"], &data, logger); err != nil {
return err
}
for _, autodisc := range data {
ch <- prometheus.MustNewConstMetric(
c.autoDiscoverRequestsPerSec,
prometheus.CounterValue,
autodisc.RequestsPerSec,
)
}
c.autoDiscoverRequestsPerSec = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "autodiscover_requests_total"),
"Number of autodiscover service requests processed each second",
nil,
nil,
)
return nil
}
func (c *Collector) collectPDHAutoDiscover(ch chan<- prometheus.Metric) error {
func (c *Collector) collectAutoDiscover(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorAutoDiscover.Collect()
if err != nil {
return fmt.Errorf("failed to collect MSExchange Autodiscover metrics: %w", err)

View File

@@ -1,53 +1,39 @@
//go:build windows
package exchange
import (
"errors"
"fmt"
"log/slog"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// Perflib: [24914] MSExchange Availability Service.
type perflibAvailabilityService struct {
RequestsSec float64 `perflib:"Availability Requests (sec)"`
}
func (c *Collector) buildAvailabilityService() error {
counters := []string{}
counters := []string{
requestsPerSec,
}
var err error
c.perfDataCollectorAvailabilityService, err = perfdata.NewCollector(perfdata.V1, "MSExchange Availability Service", perfdata.AllInstances, counters)
c.perfDataCollectorAvailabilityService, err = perfdata.NewCollector("MSExchange Availability Service", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create MSExchange Availability Service collector: %w", err)
}
return nil
}
func (c *Collector) collectAvailabilityService(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var data []perflibAvailabilityService
if err := v1.UnmarshalObject(ctx.PerfObjects["MSExchange Availability Service"], &data, logger); err != nil {
return err
}
for _, availservice := range data {
ch <- prometheus.MustNewConstMetric(
c.availabilityRequestsSec,
prometheus.CounterValue,
availservice.RequestsSec,
)
}
c.availabilityRequestsSec = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "avail_service_requests_per_sec"),
"Number of requests serviced per second",
nil,
nil,
)
return nil
}
func (c *Collector) collectPDHAvailabilityService(ch chan<- prometheus.Metric) error {
func (c *Collector) collectAvailabilityService(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorAvailabilityService.Collect()
if err != nil {
return fmt.Errorf("failed to collect MSExchange Availability Service metrics: %w", err)

View File

@@ -1,12 +1,12 @@
//go:build windows
package exchange
import (
"errors"
"fmt"
"log/slog"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -20,18 +20,6 @@ const (
proxyRequestsPerSec = "Proxy Requests/Sec"
)
// Perflib: [36934] MSExchange HttpProxy.
type perflibHTTPProxy struct {
Name string
MailboxServerLocatorAverageLatency float64 `perflib:"MailboxServerLocator Average Latency (Moving Average)"`
AverageAuthenticationLatency float64 `perflib:"Average Authentication Latency"`
AverageCASProcessingLatency float64 `perflib:"Average ClientAccess Server Processing Latency"`
MailboxServerProxyFailureRate float64 `perflib:"Mailbox Server Proxy Failure Rate"`
OutstandingProxyRequests float64 `perflib:"Outstanding Proxy Requests"`
ProxyRequestsPerSec float64 `perflib:"Proxy Requests/Sec"`
}
func (c *Collector) buildHTTPProxy() error {
counters := []string{
mailboxServerLocatorAverageLatency,
@@ -44,65 +32,52 @@ func (c *Collector) buildHTTPProxy() error {
var err error
c.perfDataCollectorHttpProxy, err = perfdata.NewCollector(perfdata.V1, "MSExchange HttpProxy", perfdata.AllInstances, counters)
c.perfDataCollectorHttpProxy, err = perfdata.NewCollector("MSExchange HttpProxy", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create MSExchange HttpProxy collector: %w", err)
}
return nil
}
func (c *Collector) collectHTTPProxy(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var data []perflibHTTPProxy
if err := v1.UnmarshalObject(ctx.PerfObjects["MSExchange HttpProxy"], &data, logger); err != nil {
return err
}
for _, instance := range data {
labelName := c.toLabelName(instance.Name)
ch <- prometheus.MustNewConstMetric(
c.mailboxServerLocatorAverageLatency,
prometheus.GaugeValue,
c.msToSec(instance.MailboxServerLocatorAverageLatency),
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.averageAuthenticationLatency,
prometheus.GaugeValue,
instance.AverageAuthenticationLatency,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.averageCASProcessingLatency,
prometheus.GaugeValue,
c.msToSec(instance.AverageCASProcessingLatency),
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.mailboxServerProxyFailureRate,
prometheus.GaugeValue,
instance.MailboxServerProxyFailureRate,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.outstandingProxyRequests,
prometheus.GaugeValue,
instance.OutstandingProxyRequests,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.proxyRequestsPerSec,
prometheus.CounterValue,
instance.ProxyRequestsPerSec,
labelName,
)
}
c.mailboxServerLocatorAverageLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "http_proxy_mailbox_server_locator_avg_latency_sec"),
"Average latency (sec) of MailboxServerLocator web service calls",
[]string{"name"},
nil,
)
c.averageAuthenticationLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "http_proxy_avg_auth_latency"),
"Average time spent authenticating CAS requests over the last 200 samples",
[]string{"name"},
nil,
)
c.outstandingProxyRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "http_proxy_outstanding_proxy_requests"),
"Number of concurrent outstanding proxy requests",
[]string{"name"},
nil,
)
c.proxyRequestsPerSec = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "http_proxy_requests_total"),
"Number of proxy requests processed each second",
[]string{"name"},
nil,
)
c.averageCASProcessingLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "http_proxy_avg_cas_processing_latency_sec"),
"Average latency (sec) of CAS processing time over the last 200 reqs",
[]string{"name"},
nil,
)
c.mailboxServerProxyFailureRate = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "http_proxy_mailbox_proxy_failure_rate"),
"% of failures between this CAS and MBX servers over the last 200 samples",
[]string{"name"},
nil,
)
return nil
}
func (c *Collector) collectPDHHTTPProxy(ch chan<- prometheus.Metric) error {
func (c *Collector) collectHTTPProxy(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorHttpProxy.Collect()
if err != nil {
return fmt.Errorf("failed to collect MSExchange HttpProxy Service metrics: %w", err)

View File

@@ -1,12 +1,12 @@
//go:build windows
package exchange
import (
"errors"
"fmt"
"log/slog"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -15,11 +15,6 @@ const (
activeUserCount = "Active User Count"
)
// perflib [26463] MSExchange MapiHttp Emsmdb.
type perflibMapiHttpEmsmdb struct {
ActiveUserCount float64 `perflib:"Active User Count"`
}
func (c *Collector) buildMapiHttpEmsmdb() error {
counters := []string{
activeUserCount,
@@ -27,33 +22,22 @@ func (c *Collector) buildMapiHttpEmsmdb() error {
var err error
c.perfDataCollectorMapiHttpEmsmdb, err = perfdata.NewCollector(perfdata.V1, "MSExchange MapiHttp Emsmdb", perfdata.AllInstances, counters)
c.perfDataCollectorMapiHttpEmsmdb, err = perfdata.NewCollector("MSExchange MapiHttp Emsmdb", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create MSExchange MapiHttp Emsmdb: %w", err)
}
return nil
}
func (c *Collector) collectMapiHttpEmsmdb(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var data []perflibMapiHttpEmsmdb
if err := v1.UnmarshalObject(ctx.PerfObjects["MSExchange MapiHttp Emsmdb"], &data, logger); err != nil {
return err
}
for _, mapihttp := range data {
ch <- prometheus.MustNewConstMetric(
c.activeUserCountMapiHttpEmsMDB,
prometheus.GaugeValue,
mapihttp.ActiveUserCount,
)
}
c.activeUserCountMapiHttpEmsMDB = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "mapihttp_emsmdb_active_user_count"),
"Number of unique outlook users that have shown some kind of activity in the last 2 minutes",
nil,
nil,
)
return nil
}
func (c *Collector) collectPDHMapiHttpEmsmdb(ch chan<- prometheus.Metric) error {
func (c *Collector) collectMapiHttpEmsmdb(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorMapiHttpEmsmdb.Collect()
if err != nil {
return fmt.Errorf("failed to collect MSExchange MapiHttp Emsmdb metrics: %w", err)

View File

@@ -1,12 +1,12 @@
//go:build windows
package exchange
import (
"errors"
"fmt"
"log/slog"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -16,12 +16,6 @@ const (
// requestsPerSec = "Requests/sec"
)
// Perflib: [24618] MSExchange OWA.
type perflibOWA struct {
CurrentUniqueUsers float64 `perflib:"Current Unique Users"`
RequestsPerSec float64 `perflib:"Requests/sec"`
}
func (c *Collector) buildOWA() error {
counters := []string{
currentUniqueUsers,
@@ -30,38 +24,28 @@ func (c *Collector) buildOWA() error {
var err error
c.perfDataCollectorOWA, err = perfdata.NewCollector(perfdata.V1, "MSExchange OWA", perfdata.AllInstances, counters)
c.perfDataCollectorOWA, err = perfdata.NewCollector("MSExchange OWA", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create MSExchange OWA collector: %w", err)
}
return nil
}
func (c *Collector) collectOWA(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var data []perflibOWA
if err := v1.UnmarshalObject(ctx.PerfObjects["MSExchange OWA"], &data, logger); err != nil {
return err
}
for _, owa := range data {
ch <- prometheus.MustNewConstMetric(
c.currentUniqueUsers,
prometheus.GaugeValue,
owa.CurrentUniqueUsers,
)
ch <- prometheus.MustNewConstMetric(
c.owaRequestsPerSec,
prometheus.CounterValue,
owa.RequestsPerSec,
)
}
c.currentUniqueUsers = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "owa_current_unique_users"),
"Number of unique users currently logged on to Outlook Web App",
nil,
nil,
)
c.owaRequestsPerSec = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "owa_requests_total"),
"Number of requests handled by Outlook Web App per second",
nil,
nil,
)
return nil
}
func (c *Collector) collectPDHOWA(ch chan<- prometheus.Metric) error {
func (c *Collector) collectOWA(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorOWA.Collect()
if err != nil {
return fmt.Errorf("failed to collect MSExchange OWA metrics: %w", err)

View File

@@ -1,12 +1,12 @@
//go:build windows
package exchange
import (
"errors"
"fmt"
"log/slog"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -20,16 +20,6 @@ const (
userCount = "User Count"
)
// Perflib: [29366] MSExchange RpcClientAccess.
type perflibRPCClientAccess struct {
RPCAveragedLatency float64 `perflib:"RPC Averaged Latency"`
RPCRequests float64 `perflib:"RPC Requests"`
ActiveUserCount float64 `perflib:"Active User Count"`
ConnectionCount float64 `perflib:"Connection Count"`
RPCOperationsPerSec float64 `perflib:"RPC Operations/sec"`
UserCount float64 `perflib:"User Count"`
}
func (c *Collector) buildRPC() error {
counters := []string{
rpcAveragedLatency,
@@ -42,58 +32,52 @@ func (c *Collector) buildRPC() error {
var err error
c.perfDataCollectorRpcClientAccess, err = perfdata.NewCollector(perfdata.V1, "MSExchange RpcClientAccess", perfdata.AllInstances, counters)
c.perfDataCollectorRpcClientAccess, err = perfdata.NewCollector("MSExchange RpcClientAccess", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create MSExchange RpcClientAccess collector: %w", err)
}
return nil
}
func (c *Collector) collectRPC(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var data []perflibRPCClientAccess
if err := v1.UnmarshalObject(ctx.PerfObjects["MSExchange RpcClientAccess"], &data, logger); err != nil {
return err
}
for _, rpc := range data {
ch <- prometheus.MustNewConstMetric(
c.rpcAveragedLatency,
prometheus.GaugeValue,
c.msToSec(rpc.RPCAveragedLatency),
)
ch <- prometheus.MustNewConstMetric(
c.rpcRequests,
prometheus.GaugeValue,
rpc.RPCRequests,
)
ch <- prometheus.MustNewConstMetric(
c.activeUserCount,
prometheus.GaugeValue,
rpc.ActiveUserCount,
)
ch <- prometheus.MustNewConstMetric(
c.connectionCount,
prometheus.GaugeValue,
rpc.ConnectionCount,
)
ch <- prometheus.MustNewConstMetric(
c.rpcOperationsPerSec,
prometheus.CounterValue,
rpc.RPCOperationsPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.userCount,
prometheus.GaugeValue,
rpc.UserCount,
)
}
c.rpcAveragedLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "rpc_avg_latency_sec"),
"The latency (sec) averaged for the past 1024 packets",
nil,
nil,
)
c.rpcRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "rpc_requests"),
"Number of client requests currently being processed by the RPC Client Access service",
nil,
nil,
)
c.activeUserCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "rpc_active_user_count"),
"Number of unique users that have shown some kind of activity in the last 2 minutes",
nil,
nil,
)
c.connectionCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "rpc_connection_count"),
"Total number of client connections maintained",
nil,
nil,
)
c.rpcOperationsPerSec = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "rpc_operations_total"),
"The rate at which RPC operations occur",
nil,
nil,
)
c.userCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "rpc_user_count"),
"Number of users",
nil,
nil,
)
return nil
}
func (c *Collector) collectPDHRPC(ch chan<- prometheus.Metric) error {
func (c *Collector) collectRPC(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorRpcClientAccess.Collect()
if err != nil {
return fmt.Errorf("failed to collect MSExchange RpcClientAccess: %w", err)

View File

@@ -1,10 +1,12 @@
//go:build windows
package exchange_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/exchange"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,13 +1,12 @@
//go:build windows
package exchange
import (
"errors"
"fmt"
"log/slog"
"strings"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -21,22 +20,19 @@ const (
externalLargestDeliveryQueueLength = "External Largest Delivery Queue Length"
internalLargestDeliveryQueueLength = "Internal Largest Delivery Queue Length"
poisonQueueLength = "Poison Queue Length"
messagesQueuedForDeliveryTotal = "Messages Queued For Delivery Total"
messagesSubmittedTotal = "Messages Submitted Total"
messagesDelayedTotal = "Messages Delayed Total"
messagesCompletedDeliveryTotal = "Messages Completed Delivery Total"
shadowQueueLength = "Shadow Queue Length"
submissionQueueLength = "Submission Queue Length"
delayQueueLength = "Delay Queue Length"
itemsCompletedDeliveryTotal = "Items Completed Delivery Total"
itemsQueuedForDeliveryExpiredTotal = "Items Queued For Delivery Expired Total"
itemsQueuedForDeliveryTotal = "Items Queued For Delivery Total"
itemsResubmittedTotal = "Items Resubmitted Total"
)
// Perflib: [20524] MSExchangeTransport Queues.
type perflibTransportQueues struct {
Name string
ExternalActiveRemoteDeliveryQueueLength float64 `perflib:"External Active Remote Delivery Queue Length"`
InternalActiveRemoteDeliveryQueueLength float64 `perflib:"Internal Active Remote Delivery Queue Length"`
ActiveMailboxDeliveryQueueLength float64 `perflib:"Active Mailbox Delivery Queue Length"`
RetryMailboxDeliveryQueueLength float64 `perflib:"Retry Mailbox Delivery Queue Length"`
UnreachableQueueLength float64 `perflib:"Unreachable Queue Length"`
ExternalLargestDeliveryQueueLength float64 `perflib:"External Largest Delivery Queue Length"`
InternalLargestDeliveryQueueLength float64 `perflib:"Internal Largest Delivery Queue Length"`
PoisonQueueLength float64 `perflib:"Poison Queue Length"`
}
func (c *Collector) buildTransportQueues() error {
counters := []string{
externalActiveRemoteDeliveryQueueLength,
@@ -47,84 +43,145 @@ func (c *Collector) buildTransportQueues() error {
externalLargestDeliveryQueueLength,
internalLargestDeliveryQueueLength,
poisonQueueLength,
messagesQueuedForDeliveryTotal,
messagesSubmittedTotal,
messagesDelayedTotal,
messagesCompletedDeliveryTotal,
shadowQueueLength,
submissionQueueLength,
delayQueueLength,
itemsCompletedDeliveryTotal,
itemsQueuedForDeliveryExpiredTotal,
itemsQueuedForDeliveryTotal,
itemsResubmittedTotal,
}
var err error
c.perfDataCollectorTransportQueues, err = perfdata.NewCollector(perfdata.V1, "MSExchangeTransport Queues", perfdata.AllInstances, counters)
c.perfDataCollectorTransportQueues, err = perfdata.NewCollector("MSExchangeTransport Queues", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create MSExchangeTransport Queues collector: %w", err)
}
return nil
}
func (c *Collector) collectTransportQueues(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var data []perflibTransportQueues
if err := v1.UnmarshalObject(ctx.PerfObjects["MSExchangeTransport Queues"], &data, logger); err != nil {
return err
}
for _, queue := range data {
labelName := c.toLabelName(queue.Name)
if strings.HasSuffix(labelName, "_total") {
continue
}
ch <- prometheus.MustNewConstMetric(
c.externalActiveRemoteDeliveryQueueLength,
prometheus.GaugeValue,
queue.ExternalActiveRemoteDeliveryQueueLength,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.internalActiveRemoteDeliveryQueueLength,
prometheus.GaugeValue,
queue.InternalActiveRemoteDeliveryQueueLength,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.activeMailboxDeliveryQueueLength,
prometheus.GaugeValue,
queue.ActiveMailboxDeliveryQueueLength,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.retryMailboxDeliveryQueueLength,
prometheus.GaugeValue,
queue.RetryMailboxDeliveryQueueLength,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.unreachableQueueLength,
prometheus.GaugeValue,
queue.UnreachableQueueLength,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.externalLargestDeliveryQueueLength,
prometheus.GaugeValue,
queue.ExternalLargestDeliveryQueueLength,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.internalLargestDeliveryQueueLength,
prometheus.GaugeValue,
queue.InternalLargestDeliveryQueueLength,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.poisonQueueLength,
prometheus.GaugeValue,
queue.PoisonQueueLength,
labelName,
)
}
c.externalActiveRemoteDeliveryQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_external_active_remote_delivery"),
"External Active Remote Delivery Queue length",
[]string{"name"},
nil,
)
c.internalActiveRemoteDeliveryQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_internal_active_remote_delivery"),
"Internal Active Remote Delivery Queue length",
[]string{"name"},
nil,
)
c.activeMailboxDeliveryQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_active_mailbox_delivery"),
"Active Mailbox Delivery Queue length",
[]string{"name"},
nil,
)
c.retryMailboxDeliveryQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_retry_mailbox_delivery"),
"Retry Mailbox Delivery Queue length",
[]string{"name"},
nil,
)
c.unreachableQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_unreachable"),
"Unreachable Queue length",
[]string{"name"},
nil,
)
c.externalLargestDeliveryQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_external_largest_delivery"),
"External Largest Delivery Queue length",
[]string{"name"},
nil,
)
c.internalLargestDeliveryQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_internal_largest_delivery"),
"Internal Largest Delivery Queue length",
[]string{"name"},
nil,
)
c.poisonQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_poison"),
"Poison Queue length",
[]string{"name"},
nil,
)
c.messagesQueuedForDeliveryTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_messages_queued_for_delivery_total"),
"Messages Queued For Delivery Total",
[]string{"name"},
nil,
)
c.messagesSubmittedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_messages_submitted_total"),
"Messages Submitted Total",
[]string{"name"},
nil,
)
c.messagesDelayedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_messages_delayed_total"),
"Messages Delayed Total",
[]string{"name"},
nil,
)
c.messagesCompletedDeliveryTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_messages_completed_delivery_total"),
"Messages Completed Delivery Total",
[]string{"name"},
nil,
)
c.shadowQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_shadow_queue_length"),
"Shadow Queue Length",
[]string{"name"},
nil,
)
c.submissionQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_submission_queue_length"),
"Submission Queue Length",
[]string{"name"},
nil,
)
c.delayQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_delay_queue_length"),
"Delay Queue Length",
[]string{"name"},
nil,
)
c.itemsCompletedDeliveryTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_items_completed_delivery_total"),
"Items Completed Delivery Total",
[]string{"name"},
nil,
)
c.itemsQueuedForDeliveryExpiredTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_items_queued_for_delivery_expired_total"),
"Items Queued For Delivery Expired Total",
[]string{"name"},
nil,
)
c.itemsQueuedForDeliveryTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_items_queued_for_delivery_total"),
"Items Queued For Delivery Total",
[]string{"name"},
nil,
)
c.itemsResubmittedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transport_queues_items_resubmitted_total"),
"Items Resubmitted Total",
[]string{"name"},
nil,
)
return nil
}
func (c *Collector) collectPDHTransportQueues(ch chan<- prometheus.Metric) error {
func (c *Collector) collectTransportQueues(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorTransportQueues.Collect()
if err != nil {
return fmt.Errorf("failed to collect MSExchangeTransport Queues: %w", err)
@@ -185,6 +242,72 @@ func (c *Collector) collectPDHTransportQueues(ch chan<- prometheus.Metric) error
data[poisonQueueLength].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.messagesQueuedForDeliveryTotal,
prometheus.CounterValue,
data[messagesQueuedForDeliveryTotal].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.messagesSubmittedTotal,
prometheus.CounterValue,
data[messagesSubmittedTotal].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.messagesDelayedTotal,
prometheus.CounterValue,
data[messagesDelayedTotal].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.messagesCompletedDeliveryTotal,
prometheus.CounterValue,
data[messagesCompletedDeliveryTotal].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.shadowQueueLength,
prometheus.GaugeValue,
data[shadowQueueLength].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.submissionQueueLength,
prometheus.GaugeValue,
data[submissionQueueLength].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.delayQueueLength,
prometheus.GaugeValue,
data[delayQueueLength].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.itemsCompletedDeliveryTotal,
prometheus.CounterValue,
data[itemsCompletedDeliveryTotal].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.itemsQueuedForDeliveryExpiredTotal,
prometheus.CounterValue,
data[itemsQueuedForDeliveryExpiredTotal].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.itemsQueuedForDeliveryTotal,
prometheus.CounterValue,
data[itemsQueuedForDeliveryTotal].FirstValue,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.itemsResubmittedTotal,
prometheus.CounterValue,
data[itemsResubmittedTotal].FirstValue,
labelName,
)
}
return nil

View File

@@ -1,13 +1,12 @@
//go:build windows
package exchange
import (
"errors"
"fmt"
"log/slog"
"strings"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -20,17 +19,6 @@ const (
isActive = "Active"
)
// Perflib: [19430] MSExchange WorkloadManagement Workloads.
type perflibWorkloadManagementWorkloads struct {
Name string
ActiveTasks float64 `perflib:"ActiveTasks"`
CompletedTasks float64 `perflib:"CompletedTasks"`
QueuedTasks float64 `perflib:"QueuedTasks"`
YieldedTasks float64 `perflib:"YieldedTasks"`
IsActive float64 `perflib:"Active"`
}
func (c *Collector) buildWorkloadManagementWorkloads() error {
counters := []string{
activeTasks,
@@ -42,62 +30,46 @@ func (c *Collector) buildWorkloadManagementWorkloads() error {
var err error
c.perfDataCollectorWorkloadManagementWorkloads, err = perfdata.NewCollector(perfdata.V1, "MSExchange WorkloadManagement Workloads", perfdata.AllInstances, counters)
c.perfDataCollectorWorkloadManagementWorkloads, err = perfdata.NewCollector("MSExchange WorkloadManagement Workloads", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create MSExchange WorkloadManagement Workloads collector: %w", err)
}
return nil
}
func (c *Collector) collectWorkloadManagementWorkloads(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var data []perflibWorkloadManagementWorkloads
if err := v1.UnmarshalObject(ctx.PerfObjects["MSExchange WorkloadManagement Workloads"], &data, logger); err != nil {
return err
}
for _, instance := range data {
labelName := c.toLabelName(instance.Name)
if strings.HasSuffix(labelName, "_total") {
continue
}
ch <- prometheus.MustNewConstMetric(
c.activeTasks,
prometheus.GaugeValue,
instance.ActiveTasks,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.completedTasks,
prometheus.CounterValue,
instance.CompletedTasks,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.queuedTasks,
prometheus.CounterValue,
instance.QueuedTasks,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.yieldedTasks,
prometheus.CounterValue,
instance.YieldedTasks,
labelName,
)
ch <- prometheus.MustNewConstMetric(
c.isActive,
prometheus.GaugeValue,
instance.IsActive,
labelName,
)
}
c.activeTasks = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "workload_active_tasks"),
"Number of active tasks currently running in the background for workload management",
[]string{"name"},
nil,
)
c.completedTasks = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "workload_completed_tasks"),
"Number of workload management tasks that have been completed",
[]string{"name"},
nil,
)
c.queuedTasks = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "workload_queued_tasks"),
"Number of workload management tasks that are currently queued up waiting to be processed",
[]string{"name"},
nil,
)
c.yieldedTasks = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "workload_yielded_tasks"),
"The total number of tasks that have been yielded by a workload",
[]string{"name"},
nil,
)
c.isActive = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "workload_is_active"),
"Active indicates whether the workload is in an active (1) or paused (0) state",
[]string{"name"},
nil,
)
return nil
}
func (c *Collector) collectPDHWorkloadManagementWorkloads(ch chan<- prometheus.Metric) error {
func (c *Collector) collectWorkloadManagementWorkloads(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorWorkloadManagementWorkloads.Collect()
if err != nil {
return fmt.Errorf("failed to collect MSExchange WorkloadManagement Workloads: %w", err)

View File

@@ -31,6 +31,7 @@ var ConfigDefaults = Config{
type Collector struct {
config Config
logger *slog.Logger
fileMTime *prometheus.Desc
}
@@ -77,18 +78,14 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
logger.Info("filetime collector is in an experimental state! It may subject to change.",
slog.String("collector", Name),
)
c.logger = logger.With(slog.String("collector", Name))
c.logger.Info("filetime collector is in an experimental state! It may subject to change.")
c.fileMTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "mtime_timestamp_seconds"),
@@ -111,14 +108,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
return c.collectGlob(logger, ch)
}
// collectWin32 collects file times for each file path in the config. It using Win32 FindFirstFile and FindNextFile.
func (c *Collector) collectGlob(logger *slog.Logger, ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
wg := sync.WaitGroup{}
for _, filePattern := range c.config.FilePatterns {
@@ -127,8 +117,8 @@ func (c *Collector) collectGlob(logger *slog.Logger, ch chan<- prometheus.Metric
go func(filePattern string) {
defer wg.Done()
if err := c.collectGlobFilePath(logger, ch, filePattern); err != nil {
logger.Error("failed collecting metrics for filepath",
if err := c.collectGlobFilePath(ch, filePattern); err != nil {
c.logger.Error("failed collecting metrics for filepath",
slog.String("filepath", filePattern),
slog.Any("err", err),
)
@@ -141,7 +131,7 @@ func (c *Collector) collectGlob(logger *slog.Logger, ch chan<- prometheus.Metric
return nil
}
func (c *Collector) collectGlobFilePath(logger *slog.Logger, ch chan<- prometheus.Metric, filePattern string) error {
func (c *Collector) collectGlobFilePath(ch chan<- prometheus.Metric, filePattern string) error {
basePath, pattern := doublestar.SplitPattern(filePattern)
basePathFS := os.DirFS(basePath)
@@ -155,7 +145,7 @@ func (c *Collector) collectGlobFilePath(logger *slog.Logger, ch chan<- prometheu
fileInfo, err := os.Stat(filePath)
if err != nil {
logger.Warn("failed to state file",
c.logger.Warn("failed to state file",
slog.String("file", filePath),
slog.Any("err", err),
)

View File

@@ -1,10 +1,12 @@
//go:build windows
package filetime_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/filetime"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -57,11 +57,7 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
@@ -136,21 +132,6 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
return nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
if err := c.collect(ch); err != nil {
logger.Error("failed collecting fsrmquota metrics",
slog.Any("err", err),
)
return err
}
return nil
}
// MSFT_FSRMQuota docs:
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota
type MSFT_FSRMQuota struct {
@@ -168,7 +149,9 @@ type MSFT_FSRMQuota struct {
SoftLimit bool `mi:"SoftLimit"`
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
var dst []MSFT_FSRMQuota
if err := c.miSession.Query(&dst, mi.NamespaceRootWindowsFSRM, c.miQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)

View File

@@ -1,10 +1,12 @@
//go:build windows
package fsrmquota_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/fsrmquota"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,780 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorDataStore Hyper-V DataStore metrics
type collectorDataStore struct {
perfDataCollectorDataStore *perfdata.Collector
dataStoreFragmentationRatio *prometheus.Desc // \Hyper-V DataStore(*)\Fragmentation ratio
dataStoreSectorSize *prometheus.Desc // \Hyper-V DataStore(*)\Sector size
dataStoreDataAlignment *prometheus.Desc // \Hyper-V DataStore(*)\Data alignment
dataStoreCurrentReplayLogSize *prometheus.Desc // \Hyper-V DataStore(*)\Current replay logSize
dataStoreAvailableEntries *prometheus.Desc // \Hyper-V DataStore(*)\Number of available entries inside object tables
dataStoreEmptyEntries *prometheus.Desc // \Hyper-V DataStore(*)\Number of empty entries inside object tables
dataStoreFreeBytes *prometheus.Desc // \Hyper-V DataStore(*)\Number of free bytes inside key tables
dataStoreDataEnd *prometheus.Desc // \Hyper-V DataStore(*)\Data end
dataStoreFileObjects *prometheus.Desc // \Hyper-V DataStore(*)\Number of file objects
dataStoreObjectTables *prometheus.Desc // \Hyper-V DataStore(*)\Number of object tables
dataStoreKeyTables *prometheus.Desc // \Hyper-V DataStore(*)\Number of key tables
dataStoreFileDataSize *prometheus.Desc // \Hyper-V DataStore(*)\File data size in bytes
dataStoreTableDataSize *prometheus.Desc // \Hyper-V DataStore(*)\Table data size in bytes
dataStoreNamesSize *prometheus.Desc // \Hyper-V DataStore(*)\Names size in bytes
dataStoreNumberOfKeys *prometheus.Desc // \Hyper-V DataStore(*)\Number of keys
dataStoreReconnectLatencyMicro *prometheus.Desc // \Hyper-V DataStore(*)\Reconnect latency microseconds
dataStoreDisconnectCount *prometheus.Desc // \Hyper-V DataStore(*)\Disconnect count
dataStoreWriteToFileByteLatency *prometheus.Desc // \Hyper-V DataStore(*)\Write to file byte latency microseconds
dataStoreWriteToFileByteCount *prometheus.Desc // \Hyper-V DataStore(*)\Write to file byte count
dataStoreWriteToFileCount *prometheus.Desc // \Hyper-V DataStore(*)\Write to file count
dataStoreReadFromFileByteLatency *prometheus.Desc // \Hyper-V DataStore(*)\Read from file byte latency microseconds
dataStoreReadFromFileByteCount *prometheus.Desc // \Hyper-V DataStore(*)\Read from file byte count
dataStoreReadFromFileCount *prometheus.Desc // \Hyper-V DataStore(*)\Read from file count
dataStoreWriteToStorageByteLatency *prometheus.Desc // \Hyper-V DataStore(*)\Write to storage byte latency microseconds
dataStoreWriteToStorageByteCount *prometheus.Desc // \Hyper-V DataStore(*)\Write to storage byte count
dataStoreWriteToStorageCount *prometheus.Desc // \Hyper-V DataStore(*)\Write to storage count
dataStoreReadFromStorageByteLatency *prometheus.Desc // \Hyper-V DataStore(*)\Read from storage byte latency microseconds
dataStoreReadFromStorageByteCount *prometheus.Desc // \Hyper-V DataStore(*)\Read from storage byte count
dataStoreReadFromStorageCount *prometheus.Desc // \Hyper-V DataStore(*)\Read from storage count
dataStoreCommitByteLatency *prometheus.Desc // \Hyper-V DataStore(*)\Commit byte latency microseconds
dataStoreCommitByteCount *prometheus.Desc // \Hyper-V DataStore(*)\Commit byte count
dataStoreCommitCount *prometheus.Desc // \Hyper-V DataStore(*)\Commit count
dataStoreCacheUpdateOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Cache update operation latency microseconds
dataStoreCacheUpdateOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Cache update operation count
dataStoreCommitOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Commit operation latency microseconds
dataStoreCommitOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Commit operation count
dataStoreCompactOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Compact operation latency microseconds
dataStoreCompactOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Compact operation count
dataStoreLoadFileOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Load file operation latency microseconds
dataStoreLoadFileOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Load file operation count
dataStoreRemoveOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Remove operation latency microseconds
dataStoreRemoveOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Remove operation count
dataStoreQuerySizeOperationLatency *prometheus.Desc // \Hyper-V DataStore(*)\Query size operation latency microseconds
dataStoreQuerySizeOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Query size operation count
dataStoreSetOperationLatencyMicro *prometheus.Desc // \Hyper-V DataStore(*)\Set operation latency microseconds
dataStoreSetOperationCount *prometheus.Desc // \Hyper-V DataStore(*)\Set operation count
}
const (
// Hyper-V DataStore metrics
dataStoreFragmentationRatio = "Fragmentation ratio"
dataStoreSectorSize = "Sector size"
dataStoreDataAlignment = "Data alignment"
dataStoreCurrentReplayLogSize = "Current replay logSize"
dataStoreAvailableEntries = "Number of available entries inside object tables"
dataStoreEmptyEntries = "Number of empty entries inside object tables"
dataStoreFreeBytes = "Number of free bytes inside key tables"
dataStoreDataEnd = "Data end"
dataStoreFileObjects = "Number of file objects"
dataStoreObjectTables = "Number of object tables"
dataStoreKeyTables = "Number of key tables"
dataStoreFileDataSize = "File data size in bytes"
dataStoreTableDataSize = "Table data size in bytes"
dataStoreNamesSize = "Names size in bytes"
dataStoreNumberOfKeys = "Number of keys"
dataStoreReconnectLatencyMicro = "Reconnect latency microseconds"
dataStoreDisconnectCount = "Disconnect count"
dataStoreWriteToFileByteLatency = "Write to file byte latency microseconds"
dataStoreWriteToFileByteCount = "Write to file byte count"
dataStoreWriteToFileCount = "Write to file count"
dataStoreReadFromFileByteLatency = "Read from file byte latency microseconds"
dataStoreReadFromFileByteCount = "Read from file byte count"
dataStoreReadFromFileCount = "Read from file count"
dataStoreWriteToStorageByteLatency = "Write to storage byte latency microseconds"
dataStoreWriteToStorageByteCount = "Write to storage byte count"
dataStoreWriteToStorageCount = "Write to storage count"
dataStoreReadFromStorageByteLatency = "Read from storage byte latency microseconds"
dataStoreReadFromStorageByteCount = "Read from storage byte count"
dataStoreReadFromStorageCount = "Read from storage count"
dataStoreCommitByteLatency = "Commit byte latency microseconds"
dataStoreCommitByteCount = "Commit byte count"
dataStoreCommitCount = "Commit count"
dataStoreCacheUpdateOperationLatency = "Cache update operation latency microseconds"
dataStoreCacheUpdateOperationCount = "Cache update operation count"
dataStoreCommitOperationLatency = "Commit operation latency microseconds"
dataStoreCommitOperationCount = "Commit operation count"
dataStoreCompactOperationLatency = "Compact operation latency microseconds"
dataStoreCompactOperationCount = "Compact operation count"
dataStoreLoadFileOperationLatency = "Load file operation latency microseconds"
dataStoreLoadFileOperationCount = "Load file operation count"
dataStoreRemoveOperationLatency = "Remove operation latency microseconds"
dataStoreRemoveOperationCount = "Remove operation count"
dataStoreQuerySizeOperationLatency = "Query size operation latency microseconds"
dataStoreQuerySizeOperationCount = "Query size operation count"
dataStoreSetOperationLatencyMicro = "Set operation latency microseconds"
dataStoreSetOperationCount = "Set operation count"
)
func (c *Collector) buildDataStore() error {
var err error
c.perfDataCollectorDataStore, err = perfdata.NewCollector("Hyper-V DataStore", perfdata.InstanceAll, []string{
dataStoreFragmentationRatio,
dataStoreSectorSize,
dataStoreDataAlignment,
dataStoreCurrentReplayLogSize,
dataStoreAvailableEntries,
dataStoreEmptyEntries,
dataStoreFreeBytes,
dataStoreDataEnd,
dataStoreFileObjects,
dataStoreObjectTables,
dataStoreKeyTables,
dataStoreFileDataSize,
dataStoreTableDataSize,
dataStoreNamesSize,
dataStoreNumberOfKeys,
dataStoreReconnectLatencyMicro,
dataStoreDisconnectCount,
dataStoreWriteToFileByteLatency,
dataStoreWriteToFileByteCount,
dataStoreWriteToFileCount,
dataStoreReadFromFileByteLatency,
dataStoreReadFromFileByteCount,
dataStoreReadFromFileCount,
dataStoreWriteToStorageByteLatency,
dataStoreWriteToStorageByteCount,
dataStoreWriteToStorageCount,
dataStoreReadFromStorageByteLatency,
dataStoreReadFromStorageByteCount,
dataStoreReadFromStorageCount,
dataStoreCommitByteLatency,
dataStoreCommitByteCount,
dataStoreCommitCount,
dataStoreCacheUpdateOperationLatency,
dataStoreCacheUpdateOperationCount,
dataStoreCommitOperationLatency,
dataStoreCommitOperationCount,
dataStoreCompactOperationLatency,
dataStoreCompactOperationCount,
dataStoreLoadFileOperationLatency,
dataStoreLoadFileOperationCount,
dataStoreRemoveOperationLatency,
dataStoreRemoveOperationCount,
dataStoreQuerySizeOperationLatency,
dataStoreQuerySizeOperationCount,
dataStoreSetOperationLatencyMicro,
dataStoreSetOperationCount,
})
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to create Hyper-V DataStore collector: %w", err)
}
c.dataStoreFragmentationRatio = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_fragmentation_ratio"),
"Represents the fragmentation ratio of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreSectorSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_sector_size_bytes"),
"Represents the sector size of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreDataAlignment = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_data_alignment_bytes"),
"Represents the data alignment of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreCurrentReplayLogSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_current_replay_log_size_bytes"),
"Represents the current replay log size of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreAvailableEntries = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_available_entries"),
"Represents the number of available entries inside object tables.",
[]string{"datastore"},
nil,
)
c.dataStoreEmptyEntries = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_empty_entries"),
"Represents the number of empty entries inside object tables.",
[]string{"datastore"},
nil,
)
c.dataStoreFreeBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_free_bytes"),
"Represents the number of free bytes inside key tables.",
[]string{"datastore"},
nil,
)
c.dataStoreDataEnd = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_data_end_bytes"),
"Represents the data end of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreFileObjects = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_file_objects"),
"Represents the number of file objects in the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreObjectTables = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_object_tables"),
"Represents the number of object tables in the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreKeyTables = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_key_tables"),
"Represents the number of key tables in the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreFileDataSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_file_data_size_bytes"),
"Represents the file data size in bytes of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreTableDataSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_table_data_size_bytes"),
"Represents the table data size in bytes of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreNamesSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_names_size_bytes"),
"Represents the names size in bytes of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreNumberOfKeys = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_number_of_keys"),
"Represents the number of keys in the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreReconnectLatencyMicro = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_reconnect_latency_microseconds"),
"Represents the reconnect latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreDisconnectCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_disconnect_count"),
"Represents the disconnect count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreWriteToFileByteLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_file_byte_latency_microseconds"),
"Represents the write to file byte latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreWriteToFileByteCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_file_byte_count"),
"Represents the write to file byte count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreWriteToFileCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_file_count"),
"Represents the write to file count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreReadFromFileByteLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_file_byte_latency_microseconds"),
"Represents the read from file byte latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreReadFromFileByteCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_file_byte_count"),
"Represents the read from file byte count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreReadFromFileCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_file_count"),
"Represents the read from file count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreWriteToStorageByteLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_storage_byte_latency_microseconds"),
"Represents the write to storage byte latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreWriteToStorageByteCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_storage_byte_count"),
"Represents the write to storage byte count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreWriteToStorageCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_write_to_storage_count"),
"Represents the write to storage count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreReadFromStorageByteLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_storage_byte_latency_microseconds"),
"Represents the read from storage byte latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreReadFromStorageByteCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_storage_byte_count"),
"Represents the read from storage byte count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreReadFromStorageCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_read_from_storage_count"),
"Represents the read from storage count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreCommitByteLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_commit_byte_latency_microseconds"),
"Represents the commit byte latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreCommitByteCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_commit_byte_count"),
"Represents the commit byte count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreCommitCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_commit_count"),
"Represents the commit count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreCacheUpdateOperationLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_cache_update_operation_latency_microseconds"),
"Represents the cache update operation latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreCacheUpdateOperationCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_cache_update_operation_count"),
"Represents the cache update operation count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreCommitOperationLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_commit_operation_latency_microseconds"),
"Represents the commit operation latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreCommitOperationCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_commit_operation_count"),
"Represents the commit operation count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreCompactOperationLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_compact_operation_latency_microseconds"),
"Represents the compact operation latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreCompactOperationCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_compact_operation_count"),
"Represents the compact operation count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreLoadFileOperationLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_load_file_operation_latency_microseconds"),
"Represents the load file operation latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreLoadFileOperationCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_load_file_operation_count"),
"Represents the load file operation count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreRemoveOperationLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_remove_operation_latency_microseconds"),
"Represents the remove operation latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreRemoveOperationCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_remove_operation_count"),
"Represents the remove operation count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreQuerySizeOperationLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_query_size_operation_latency_microseconds"),
"Represents the query size operation latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreQuerySizeOperationCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_query_size_operation_count"),
"Represents the query size operation count of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreSetOperationLatencyMicro = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_set_operation_latency_microseconds"),
"Represents the set operation latency in microseconds of the DataStore.",
[]string{"datastore"},
nil,
)
c.dataStoreSetOperationCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "datastore_set_operation_count"),
"Represents the set operation count of the DataStore.",
[]string{"datastore"},
nil,
)
return nil
}
func (c *Collector) collectDataStore(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorDataStore.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to collect Hyper-V DataStore metrics: %w", err)
}
for name, page := range data {
ch <- prometheus.MustNewConstMetric(
c.dataStoreFragmentationRatio,
prometheus.GaugeValue,
page[dataStoreFragmentationRatio].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreSectorSize,
prometheus.GaugeValue,
page[dataStoreSectorSize].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreDataAlignment,
prometheus.GaugeValue,
page[dataStoreDataAlignment].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreCurrentReplayLogSize,
prometheus.GaugeValue,
page[dataStoreCurrentReplayLogSize].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreAvailableEntries,
prometheus.GaugeValue,
page[dataStoreAvailableEntries].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreEmptyEntries,
prometheus.GaugeValue,
page[dataStoreEmptyEntries].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreFreeBytes,
prometheus.GaugeValue,
page[dataStoreFreeBytes].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreDataEnd,
prometheus.GaugeValue,
page[dataStoreDataEnd].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreFileObjects,
prometheus.GaugeValue,
page[dataStoreFileObjects].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreObjectTables,
prometheus.GaugeValue,
page[dataStoreObjectTables].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreKeyTables,
prometheus.GaugeValue,
page[dataStoreKeyTables].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreFileDataSize,
prometheus.GaugeValue,
page[dataStoreFileDataSize].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreTableDataSize,
prometheus.GaugeValue,
page[dataStoreTableDataSize].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreNamesSize,
prometheus.GaugeValue,
page[dataStoreNamesSize].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreNumberOfKeys,
prometheus.GaugeValue,
page[dataStoreNumberOfKeys].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreReconnectLatencyMicro,
prometheus.GaugeValue,
page[dataStoreReconnectLatencyMicro].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreDisconnectCount,
prometheus.CounterValue,
page[dataStoreDisconnectCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreWriteToFileByteLatency,
prometheus.GaugeValue,
page[dataStoreWriteToFileByteLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreWriteToFileByteCount,
prometheus.CounterValue,
page[dataStoreWriteToFileByteCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreWriteToFileCount,
prometheus.CounterValue,
page[dataStoreWriteToFileCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreReadFromFileByteLatency,
prometheus.GaugeValue,
page[dataStoreReadFromFileByteLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreReadFromFileByteCount,
prometheus.CounterValue,
page[dataStoreReadFromFileByteCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreReadFromFileCount,
prometheus.CounterValue,
page[dataStoreReadFromFileCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreWriteToStorageByteLatency,
prometheus.GaugeValue,
page[dataStoreWriteToStorageByteLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreWriteToStorageByteCount,
prometheus.CounterValue,
page[dataStoreWriteToStorageByteCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreWriteToStorageCount,
prometheus.CounterValue,
page[dataStoreWriteToStorageCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreReadFromStorageByteLatency,
prometheus.GaugeValue,
page[dataStoreReadFromStorageByteLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreReadFromStorageByteCount,
prometheus.CounterValue,
page[dataStoreReadFromStorageByteCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreReadFromStorageCount,
prometheus.CounterValue,
page[dataStoreReadFromStorageCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreCommitByteLatency,
prometheus.GaugeValue,
page[dataStoreCommitByteLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreCommitByteCount,
prometheus.CounterValue,
page[dataStoreCommitByteCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreCommitCount,
prometheus.CounterValue,
page[dataStoreCommitCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreCacheUpdateOperationLatency,
prometheus.GaugeValue,
page[dataStoreCacheUpdateOperationLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreCacheUpdateOperationCount,
prometheus.CounterValue,
page[dataStoreCacheUpdateOperationCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreCommitOperationLatency,
prometheus.GaugeValue,
page[dataStoreCommitOperationLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreCommitOperationCount,
prometheus.CounterValue,
page[dataStoreCommitOperationCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreCompactOperationLatency,
prometheus.GaugeValue,
page[dataStoreCompactOperationLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreCompactOperationCount,
prometheus.CounterValue,
page[dataStoreCompactOperationCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreLoadFileOperationLatency,
prometheus.GaugeValue,
page[dataStoreLoadFileOperationLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreLoadFileOperationCount,
prometheus.CounterValue,
page[dataStoreLoadFileOperationCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreRemoveOperationLatency,
prometheus.GaugeValue,
page[dataStoreRemoveOperationLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreRemoveOperationCount,
prometheus.CounterValue,
page[dataStoreRemoveOperationCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreQuerySizeOperationLatency,
prometheus.GaugeValue,
page[dataStoreQuerySizeOperationLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreQuerySizeOperationCount,
prometheus.CounterValue,
page[dataStoreQuerySizeOperationCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreSetOperationLatencyMicro,
prometheus.GaugeValue,
page[dataStoreSetOperationLatencyMicro].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.dataStoreSetOperationCount,
prometheus.CounterValue,
page[dataStoreSetOperationCount].FirstValue,
name,
)
}
return nil
}

View File

@@ -0,0 +1,108 @@
package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils"
"github.com/prometheus/client_golang/prometheus"
)
// collectorDynamicMemoryBalancer Hyper-V Dynamic Memory Balancer metrics
type collectorDynamicMemoryBalancer struct {
perfDataCollectorDynamicMemoryBalancer *perfdata.Collector
vmDynamicMemoryBalancerAvailableMemoryForBalancing *prometheus.Desc // \Hyper-V Dynamic Memory Balancer(*)\Available Memory For Balancing
vmDynamicMemoryBalancerSystemCurrentPressure *prometheus.Desc // \Hyper-V Dynamic Memory Balancer(*)\System Current Pressure
vmDynamicMemoryBalancerAvailableMemory *prometheus.Desc // \Hyper-V Dynamic Memory Balancer(*)\Available Memory
vmDynamicMemoryBalancerAveragePressure *prometheus.Desc // \Hyper-V Dynamic Memory Balancer(*)\Average Pressure
}
const (
// Hyper-V Dynamic Memory Balancer metrics
vmDynamicMemoryBalancerAvailableMemory = "Available Memory"
vmDynamicMemoryBalancerAvailableMemoryForBalancing = "Available Memory For Balancing"
vmDynamicMemoryBalancerAveragePressure = "Average Pressure"
vmDynamicMemoryBalancerSystemCurrentPressure = "System Current Pressure"
)
func (c *Collector) buildDynamicMemoryBalancer() error {
var err error
// https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012
c.perfDataCollectorDynamicMemoryBalancer, err = perfdata.NewCollector("Hyper-V Dynamic Memory Balancer", perfdata.InstanceAll, []string{
vmDynamicMemoryBalancerAvailableMemory,
vmDynamicMemoryBalancerAvailableMemoryForBalancing,
vmDynamicMemoryBalancerAveragePressure,
vmDynamicMemoryBalancerSystemCurrentPressure,
})
if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err)
}
c.vmDynamicMemoryBalancerAvailableMemory = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_available_memory_bytes"),
"Represents the amount of memory left on the node.",
[]string{"balancer"},
nil,
)
c.vmDynamicMemoryBalancerAvailableMemoryForBalancing = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_available_memory_for_balancing_bytes"),
"Represents the available memory for balancing purposes.",
[]string{"balancer"},
nil,
)
c.vmDynamicMemoryBalancerAveragePressure = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_average_pressure_ratio"),
"Represents the average system pressure on the balancer node among all balanced objects.",
[]string{"balancer"},
nil,
)
c.vmDynamicMemoryBalancerSystemCurrentPressure = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_balancer_system_current_pressure_ratio"),
"Represents the current pressure in the system.",
[]string{"balancer"},
nil,
)
return nil
}
func (c *Collector) collectDynamicMemoryBalancer(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorDynamicMemoryBalancer.Collect()
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Dynamic Memory Balancer metrics: %w", err)
}
for name, page := range data {
ch <- prometheus.MustNewConstMetric(
c.vmDynamicMemoryBalancerAvailableMemory,
prometheus.GaugeValue,
utils.MBToBytes(page[vmDynamicMemoryBalancerAvailableMemory].FirstValue),
name,
)
ch <- prometheus.MustNewConstMetric(
c.vmDynamicMemoryBalancerAvailableMemoryForBalancing,
prometheus.GaugeValue,
utils.MBToBytes(page[vmDynamicMemoryBalancerAvailableMemoryForBalancing].FirstValue),
name,
)
ch <- prometheus.MustNewConstMetric(
c.vmDynamicMemoryBalancerAveragePressure,
prometheus.GaugeValue,
utils.PercentageToRatio(page[vmDynamicMemoryBalancerAveragePressure].FirstValue),
name,
)
ch <- prometheus.MustNewConstMetric(
c.vmDynamicMemoryBalancerSystemCurrentPressure,
prometheus.GaugeValue,
utils.PercentageToRatio(page[vmDynamicMemoryBalancerSystemCurrentPressure].FirstValue),
name,
)
}
return nil
}

View File

@@ -0,0 +1,204 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils"
"github.com/prometheus/client_golang/prometheus"
)
// collectorDynamicMemoryVM Hyper-V Dynamic Memory VM metrics
type collectorDynamicMemoryVM struct {
perfDataCollectorDynamicMemoryVM *perfdata.Collector
vmMemoryAddedMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Added Memory
vmMemoryCurrentPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Current Pressure
vmMemoryGuestVisiblePhysicalMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Guest Visible Physical Memory
vmMemoryMaximumPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Maximum Pressure
vmMemoryMemoryAddOperations *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Memory Add Operations
vmMemoryMemoryRemoveOperations *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Memory Remove Operations
vmMemoryMinimumPressure *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Minimum Pressure
vmMemoryPhysicalMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Physical Memory
vmMemoryRemovedMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Removed Memory
vmMemoryGuestAvailableMemory *prometheus.Desc // \Hyper-V Dynamic Memory VM(*)\Guest Available Memory
}
const (
// Hyper-V Dynamic Memory VM metrics
vmMemoryAddedMemory = "Added Memory"
vmMemoryCurrentPressure = "Current Pressure"
vmMemoryGuestAvailableMemory = "Guest Available Memory"
vmMemoryGuestVisiblePhysicalMemory = "Guest Visible Physical Memory"
vmMemoryMaximumPressure = "Maximum Pressure"
vmMemoryMemoryAddOperations = "Memory Add Operations"
vmMemoryMemoryRemoveOperations = "Memory Remove Operations"
vmMemoryMinimumPressure = "Minimum Pressure"
vmMemoryPhysicalMemory = "Physical Memory"
vmMemoryRemovedMemory = "Removed Memory"
)
func (c *Collector) buildDynamicMemoryVM() error {
var err error
c.perfDataCollectorDynamicMemoryVM, err = perfdata.NewCollector("Hyper-V Dynamic Memory VM", perfdata.InstanceAll, []string{
vmMemoryAddedMemory,
vmMemoryCurrentPressure,
vmMemoryGuestVisiblePhysicalMemory,
vmMemoryMaximumPressure,
vmMemoryMemoryAddOperations,
vmMemoryMemoryRemoveOperations,
vmMemoryMinimumPressure,
vmMemoryPhysicalMemory,
vmMemoryRemovedMemory,
vmMemoryGuestAvailableMemory,
})
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to create Hyper-V Dynamic Memory VM collector: %w", err)
}
c.vmMemoryAddedMemory = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_added_total"),
"Represents the cumulative amount of memory added to the VM.",
[]string{"vm"},
nil,
)
c.vmMemoryCurrentPressure = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_pressure_current_ratio"),
"Represents the current pressure in the VM.",
[]string{"vm"},
nil,
)
c.vmMemoryGuestAvailableMemory = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_guest_available_bytes"),
"Represents the current amount of available memory in the VM (reported by the VM).",
[]string{"vm"},
nil,
)
c.vmMemoryGuestVisiblePhysicalMemory = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_guest_visible_physical_memory_bytes"),
"Represents the amount of memory visible in the VM.'",
[]string{"vm"},
nil,
)
c.vmMemoryMaximumPressure = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_pressure_maximum_ratio"),
"Represents the maximum pressure band in the VM.",
[]string{"vm"},
nil,
)
c.vmMemoryMemoryAddOperations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_add_operations_total"),
"Represents the total number of add operations for the VM.",
[]string{"vm"},
nil,
)
c.vmMemoryMemoryRemoveOperations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_remove_operations_total"),
"Represents the total number of remove operations for the VM.",
[]string{"vm"},
nil,
)
c.vmMemoryMinimumPressure = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_pressure_minimum_ratio"),
"Represents the minimum pressure band in the VM.",
[]string{"vm"},
nil,
)
c.vmMemoryPhysicalMemory = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_physical_bytes"),
"Represents the current amount of memory in the VM.",
[]string{"vm"},
nil,
)
c.vmMemoryRemovedMemory = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_memory_vm_removed_bytes_total"),
"Represents the cumulative amount of memory removed from the VM.",
[]string{"vm"},
nil,
)
return nil
}
func (c *Collector) collectDynamicMemoryVM(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorDynamicMemoryVM.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to collect Hyper-V Dynamic Memory VM metrics: %w", err)
}
for vmName, vmData := range data {
ch <- prometheus.MustNewConstMetric(
c.vmMemoryAddedMemory,
prometheus.CounterValue,
utils.MBToBytes(vmData[vmMemoryAddedMemory].FirstValue),
vmName,
)
ch <- prometheus.MustNewConstMetric(
c.vmMemoryCurrentPressure,
prometheus.GaugeValue,
utils.PercentageToRatio(vmData[vmMemoryCurrentPressure].FirstValue),
vmName,
)
ch <- prometheus.MustNewConstMetric(
c.vmMemoryGuestAvailableMemory,
prometheus.GaugeValue,
utils.MBToBytes(vmData[vmMemoryGuestAvailableMemory].FirstValue),
vmName,
)
ch <- prometheus.MustNewConstMetric(
c.vmMemoryGuestVisiblePhysicalMemory,
prometheus.GaugeValue,
utils.MBToBytes(vmData[vmMemoryGuestVisiblePhysicalMemory].FirstValue),
vmName,
)
ch <- prometheus.MustNewConstMetric(
c.vmMemoryMaximumPressure,
prometheus.GaugeValue,
utils.PercentageToRatio(vmData[vmMemoryMaximumPressure].FirstValue),
vmName,
)
ch <- prometheus.MustNewConstMetric(
c.vmMemoryMemoryAddOperations,
prometheus.CounterValue,
vmData[vmMemoryMemoryAddOperations].FirstValue,
vmName,
)
ch <- prometheus.MustNewConstMetric(
c.vmMemoryMemoryRemoveOperations,
prometheus.CounterValue,
vmData[vmMemoryMemoryRemoveOperations].FirstValue,
vmName,
)
ch <- prometheus.MustNewConstMetric(
c.vmMemoryMinimumPressure,
prometheus.GaugeValue,
utils.PercentageToRatio(vmData[vmMemoryMinimumPressure].FirstValue),
vmName,
)
ch <- prometheus.MustNewConstMetric(
c.vmMemoryPhysicalMemory,
prometheus.GaugeValue,
utils.MBToBytes(vmData[vmMemoryPhysicalMemory].FirstValue),
vmName,
)
ch <- prometheus.MustNewConstMetric(
c.vmMemoryRemovedMemory,
prometheus.CounterValue,
utils.MBToBytes(vmData[vmMemoryRemovedMemory].FirstValue),
vmName,
)
}
return nil
}

View File

@@ -0,0 +1,121 @@
package hyperv
import (
"fmt"
"strings"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorHypervisorLogicalProcessor Hyper-V Hypervisor Logical Processor metrics
type collectorHypervisorLogicalProcessor struct {
perfDataCollectorHypervisorLogicalProcessor *perfdata.Collector
// \Hyper-V Hypervisor Logical Processor(*)\% Guest Run Time
// \Hyper-V Hypervisor Logical Processor(*)\% Hypervisor Run Time
// \Hyper-V Hypervisor Logical Processor(*)\% Idle Time
hypervisorLogicalProcessorTimeTotal *prometheus.Desc
hypervisorLogicalProcessorTotalRunTimeTotal *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\% Total Run Time
hypervisorLogicalProcessorContextSwitches *prometheus.Desc // \Hyper-V Hypervisor Logical Processor(*)\Context Switches/sec
}
const (
hypervisorLogicalProcessorGuestRunTimePercent = "% Guest Run Time"
hypervisorLogicalProcessorHypervisorRunTimePercent = "% Hypervisor Run Time"
hypervisorLogicalProcessorTotalRunTimePercent = "% Total Run Time"
hypervisorLogicalProcessorIdleRunTimePercent = "% Idle Time"
hypervisorLogicalProcessorContextSwitches = "Context Switches/sec"
)
func (c *Collector) buildHypervisorLogicalProcessor() error {
var err error
c.perfDataCollectorHypervisorLogicalProcessor, err = perfdata.NewCollector("Hyper-V Hypervisor Logical Processor", perfdata.InstanceAll, []string{
hypervisorLogicalProcessorGuestRunTimePercent,
hypervisorLogicalProcessorHypervisorRunTimePercent,
hypervisorLogicalProcessorTotalRunTimePercent,
hypervisorLogicalProcessorIdleRunTimePercent,
hypervisorLogicalProcessorContextSwitches,
})
if err != nil {
return fmt.Errorf("failed to create Hyper-V Hypervisor Logical Processor collector: %w", err)
}
c.hypervisorLogicalProcessorTimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_logical_processor_time_total"),
"Time that processor spent in different modes (hypervisor, guest, idle)",
[]string{"core", "state"},
nil,
)
c.hypervisorLogicalProcessorTotalRunTimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_logical_processor_total_run_time_total"),
"Time that processor spent",
[]string{"core"},
nil,
)
c.hypervisorLogicalProcessorContextSwitches = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_logical_processor_context_switches_total"),
"The rate of virtual processor context switches on the processor.",
[]string{"core"},
nil,
)
return nil
}
func (c *Collector) collectHypervisorLogicalProcessor(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorHypervisorLogicalProcessor.Collect()
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Hypervisor Logical Processor metrics: %w", err)
}
for coreName, coreData := range data {
// The name format is Hv LP <core id>
parts := strings.Split(coreName, " ")
if len(parts) != 3 {
return fmt.Errorf("unexpected Hyper-V Hypervisor Logical Processor name format: %s", coreName)
}
coreId := parts[2]
ch <- prometheus.MustNewConstMetric(
c.hypervisorLogicalProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorLogicalProcessorGuestRunTimePercent].FirstValue,
coreId, "guest",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorLogicalProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorLogicalProcessorHypervisorRunTimePercent].FirstValue,
coreId, "hypervisor",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorLogicalProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorLogicalProcessorIdleRunTimePercent].FirstValue,
coreId, "idle",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorLogicalProcessorTotalRunTimeTotal,
prometheus.CounterValue,
coreData[hypervisorLogicalProcessorTotalRunTimePercent].FirstValue,
coreId,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorLogicalProcessorContextSwitches,
prometheus.CounterValue,
coreData[hypervisorLogicalProcessorContextSwitches].FirstValue,
coreId,
)
}
return nil
}

View File

@@ -0,0 +1,349 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorHypervisorRootPartition Hyper-V Hypervisor Root Partition metrics
type collectorHypervisorRootPartition struct {
perfDataCollectorHypervisorRootPartition *perfdata.Collector
hypervisorRootPartitionAddressSpaces *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Address Spaces
hypervisorRootPartitionAttachedDevices *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Attached Devices
hypervisorRootPartitionDepositedPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Deposited Pages
hypervisorRootPartitionDeviceDMAErrors *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device DMA Errors
hypervisorRootPartitionDeviceInterruptErrors *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Errors
hypervisorRootPartitionDeviceInterruptMappings *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Mappings
hypervisorRootPartitionDeviceInterruptThrottleEvents *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Device Interrupt Throttle Events
hypervisorRootPartitionGPAPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\GPA Pages
hypervisorRootPartitionGPASpaceModifications *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\GPA Space Modifications/sec
hypervisorRootPartitionIOTLBFlushCost *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\I/O TLB Flush Cost
hypervisorRootPartitionIOTLBFlushes *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\I/O TLB Flushes/sec
hypervisorRootPartitionRecommendedVirtualTLBSize *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Recommended Virtual TLB Size
hypervisorRootPartitionSkippedTimerTicks *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Skipped Timer Ticks
hypervisorRootPartition1GDevicePages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\1G device pages
hypervisorRootPartition1GGPAPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\1G GPA pages
hypervisorRootPartition2MDevicePages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\2M device pages
hypervisorRootPartition2MGPAPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\2M GPA pages
hypervisorRootPartition4KDevicePages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\4K device pages
hypervisorRootPartition4KGPAPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\4K GPA pages
hypervisorRootPartitionVirtualTLBFlushEntries *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Flush Entries/sec
hypervisorRootPartitionVirtualTLBPages *prometheus.Desc // \Hyper-V Hypervisor Root Partition(*)\Virtual TLB Pages
}
const (
hypervisorRootPartitionAddressSpaces = "Address Spaces"
hypervisorRootPartitionAttachedDevices = "Attached Devices"
hypervisorRootPartitionDepositedPages = "Deposited Pages"
hypervisorRootPartitionDeviceDMAErrors = "Device DMA Errors"
hypervisorRootPartitionDeviceInterruptErrors = "Device Interrupt Errors"
hypervisorRootPartitionDeviceInterruptMappings = "Device Interrupt Mappings"
hypervisorRootPartitionDeviceInterruptThrottleEvents = "Device Interrupt Throttle Events"
hypervisorRootPartitionGPAPages = "GPA Pages"
hypervisorRootPartitionGPASpaceModifications = "GPA Space Modifications/sec"
hypervisorRootPartitionIOTLBFlushCost = "I/O TLB Flush Cost"
hypervisorRootPartitionIOTLBFlushes = "I/O TLB Flushes/sec"
hypervisorRootPartitionRecommendedVirtualTLBSize = "Recommended Virtual TLB Size"
hypervisorRootPartitionSkippedTimerTicks = "Skipped Timer Ticks"
hypervisorRootPartition1GDevicePages = "1G device pages"
hypervisorRootPartition1GGPAPages = "1G GPA pages"
hypervisorRootPartition2MDevicePages = "2M device pages"
hypervisorRootPartition2MGPAPages = "2M GPA pages"
hypervisorRootPartition4KDevicePages = "4K device pages"
hypervisorRootPartition4KGPAPages = "4K GPA pages"
hypervisorRootPartitionVirtualTLBFlushEntries = "Virtual TLB Flush Entires/sec"
hypervisorRootPartitionVirtualTLBPages = "Virtual TLB Pages"
)
func (c *Collector) buildHypervisorRootPartition() error {
var err error
c.perfDataCollectorHypervisorRootPartition, err = perfdata.NewCollector("Hyper-V Hypervisor Root Partition", []string{"Root"}, []string{
hypervisorRootPartitionAddressSpaces,
hypervisorRootPartitionAttachedDevices,
hypervisorRootPartitionDepositedPages,
hypervisorRootPartitionDeviceDMAErrors,
hypervisorRootPartitionDeviceInterruptErrors,
hypervisorRootPartitionDeviceInterruptMappings,
hypervisorRootPartitionDeviceInterruptThrottleEvents,
hypervisorRootPartitionGPAPages,
hypervisorRootPartitionGPASpaceModifications,
hypervisorRootPartitionIOTLBFlushCost,
hypervisorRootPartitionIOTLBFlushes,
hypervisorRootPartitionRecommendedVirtualTLBSize,
hypervisorRootPartitionSkippedTimerTicks,
hypervisorRootPartition1GDevicePages,
hypervisorRootPartition1GGPAPages,
hypervisorRootPartition2MDevicePages,
hypervisorRootPartition2MGPAPages,
hypervisorRootPartition4KDevicePages,
hypervisorRootPartition4KGPAPages,
hypervisorRootPartitionVirtualTLBFlushEntries,
hypervisorRootPartitionVirtualTLBPages,
})
if err != nil {
return fmt.Errorf("failed to create Hyper-V Hypervisor Root Partition collector: %w", err)
}
c.hypervisorRootPartitionAddressSpaces = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_address_spaces"),
"The number of address spaces in the virtual TLB of the partition",
nil,
nil,
)
c.hypervisorRootPartitionAttachedDevices = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_attached_devices"),
"The number of devices attached to the partition",
nil,
nil,
)
c.hypervisorRootPartitionDepositedPages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_deposited_pages"),
"The number of pages deposited into the partition",
nil,
nil,
)
c.hypervisorRootPartitionDeviceDMAErrors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_dma_errors"),
"An indicator of illegal DMA requests generated by all devices assigned to the partition",
nil,
nil,
)
c.hypervisorRootPartitionDeviceInterruptErrors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_errors"),
"An indicator of illegal interrupt requests generated by all devices assigned to the partition",
nil,
nil,
)
c.hypervisorRootPartitionDeviceInterruptMappings = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_mappings"),
"The number of device interrupt mappings used by the partition",
nil,
nil,
)
c.hypervisorRootPartitionDeviceInterruptThrottleEvents = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_device_interrupt_throttle_events"),
"The number of times an interrupt from a device assigned to the partition was temporarily throttled because the device was generating too many interrupts",
nil,
nil,
)
c.hypervisorRootPartitionGPAPages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_preferred_numa_node_index"),
"The number of pages present in the GPA space of the partition (zero for root partition)",
nil,
nil,
)
c.hypervisorRootPartitionGPASpaceModifications = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_gpa_space_modifications"),
"The rate of modifications to the GPA space of the partition",
nil,
nil,
)
c.hypervisorRootPartitionIOTLBFlushCost = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_io_tlb_flush_cost"),
"The average time (in nanoseconds) spent processing an I/O TLB flush",
nil,
nil,
)
c.hypervisorRootPartitionIOTLBFlushes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_io_tlb_flush"),
"The rate of flushes of I/O TLBs of the partition",
nil,
nil,
)
c.hypervisorRootPartitionRecommendedVirtualTLBSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_recommended_virtual_tlb_size"),
"The recommended number of pages to be deposited for the virtual TLB",
nil,
nil,
)
c.hypervisorRootPartitionSkippedTimerTicks = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_physical_pages_allocated"),
"The number of timer interrupts skipped for the partition",
nil,
nil,
)
c.hypervisorRootPartition1GDevicePages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_1G_device_pages"),
"The number of 1G pages present in the device space of the partition",
nil,
nil,
)
c.hypervisorRootPartition1GGPAPages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_1G_gpa_pages"),
"The number of 1G pages present in the GPA space of the partition",
nil,
nil,
)
c.hypervisorRootPartition2MDevicePages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_2M_device_pages"),
"The number of 2M pages present in the device space of the partition",
nil,
nil,
)
c.hypervisorRootPartition2MGPAPages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_2M_gpa_pages"),
"The number of 2M pages present in the GPA space of the partition",
nil,
nil,
)
c.hypervisorRootPartition4KDevicePages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_4K_device_pages"),
"The number of 4K pages present in the device space of the partition",
nil,
nil,
)
c.hypervisorRootPartition4KGPAPages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_4K_gpa_pages"),
"The number of 4K pages present in the GPA space of the partition",
nil,
nil,
)
c.hypervisorRootPartitionVirtualTLBFlushEntries = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_flush_entries"),
"The rate of flushes of the entire virtual TLB",
nil,
nil,
)
c.hypervisorRootPartitionVirtualTLBPages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "root_partition_virtual_tlb_pages"),
"The number of pages used by the virtual TLB of the partition",
nil,
nil,
)
return nil
}
func (c *Collector) collectHypervisorRootPartition(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorHypervisorRootPartition.Collect()
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Hypervisor Root Partition metrics: %w", err)
}
rootData, ok := data["Root"]
if !ok {
return errors.New("no data returned from Hyper-V Hypervisor Root Partition")
}
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionAddressSpaces,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionAddressSpaces].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionAttachedDevices,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionAttachedDevices].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionDepositedPages,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionDepositedPages].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionDeviceDMAErrors,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionDeviceDMAErrors].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionDeviceInterruptErrors,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionDeviceInterruptErrors].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionDeviceInterruptThrottleEvents,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionDeviceInterruptThrottleEvents].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionGPAPages,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionGPAPages].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionGPASpaceModifications,
prometheus.CounterValue,
rootData[hypervisorRootPartitionGPASpaceModifications].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionIOTLBFlushCost,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionIOTLBFlushCost].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionIOTLBFlushes,
prometheus.CounterValue,
rootData[hypervisorRootPartitionIOTLBFlushes].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionRecommendedVirtualTLBSize,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionRecommendedVirtualTLBSize].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionSkippedTimerTicks,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionSkippedTimerTicks].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartition1GDevicePages,
prometheus.GaugeValue,
rootData[hypervisorRootPartition1GDevicePages].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartition1GGPAPages,
prometheus.GaugeValue,
rootData[hypervisorRootPartition1GGPAPages].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartition2MDevicePages,
prometheus.GaugeValue,
rootData[hypervisorRootPartition2MDevicePages].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartition2MGPAPages,
prometheus.GaugeValue,
rootData[hypervisorRootPartition2MGPAPages].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartition4KDevicePages,
prometheus.GaugeValue,
rootData[hypervisorRootPartition4KDevicePages].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartition4KGPAPages,
prometheus.GaugeValue,
rootData[hypervisorRootPartition4KGPAPages].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionVirtualTLBFlushEntries,
prometheus.CounterValue,
rootData[hypervisorRootPartitionVirtualTLBFlushEntries].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionVirtualTLBPages,
prometheus.GaugeValue,
rootData[hypervisorRootPartitionVirtualTLBPages].FirstValue,
)
return nil
}

View File

@@ -0,0 +1,133 @@
package hyperv
import (
"fmt"
"strings"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorHypervisorRootVirtualProcessor Hyper-V Hypervisor Root Virtual Processor metrics
type collectorHypervisorRootVirtualProcessor struct {
perfDataCollectorHypervisorRootVirtualProcessor *perfdata.Collector
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Idle Time
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Run Time
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Hypervisor Run Time
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Remote Run Time
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Total Run Time
hypervisorRootVirtualProcessorTimeTotal *prometheus.Desc
hypervisorRootVirtualProcessorTotalRunTimeTotal *prometheus.Desc
hypervisorRootVirtualProcessorCPUWaitTimePerDispatch *prometheus.Desc // \Hyper-V Hypervisor Root Virtual Processor(*)\CPU Wait Time Per Dispatch
}
const (
hypervisorRootVirtualProcessorGuestIdleTimePercent = "% Guest Idle Time"
hypervisorRootVirtualProcessorGuestRunTimePercent = "% Guest Run Time"
hypervisorRootVirtualProcessorHypervisorRunTimePercent = "% Hypervisor Run Time"
hypervisorRootVirtualProcessorTotalRunTimePercent = "% Total Run Time"
hypervisorRootVirtualProcessorRemoteRunTimePercent = "% Remote Run Time"
hypervisorRootVirtualProcessorCPUWaitTimePerDispatch = "CPU Wait Time Per Dispatch"
)
func (c *Collector) buildHypervisorRootVirtualProcessor() error {
var err error
c.perfDataCollectorHypervisorRootVirtualProcessor, err = perfdata.NewCollector("Hyper-V Hypervisor Root Virtual Processor", perfdata.InstanceAll, []string{
hypervisorRootVirtualProcessorGuestIdleTimePercent,
hypervisorRootVirtualProcessorGuestRunTimePercent,
hypervisorRootVirtualProcessorHypervisorRunTimePercent,
hypervisorRootVirtualProcessorTotalRunTimePercent,
hypervisorRootVirtualProcessorRemoteRunTimePercent,
hypervisorRootVirtualProcessorCPUWaitTimePerDispatch,
})
if err != nil {
return fmt.Errorf("failed to create Hyper-V Hypervisor Root Virtual Processor collector: %w", err)
}
c.hypervisorRootVirtualProcessorTimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_root_virtual_processor_time_total"),
"Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote)",
[]string{"core", "state"},
nil,
)
c.hypervisorRootVirtualProcessorTotalRunTimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_root_virtual_processor_total_run_time_total"),
"Time that processor spent",
[]string{"core"},
nil,
)
c.hypervisorRootVirtualProcessorCPUWaitTimePerDispatch = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_root_virtual_cpu_wait_time_per_dispatch_total"),
"The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor.",
[]string{"core"},
nil,
)
return nil
}
func (c *Collector) collectHypervisorRootVirtualProcessor(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorHypervisorRootVirtualProcessor.Collect()
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Hypervisor Root Virtual Processor metrics: %w", err)
}
for coreName, coreData := range data {
// The name format is Hv LP <core id>
parts := strings.Split(coreName, " ")
if len(parts) != 3 {
return fmt.Errorf("unexpected Hyper-V Hypervisor Root Virtual Processor name format: %s", coreName)
}
coreId := parts[2]
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootVirtualProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorRootVirtualProcessorGuestRunTimePercent].FirstValue,
coreId, "guest_run",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootVirtualProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorRootVirtualProcessorHypervisorRunTimePercent].FirstValue,
coreId, "hypervisor",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootVirtualProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorRootVirtualProcessorGuestIdleTimePercent].FirstValue,
coreId, "guest_idle",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootVirtualProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorRootVirtualProcessorRemoteRunTimePercent].FirstValue,
coreId, "remote",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootVirtualProcessorTotalRunTimeTotal,
prometheus.CounterValue,
coreData[hypervisorRootVirtualProcessorTotalRunTimePercent].FirstValue,
coreId,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorRootVirtualProcessorCPUWaitTimePerDispatch,
prometheus.CounterValue,
coreData[hypervisorRootVirtualProcessorCPUWaitTimePerDispatch].FirstValue,
coreId,
)
}
return nil
}

View File

@@ -0,0 +1,137 @@
package hyperv
import (
"errors"
"fmt"
"strings"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorHypervisorVirtualProcessor Hyper-V Hypervisor Virtual Processor metrics
type collectorHypervisorVirtualProcessor struct {
perfDataCollectorHypervisorVirtualProcessor *perfdata.Collector
// \Hyper-V Hypervisor Virtual Processor(*)\% Guest Idle Time
// \Hyper-V Hypervisor Virtual Processor(*)\% Guest Run Time
// \Hyper-V Hypervisor Virtual Processor(*)\% Hypervisor Run Time
// \Hyper-V Hypervisor Virtual Processor(*)\% Remote Run Time
hypervisorVirtualProcessorTimeTotal *prometheus.Desc
hypervisorVirtualProcessorTotalRunTimeTotal *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Total Run Time
hypervisorVirtualProcessorContextSwitches *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per Dispatch
}
const (
hypervisorVirtualProcessorGuestRunTimePercent = "% Guest Run Time"
hypervisorVirtualProcessorGuestIdleTimePercent = "% Guest Idle Time"
hypervisorVirtualProcessorHypervisorRunTimePercent = "% Hypervisor Run Time"
hypervisorVirtualProcessorTotalRunTimePercent = "% Total Run Time"
hypervisorVirtualProcessorRemoteRunTimePercent = "% Remote Run Time"
hypervisorVirtualProcessorCPUWaitTimePerDispatch = "CPU Wait Time Per Dispatch"
)
func (c *Collector) buildHypervisorVirtualProcessor() error {
var err error
c.perfDataCollectorHypervisorVirtualProcessor, err = perfdata.NewCollector("Hyper-V Hypervisor Virtual Processor", perfdata.InstanceAll, []string{
hypervisorVirtualProcessorGuestRunTimePercent,
hypervisorVirtualProcessorGuestIdleTimePercent,
hypervisorVirtualProcessorHypervisorRunTimePercent,
hypervisorVirtualProcessorTotalRunTimePercent,
hypervisorVirtualProcessorRemoteRunTimePercent,
hypervisorVirtualProcessorCPUWaitTimePerDispatch,
})
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to create Hyper-V Hypervisor Virtual Processor collector: %w", err)
}
c.hypervisorVirtualProcessorTimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_time_total"),
"Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote)",
[]string{"vm", "core", "state"},
nil,
)
c.hypervisorVirtualProcessorTotalRunTimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_total_run_time_total"),
"Time that processor spent",
[]string{"vm", "core"},
nil,
)
c.hypervisorVirtualProcessorContextSwitches = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_cpu_wait_time_per_dispatch_total"),
"The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor.",
[]string{"vm", "core"},
nil,
)
return nil
}
func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorHypervisorVirtualProcessor.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to collect Hyper-V Hypervisor Virtual Processor metrics: %w", err)
}
for coreName, coreData := range data {
// The name format is <VM Name>:Hv VP <vcore id>
parts := strings.Split(coreName, ":")
if len(parts) != 2 {
return fmt.Errorf("unexpected format of Name in Hyper-V Hypervisor Virtual Processor: %q, expected %q", coreName, "<VM Name>:Hv VP <vcore id>")
}
coreParts := strings.Split(parts[1], " ")
if len(coreParts) != 3 {
return fmt.Errorf("unexpected format of core identifier in Hyper-V Hypervisor Virtual Processor: %q, expected %q", parts[1], "Hv VP <vcore id>")
}
vmName := parts[0]
coreId := coreParts[2]
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorVirtualProcessorGuestRunTimePercent].FirstValue,
vmName, coreId, "guest_run",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorVirtualProcessorHypervisorRunTimePercent].FirstValue,
vmName, coreId, "hypervisor",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorVirtualProcessorGuestIdleTimePercent].FirstValue,
vmName, coreId, "guest_idle",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorTimeTotal,
prometheus.CounterValue,
coreData[hypervisorVirtualProcessorGuestIdleTimePercent].FirstValue,
vmName, coreId, "guest_idle",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorTotalRunTimeTotal,
prometheus.CounterValue,
coreData[hypervisorVirtualProcessorTotalRunTimePercent].FirstValue,
vmName, coreId,
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorContextSwitches,
prometheus.CounterValue,
coreData[hypervisorVirtualProcessorCPUWaitTimePerDispatch].FirstValue,
vmName, coreId,
)
}
return nil
}

View File

@@ -0,0 +1,139 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorLegacyNetworkAdapter Hyper-V Legacy Network Adapter metrics
type collectorLegacyNetworkAdapter struct {
perfDataCollectorLegacyNetworkAdapter *perfdata.Collector
legacyNetworkAdapterBytesDropped *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Dropped
legacyNetworkAdapterBytesReceived *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Received/sec
legacyNetworkAdapterBytesSent *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Bytes Sent/sec
legacyNetworkAdapterFramesDropped *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Dropped
legacyNetworkAdapterFramesReceived *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Received/sec
legacyNetworkAdapterFramesSent *prometheus.Desc // \Hyper-V Legacy Network Adapter(*)\Frames Sent/sec
}
const (
legacyNetworkAdapterBytesDropped = "Bytes Dropped"
legacyNetworkAdapterBytesReceived = "Bytes Received/sec"
legacyNetworkAdapterBytesSent = "Bytes Sent/sec"
legacyNetworkAdapterFramesDropped = "Frames Dropped"
legacyNetworkAdapterFramesReceived = "Frames Received/sec"
legacyNetworkAdapterFramesSent = "Frames Sent/sec"
)
func (c *Collector) buildLegacyNetworkAdapter() error {
var err error
c.perfDataCollectorLegacyNetworkAdapter, err = perfdata.NewCollector("Hyper-V Legacy Network Adapter", perfdata.InstanceAll, []string{
legacyNetworkAdapterBytesDropped,
legacyNetworkAdapterBytesReceived,
legacyNetworkAdapterBytesSent,
legacyNetworkAdapterFramesDropped,
legacyNetworkAdapterFramesReceived,
legacyNetworkAdapterFramesSent,
})
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to create Hyper-V Legacy Network Adapter collector: %w", err)
}
c.legacyNetworkAdapterBytesDropped = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_bytes_dropped_total"),
"Bytes Dropped is the number of bytes dropped on the network adapter",
[]string{"adapter"},
nil,
)
c.legacyNetworkAdapterBytesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_bytes_received_total"),
"Bytes received is the number of bytes received on the network adapter",
[]string{"adapter"},
nil,
)
c.legacyNetworkAdapterBytesSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_bytes_sent_total"),
"Bytes sent is the number of bytes sent over the network adapter",
[]string{"adapter"},
nil,
)
c.legacyNetworkAdapterFramesDropped = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_frames_dropped_total"),
"Frames Dropped is the number of frames dropped on the network adapter",
[]string{"adapter"},
nil,
)
c.legacyNetworkAdapterFramesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_frames_received_total"),
"Frames received is the number of frames received on the network adapter",
[]string{"adapter"},
nil,
)
c.legacyNetworkAdapterFramesSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "legacy_network_adapter_frames_sent_total"),
"Frames sent is the number of frames sent over the network adapter",
[]string{"adapter"},
nil,
)
return nil
}
func (c *Collector) collectLegacyNetworkAdapter(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorLegacyNetworkAdapter.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to collect Hyper-V Legacy Network Adapter metrics: %w", err)
}
for name, adapter := range data {
ch <- prometheus.MustNewConstMetric(
c.legacyNetworkAdapterBytesDropped,
prometheus.GaugeValue,
adapter[legacyNetworkAdapterBytesDropped].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.legacyNetworkAdapterBytesReceived,
prometheus.CounterValue,
adapter[legacyNetworkAdapterBytesReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.legacyNetworkAdapterBytesSent,
prometheus.CounterValue,
adapter[legacyNetworkAdapterBytesSent].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.legacyNetworkAdapterFramesReceived,
prometheus.CounterValue,
adapter[legacyNetworkAdapterFramesReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.legacyNetworkAdapterFramesDropped,
prometheus.CounterValue,
adapter[legacyNetworkAdapterFramesDropped].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.legacyNetworkAdapterFramesSent,
prometheus.CounterValue,
adapter[legacyNetworkAdapterFramesSent].FirstValue,
name,
)
}
return nil
}

View File

@@ -1,10 +1,12 @@
//go:build windows
package hyperv_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/hyperv"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -0,0 +1,74 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorVirtualMachineHealthSummary Hyper-V Virtual Machine Health Summary metrics
type collectorVirtualMachineHealthSummary struct {
perfDataCollectorVirtualMachineHealthSummary *perfdata.Collector
// \Hyper-V Virtual Machine Health Summary\Health Critical
// \Hyper-V Virtual Machine Health Summary\Health Ok
health *prometheus.Desc
}
const (
// Hyper-V Virtual Machine Health Summary
healthCritical = "Health Critical"
healthOk = "Health Ok"
)
func (c *Collector) buildVirtualMachineHealthSummary() error {
var err error
c.perfDataCollectorVirtualMachineHealthSummary, err = perfdata.NewCollector("Hyper-V Virtual Machine Health Summary", nil, []string{
healthCritical,
healthOk,
})
if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err)
}
c.health = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_machine_health_total_count"),
"Represents the number of virtual machines with critical health",
[]string{"state"},
nil,
)
return nil
}
func (c *Collector) collectVirtualMachineHealthSummary(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualMachineHealthSummary.Collect()
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual Machine Health Summary metrics: %w", err)
}
healthData, ok := data[perfdata.EmptyInstance]
if !ok {
return errors.New("no data returned for Hyper-V Virtual Machine Health Summary")
}
ch <- prometheus.MustNewConstMetric(
c.health,
prometheus.GaugeValue,
healthData[healthCritical].FirstValue,
"critical",
)
ch <- prometheus.MustNewConstMetric(
c.health,
prometheus.GaugeValue,
healthData[healthOk].FirstValue,
"ok",
)
return nil
}

View File

@@ -0,0 +1,90 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorVirtualMachineVidPartition Hyper-V VM Vid Partition metrics
type collectorVirtualMachineVidPartition struct {
perfDataCollectorVirtualMachineVidPartition *perfdata.Collector
physicalPagesAllocated *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Physical Pages Allocated
preferredNUMANodeIndex *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Preferred NUMA Node Index
remotePhysicalPages *prometheus.Desc // \Hyper-V VM Vid Partition(*)\Remote Physical Pages
}
const (
physicalPagesAllocated = "Physical Pages Allocated"
preferredNUMANodeIndex = "Preferred NUMA Node Index"
remotePhysicalPages = "Remote Physical Pages"
)
func (c *Collector) buildVirtualMachineVidPartition() error {
var err error
c.perfDataCollectorVirtualMachineVidPartition, err = perfdata.NewCollector("Hyper-V VM Vid Partition", perfdata.InstanceAll, []string{
physicalPagesAllocated,
preferredNUMANodeIndex,
remotePhysicalPages,
})
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to create Hyper-V VM Vid Partition collector: %w", err)
}
c.physicalPagesAllocated = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vid_physical_pages_allocated"),
"The number of physical pages allocated",
[]string{"vm"},
nil,
)
c.preferredNUMANodeIndex = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vid_preferred_numa_node_index"),
"The preferred NUMA node index associated with this partition",
[]string{"vm"},
nil,
)
c.remotePhysicalPages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vid_remote_physical_pages"),
"The number of physical pages not allocated from the preferred NUMA node",
[]string{"vm"},
nil,
)
return nil
}
func (c *Collector) collectVirtualMachineVidPartition(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualMachineVidPartition.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to collect Hyper-V VM Vid Partition metrics: %w", err)
}
for name, page := range data {
ch <- prometheus.MustNewConstMetric(
c.physicalPagesAllocated,
prometheus.GaugeValue,
page[physicalPagesAllocated].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.preferredNUMANodeIndex,
prometheus.GaugeValue,
page[preferredNUMANodeIndex].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.remotePhysicalPages,
prometheus.GaugeValue,
page[remotePhysicalPages].FirstValue,
name,
)
}
return nil
}

View File

@@ -0,0 +1,139 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorVirtualNetworkAdapter Hyper-V Virtual Network Adapter metrics
type collectorVirtualNetworkAdapter struct {
perfDataCollectorVirtualNetworkAdapter *perfdata.Collector
virtualNetworkAdapterBytesReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Bytes Received/sec
virtualNetworkAdapterBytesSent *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Bytes Sent/sec
virtualNetworkAdapterDroppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Dropped Packets Incoming/sec
virtualNetworkAdapterDroppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Dropped Packets Outgoing/sec
virtualNetworkAdapterPacketsReceived *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Received/sec
virtualNetworkAdapterPacketsSent *prometheus.Desc // \Hyper-V Virtual Network Adapter(*)\Packets Sent/sec
}
const (
virtualNetworkAdapterBytesReceived = "Bytes Received/sec"
virtualNetworkAdapterBytesSent = "Bytes Sent/sec"
virtualNetworkAdapterDroppedPacketsIncoming = "Dropped Packets Incoming/sec"
virtualNetworkAdapterDroppedPacketsOutgoing = "Dropped Packets Outgoing/sec"
virtualNetworkAdapterPacketsReceived = "Packets Received/sec"
virtualNetworkAdapterPacketsSent = "Packets Sent/sec"
)
func (c *Collector) buildVirtualNetworkAdapter() error {
var err error
c.perfDataCollectorVirtualNetworkAdapter, err = perfdata.NewCollector("Hyper-V Virtual Network Adapter", perfdata.InstanceAll, []string{
virtualNetworkAdapterBytesReceived,
virtualNetworkAdapterBytesSent,
virtualNetworkAdapterDroppedPacketsIncoming,
virtualNetworkAdapterDroppedPacketsOutgoing,
virtualNetworkAdapterPacketsReceived,
virtualNetworkAdapterPacketsSent,
})
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter collector: %w", err)
}
c.virtualNetworkAdapterBytesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_received_bytes_total"),
"Represents the total number of bytes received per second by the network adapter",
[]string{"adapter"},
nil,
)
c.virtualNetworkAdapterBytesSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_sent_bytes_total"),
"Represents the total number of bytes sent per second by the network adapter",
[]string{"adapter"},
nil,
)
c.virtualNetworkAdapterDroppedPacketsIncoming = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_incoming_dropped_packets_total"),
"Represents the total number of dropped packets per second in the incoming direction of the network adapter",
[]string{"adapter"},
nil,
)
c.virtualNetworkAdapterDroppedPacketsOutgoing = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_outgoing_dropped_packets_total"),
"Represents the total number of dropped packets per second in the outgoing direction of the network adapter",
[]string{"adapter"},
nil,
)
c.virtualNetworkAdapterPacketsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_received_packets_total"),
"Represents the total number of packets received per second by the network adapter",
[]string{"adapter"},
nil,
)
c.virtualNetworkAdapterPacketsSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_sent_packets_total"),
"Represents the total number of packets sent per second by the network adapter",
[]string{"adapter"},
nil,
)
return nil
}
func (c *Collector) collectVirtualNetworkAdapter(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualNetworkAdapter.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to collect Hyper-V Virtual Network Adapter metrics: %w", err)
}
for name, adapterData := range data {
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterBytesReceived,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterBytesReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterBytesSent,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterBytesSent].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDroppedPacketsIncoming,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDroppedPacketsIncoming].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDroppedPacketsOutgoing,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDroppedPacketsOutgoing].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterPacketsReceived,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterPacketsReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterPacketsSent,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterPacketsSent].FirstValue,
name,
)
}
return nil
}

View File

@@ -0,0 +1,527 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorVirtualNetworkAdapterDropReasons Hyper-V Virtual Network Adapter Drop Reasons metrics
type collectorVirtualNetworkAdapterDropReasons struct {
perfDataCollectorVirtualNetworkAdapterDropReasons *perfdata.Collector
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing LowPowerPacketFilter
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming LowPowerPacketFilter
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidPDQueue
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidPDQueue
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FilteredIsolationUntagged
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FilteredIsolationUntagged
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing SwitchDataFlowDisabled
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming SwitchDataFlowDisabled
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedPacketFilter
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedPacketFilter
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NicDisabled
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NicDisabled
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedDestinationListUpdate
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedDestinationListUpdate
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InjectedIcmp
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InjectedIcmp
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing StormLimit
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming StormLimit
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidFirstNBTooSmall
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidFirstNBTooSmall
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidSourceMac
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidSourceMac
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidDestMac
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidDestMac
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidVlanFormat
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidVlanFormat
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NativeFwdingReq
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NativeFwdingReq
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing MTUMismatch
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming MTUMismatch
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidConfig
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidConfig
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing RequiredExtensionMissing
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming RequiredExtensionMissing
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing VirtualSubnetId
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming VirtualSubnetId
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing BridgeReserved
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming BridgeReserved
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing RouterGuard
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming RouterGuard
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing DhcpGuard
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming DhcpGuard
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing MacSpoofing
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming MacSpoofing
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Ipsec
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Ipsec
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Qos
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Qos
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedPvlanSetting
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedPvlanSetting
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FailedSecurityPolicy
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FailedSecurityPolicy
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing UnauthorizedMAC
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming UnauthorizedMAC
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing UnauthorizedVLAN
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming UnauthorizedVLAN
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing FilteredVLAN
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming FilteredVLAN
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Filtered
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Filtered
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Busy
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Busy
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NotAccepted
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NotAccepted
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Disconnected
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Disconnected
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing NotReady
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming NotReady
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Resources
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Resources
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidPacket
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidPacket
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing InvalidData
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming InvalidData
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Outgoing Unknown
// \Hyper-V Virtual Network Adapter Drop Reasons(*)\Incoming Unknown
virtualNetworkAdapterDropReasons *prometheus.Desc
}
const (
virtualNetworkAdapterDropReasonsOutgoingNativeFwdingReq = "Outgoing NativeFwdingReq"
virtualNetworkAdapterDropReasonsIncomingNativeFwdingReq = "Incoming NativeFwdingReq"
virtualNetworkAdapterDropReasonsOutgoingMTUMismatch = "Outgoing MTUMismatch"
virtualNetworkAdapterDropReasonsIncomingMTUMismatch = "Incoming MTUMismatch"
virtualNetworkAdapterDropReasonsOutgoingInvalidConfig = "Outgoing InvalidConfig"
virtualNetworkAdapterDropReasonsIncomingInvalidConfig = "Incoming InvalidConfig"
virtualNetworkAdapterDropReasonsOutgoingRequiredExtensionMissing = "Outgoing RequiredExtensionMissing"
virtualNetworkAdapterDropReasonsIncomingRequiredExtensionMissing = "Incoming RequiredExtensionMissing"
virtualNetworkAdapterDropReasonsOutgoingVirtualSubnetId = "Outgoing VirtualSubnetId"
virtualNetworkAdapterDropReasonsIncomingVirtualSubnetId = "Incoming VirtualSubnetId"
virtualNetworkAdapterDropReasonsOutgoingBridgeReserved = "Outgoing BridgeReserved"
virtualNetworkAdapterDropReasonsIncomingBridgeReserved = "Incoming BridgeReserved"
virtualNetworkAdapterDropReasonsOutgoingRouterGuard = "Outgoing RouterGuard"
virtualNetworkAdapterDropReasonsIncomingRouterGuard = "Incoming RouterGuard"
virtualNetworkAdapterDropReasonsOutgoingDhcpGuard = "Outgoing DhcpGuard"
virtualNetworkAdapterDropReasonsIncomingDhcpGuard = "Incoming DhcpGuard"
virtualNetworkAdapterDropReasonsOutgoingMacSpoofing = "Outgoing MacSpoofing"
virtualNetworkAdapterDropReasonsIncomingMacSpoofing = "Incoming MacSpoofing"
virtualNetworkAdapterDropReasonsOutgoingIpsec = "Outgoing Ipsec"
virtualNetworkAdapterDropReasonsIncomingIpsec = "Incoming Ipsec"
virtualNetworkAdapterDropReasonsOutgoingQos = "Outgoing Qos"
virtualNetworkAdapterDropReasonsIncomingQos = "Incoming Qos"
virtualNetworkAdapterDropReasonsOutgoingFailedPvlanSetting = "Outgoing FailedPvlanSetting"
virtualNetworkAdapterDropReasonsIncomingFailedPvlanSetting = "Incoming FailedPvlanSetting"
virtualNetworkAdapterDropReasonsOutgoingFailedSecurityPolicy = "Outgoing FailedSecurityPolicy"
virtualNetworkAdapterDropReasonsIncomingFailedSecurityPolicy = "Incoming FailedSecurityPolicy"
virtualNetworkAdapterDropReasonsOutgoingUnauthorizedMAC = "Outgoing UnauthorizedMAC"
virtualNetworkAdapterDropReasonsIncomingUnauthorizedMAC = "Incoming UnauthorizedMAC"
virtualNetworkAdapterDropReasonsOutgoingUnauthorizedVLAN = "Outgoing UnauthorizedVLAN"
virtualNetworkAdapterDropReasonsIncomingUnauthorizedVLAN = "Incoming UnauthorizedVLAN"
virtualNetworkAdapterDropReasonsOutgoingFilteredVLAN = "Outgoing FilteredVLAN"
virtualNetworkAdapterDropReasonsIncomingFilteredVLAN = "Incoming FilteredVLAN"
virtualNetworkAdapterDropReasonsOutgoingFiltered = "Outgoing Filtered"
virtualNetworkAdapterDropReasonsIncomingFiltered = "Incoming Filtered"
virtualNetworkAdapterDropReasonsOutgoingBusy = "Outgoing Busy"
virtualNetworkAdapterDropReasonsIncomingBusy = "Incoming Busy"
virtualNetworkAdapterDropReasonsOutgoingNotAccepted = "Outgoing NotAccepted"
virtualNetworkAdapterDropReasonsIncomingNotAccepted = "Incoming NotAccepted"
virtualNetworkAdapterDropReasonsOutgoingDisconnected = "Outgoing Disconnected"
virtualNetworkAdapterDropReasonsIncomingDisconnected = "Incoming Disconnected"
virtualNetworkAdapterDropReasonsOutgoingNotReady = "Outgoing NotReady"
virtualNetworkAdapterDropReasonsIncomingNotReady = "Incoming NotReady"
virtualNetworkAdapterDropReasonsOutgoingResources = "Outgoing Resources"
virtualNetworkAdapterDropReasonsIncomingResources = "Incoming Resources"
virtualNetworkAdapterDropReasonsOutgoingInvalidPacket = "Outgoing InvalidPacket"
virtualNetworkAdapterDropReasonsIncomingInvalidPacket = "Incoming InvalidPacket"
virtualNetworkAdapterDropReasonsOutgoingInvalidData = "Outgoing InvalidData"
virtualNetworkAdapterDropReasonsIncomingInvalidData = "Incoming InvalidData"
virtualNetworkAdapterDropReasonsOutgoingUnknown = "Outgoing Unknown"
virtualNetworkAdapterDropReasonsIncomingUnknown = "Incoming Unknown"
)
func (c *Collector) buildVirtualNetworkAdapterDropReasons() error {
var err error
c.perfDataCollectorVirtualNetworkAdapterDropReasons, err = perfdata.NewCollector("Hyper-V Virtual Network Adapter Drop Reasons", perfdata.InstanceAll, []string{
virtualNetworkAdapterDropReasonsOutgoingNativeFwdingReq,
virtualNetworkAdapterDropReasonsIncomingNativeFwdingReq,
virtualNetworkAdapterDropReasonsOutgoingMTUMismatch,
virtualNetworkAdapterDropReasonsIncomingMTUMismatch,
virtualNetworkAdapterDropReasonsOutgoingInvalidConfig,
virtualNetworkAdapterDropReasonsIncomingInvalidConfig,
virtualNetworkAdapterDropReasonsOutgoingRequiredExtensionMissing,
virtualNetworkAdapterDropReasonsIncomingRequiredExtensionMissing,
virtualNetworkAdapterDropReasonsOutgoingVirtualSubnetId,
virtualNetworkAdapterDropReasonsIncomingVirtualSubnetId,
virtualNetworkAdapterDropReasonsOutgoingBridgeReserved,
virtualNetworkAdapterDropReasonsIncomingBridgeReserved,
virtualNetworkAdapterDropReasonsOutgoingRouterGuard,
virtualNetworkAdapterDropReasonsIncomingRouterGuard,
virtualNetworkAdapterDropReasonsOutgoingDhcpGuard,
virtualNetworkAdapterDropReasonsIncomingDhcpGuard,
virtualNetworkAdapterDropReasonsOutgoingMacSpoofing,
virtualNetworkAdapterDropReasonsIncomingMacSpoofing,
virtualNetworkAdapterDropReasonsOutgoingIpsec,
virtualNetworkAdapterDropReasonsIncomingIpsec,
virtualNetworkAdapterDropReasonsOutgoingQos,
virtualNetworkAdapterDropReasonsIncomingQos,
virtualNetworkAdapterDropReasonsOutgoingFailedPvlanSetting,
virtualNetworkAdapterDropReasonsIncomingFailedPvlanSetting,
virtualNetworkAdapterDropReasonsOutgoingFailedSecurityPolicy,
virtualNetworkAdapterDropReasonsIncomingFailedSecurityPolicy,
virtualNetworkAdapterDropReasonsOutgoingUnauthorizedMAC,
virtualNetworkAdapterDropReasonsIncomingUnauthorizedMAC,
virtualNetworkAdapterDropReasonsOutgoingUnauthorizedVLAN,
virtualNetworkAdapterDropReasonsIncomingUnauthorizedVLAN,
virtualNetworkAdapterDropReasonsOutgoingFilteredVLAN,
virtualNetworkAdapterDropReasonsIncomingFilteredVLAN,
virtualNetworkAdapterDropReasonsOutgoingFiltered,
virtualNetworkAdapterDropReasonsIncomingFiltered,
virtualNetworkAdapterDropReasonsOutgoingBusy,
virtualNetworkAdapterDropReasonsIncomingBusy,
virtualNetworkAdapterDropReasonsOutgoingNotAccepted,
virtualNetworkAdapterDropReasonsIncomingNotAccepted,
virtualNetworkAdapterDropReasonsOutgoingDisconnected,
virtualNetworkAdapterDropReasonsIncomingDisconnected,
virtualNetworkAdapterDropReasonsOutgoingNotReady,
virtualNetworkAdapterDropReasonsIncomingNotReady,
virtualNetworkAdapterDropReasonsOutgoingResources,
virtualNetworkAdapterDropReasonsIncomingResources,
virtualNetworkAdapterDropReasonsOutgoingInvalidPacket,
virtualNetworkAdapterDropReasonsIncomingInvalidPacket,
virtualNetworkAdapterDropReasonsOutgoingInvalidData,
virtualNetworkAdapterDropReasonsIncomingInvalidData,
virtualNetworkAdapterDropReasonsOutgoingUnknown,
virtualNetworkAdapterDropReasonsIncomingUnknown,
})
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter Drop Reasons collector: %w", err)
}
c.virtualNetworkAdapterDropReasons = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_network_adapter_drop_reasons"),
"Hyper-V Virtual Network Adapter Drop Reasons",
[]string{"adapter", "reason", "direction"},
nil,
)
return nil
}
func (c *Collector) collectVirtualNetworkAdapterDropReasons(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualNetworkAdapterDropReasons.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to collect Hyper-V Virtual Network Adapter Drop Reasons metrics: %w", err)
}
for name, adapterData := range data {
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingNativeFwdingReq].FirstValue,
name, "NativeFwdingReq", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingNativeFwdingReq].FirstValue,
name, "NativeFwdingReq", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingMTUMismatch].FirstValue,
name, "MTUMismatch", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingMTUMismatch].FirstValue,
name, "MTUMismatch", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingInvalidConfig].FirstValue,
name, "InvalidConfig", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingInvalidConfig].FirstValue,
name, "InvalidConfig", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingRequiredExtensionMissing].FirstValue,
name, "RequiredExtensionMissing", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingRequiredExtensionMissing].FirstValue,
name, "RequiredExtensionMissing", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingVirtualSubnetId].FirstValue,
name, "VirtualSubnetId", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingVirtualSubnetId].FirstValue,
name, "VirtualSubnetId", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingBridgeReserved].FirstValue,
name, "BridgeReserved", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingBridgeReserved].FirstValue,
name, "BridgeReserved", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingRouterGuard].FirstValue,
name, "RouterGuard", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingRouterGuard].FirstValue,
name, "RouterGuard", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingDhcpGuard].FirstValue,
name, "DhcpGuard", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingDhcpGuard].FirstValue,
name, "DhcpGuard", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingMacSpoofing].FirstValue,
name, "MacSpoofing", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingMacSpoofing].FirstValue,
name, "MacSpoofing", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingIpsec].FirstValue,
name, "Ipsec", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingIpsec].FirstValue,
name, "Ipsec", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingQos].FirstValue,
name, "Qos", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingQos].FirstValue,
name, "Qos", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingFailedPvlanSetting].FirstValue,
name, "FailedPvlanSetting", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingFailedPvlanSetting].FirstValue,
name, "FailedPvlanSetting", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingFailedSecurityPolicy].FirstValue,
name, "FailedSecurityPolicy", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingFailedSecurityPolicy].FirstValue,
name, "FailedSecurityPolicy", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingUnauthorizedMAC].FirstValue,
name, "UnauthorizedMAC", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingUnauthorizedMAC].FirstValue,
name, "UnauthorizedMAC", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingUnauthorizedVLAN].FirstValue,
name, "UnauthorizedVLAN", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingUnauthorizedVLAN].FirstValue,
name, "UnauthorizedVLAN", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingFilteredVLAN].FirstValue,
name, "FilteredVLAN", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingFilteredVLAN].FirstValue,
name, "FilteredVLAN", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingFiltered].FirstValue,
name, "Filtered", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingFiltered].FirstValue,
name, "Filtered", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingBusy].FirstValue,
name, "Busy", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingBusy].FirstValue,
name, "Busy", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingNotAccepted].FirstValue,
name, "NotAccepted", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingNotAccepted].FirstValue,
name, "NotAccepted", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingDisconnected].FirstValue,
name, "Disconnected", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingDisconnected].FirstValue,
name, "Disconnected", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingNotReady].FirstValue,
name, "NotReady", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingNotReady].FirstValue,
name, "NotReady", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingResources].FirstValue,
name, "Resources", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingResources].FirstValue,
name, "Resources", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingInvalidPacket].FirstValue,
name, "InvalidPacket", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingInvalidPacket].FirstValue,
name, "InvalidPacket", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingInvalidData].FirstValue,
name, "InvalidData", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingInvalidData].FirstValue,
name, "InvalidData", "incoming",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsOutgoingUnknown].FirstValue,
name, "Unknown", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
adapterData[virtualNetworkAdapterDropReasonsIncomingUnknown].FirstValue,
name, "Unknown", "incoming",
)
}
return nil
}

View File

@@ -0,0 +1,315 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorVirtualSMB Hyper-V Virtual SMB metrics
type collectorVirtualSMB struct {
perfDataCollectorVirtualSMB *perfdata.Collector
virtualSMBDirectMappedSections *prometheus.Desc // \Hyper-V Virtual SMB(*)\Direct-Mapped Sections
virtualSMBDirectMappedPages *prometheus.Desc // \Hyper-V Virtual SMB(*)\Direct-Mapped Pages
virtualSMBWriteBytesRDMA *prometheus.Desc // \Hyper-V Virtual SMB(*)\Write Bytes/sec (RDMA)
virtualSMBWriteBytes *prometheus.Desc // \Hyper-V Virtual SMB(*)\Write Bytes/sec
virtualSMBReadBytesRDMA *prometheus.Desc // \Hyper-V Virtual SMB(*)\Read Bytes/sec (RDMA)
virtualSMBReadBytes *prometheus.Desc // \Hyper-V Virtual SMB(*)\Read Bytes/sec
virtualSMBFlushRequests *prometheus.Desc // \Hyper-V Virtual SMB(*)\Flush Requests/sec
virtualSMBWriteRequestsRDMA *prometheus.Desc // \Hyper-V Virtual SMB(*)\Write Requests/sec (RDMA)
virtualSMBWriteRequests *prometheus.Desc // \Hyper-V Virtual SMB(*)\Write Requests/sec
virtualSMBReadRequestsRDMA *prometheus.Desc // \Hyper-V Virtual SMB(*)\Read Requests/sec (RDMA)
virtualSMBReadRequests *prometheus.Desc // \Hyper-V Virtual SMB(*)\Read Requests/sec
virtualSMBCurrentPendingRequests *prometheus.Desc // \Hyper-V Virtual SMB(*)\Current Pending Requests
virtualSMBCurrentOpenFileCount *prometheus.Desc // \Hyper-V Virtual SMB(*)\Current Open File Count
virtualSMBTreeConnectCount *prometheus.Desc // \Hyper-V Virtual SMB(*)\Tree Connect Count
virtualSMBRequests *prometheus.Desc // \Hyper-V Virtual SMB(*)\Requests/sec
virtualSMBSentBytes *prometheus.Desc // \Hyper-V Virtual SMB(*)\Sent Bytes/sec
virtualSMBReceivedBytes *prometheus.Desc // \Hyper-V Virtual SMB(*)\Received Bytes/sec
}
const (
virtualSMBDirectMappedSections = "Direct-Mapped Sections"
virtualSMBDirectMappedPages = "Direct-Mapped Pages"
virtualSMBWriteBytesRDMA = "Write Bytes/sec (RDMA)"
virtualSMBWriteBytes = "Write Bytes/sec"
virtualSMBReadBytesRDMA = "Read Bytes/sec (RDMA)"
virtualSMBReadBytes = "Read Bytes/sec"
virtualSMBFlushRequests = "Flush Requests/sec"
virtualSMBWriteRequestsRDMA = "Write Requests/sec (RDMA)"
virtualSMBWriteRequests = "Write Requests/sec"
virtualSMBReadRequestsRDMA = "Read Requests/sec (RDMA)"
virtualSMBReadRequests = "Read Requests/sec"
virtualSMBCurrentPendingRequests = "Current Pending Requests"
virtualSMBCurrentOpenFileCount = "Current Open File Count"
virtualSMBTreeConnectCount = "Tree Connect Count"
virtualSMBRequests = "Requests/sec"
virtualSMBSentBytes = "Sent Bytes/sec"
virtualSMBReceivedBytes = "Received Bytes/sec"
)
func (c *Collector) buildVirtualSMB() error {
var err error
c.perfDataCollectorVirtualSMB, err = perfdata.NewCollector("Hyper-V Virtual SMB", perfdata.InstanceAll, []string{
virtualSMBDirectMappedSections,
virtualSMBDirectMappedPages,
virtualSMBWriteBytesRDMA,
virtualSMBWriteBytes,
virtualSMBReadBytesRDMA,
virtualSMBReadBytes,
virtualSMBFlushRequests,
virtualSMBWriteRequestsRDMA,
virtualSMBWriteRequests,
virtualSMBReadRequestsRDMA,
virtualSMBReadRequests,
virtualSMBCurrentPendingRequests,
virtualSMBCurrentOpenFileCount,
virtualSMBTreeConnectCount,
virtualSMBRequests,
virtualSMBSentBytes,
virtualSMBReceivedBytes,
})
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to create Hyper-V Virtual SMB collector: %w", err)
}
c.virtualSMBDirectMappedSections = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_direct_mapped_sections"),
"Represents the number of direct-mapped sections in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBDirectMappedPages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_direct_mapped_pages"),
"Represents the number of direct-mapped pages in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBWriteBytesRDMA = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_write_bytes_rdma"),
"Represents the number of bytes written per second using RDMA in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBWriteBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_write_bytes"),
"Represents the number of bytes written per second in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBReadBytesRDMA = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_read_bytes_rdma"),
"Represents the number of bytes read per second using RDMA in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBReadBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_read_bytes"),
"Represents the number of bytes read per second in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBFlushRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_flush_requests"),
"Represents the number of flush requests per second in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBWriteRequestsRDMA = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_write_requests_rdma"),
"Represents the number of write requests per second using RDMA in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBWriteRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_write_requests"),
"Represents the number of write requests per second in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBReadRequestsRDMA = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_read_requests_rdma"),
"Represents the number of read requests per second using RDMA in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBReadRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_read_requests"),
"Represents the number of read requests per second in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBCurrentPendingRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_current_pending_requests"),
"Represents the current number of pending requests in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBCurrentOpenFileCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_current_open_file_count"),
"Represents the current number of open files in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBTreeConnectCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_tree_connect_count"),
"Represents the number of tree connects in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_requests"),
"Represents the number of requests per second in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBSentBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_sent_bytes"),
"Represents the number of bytes sent per second in the virtual SMB",
[]string{"instance"},
nil,
)
c.virtualSMBReceivedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_smb_received_bytes"),
"Represents the number of bytes received per second in the virtual SMB",
[]string{"instance"},
nil,
)
return nil
}
func (c *Collector) collectVirtualSMB(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualSMB.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to collect Hyper-V Virtual SMB metrics: %w", err)
}
for name, smbData := range data {
ch <- prometheus.MustNewConstMetric(
c.virtualSMBDirectMappedSections,
prometheus.GaugeValue,
smbData[virtualSMBDirectMappedSections].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBDirectMappedPages,
prometheus.GaugeValue,
smbData[virtualSMBDirectMappedPages].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBWriteBytesRDMA,
prometheus.CounterValue,
smbData[virtualSMBWriteBytesRDMA].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBWriteBytes,
prometheus.CounterValue,
smbData[virtualSMBWriteBytes].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBReadBytesRDMA,
prometheus.CounterValue,
smbData[virtualSMBReadBytesRDMA].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBReadBytes,
prometheus.CounterValue,
smbData[virtualSMBReadBytes].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBFlushRequests,
prometheus.CounterValue,
smbData[virtualSMBFlushRequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBWriteRequestsRDMA,
prometheus.CounterValue,
smbData[virtualSMBWriteRequestsRDMA].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBWriteRequests,
prometheus.CounterValue,
smbData[virtualSMBWriteRequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBReadRequestsRDMA,
prometheus.CounterValue,
smbData[virtualSMBReadRequestsRDMA].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBReadRequests,
prometheus.CounterValue,
smbData[virtualSMBReadRequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBCurrentPendingRequests,
prometheus.GaugeValue,
smbData[virtualSMBCurrentPendingRequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBCurrentOpenFileCount,
prometheus.GaugeValue,
smbData[virtualSMBCurrentOpenFileCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBTreeConnectCount,
prometheus.GaugeValue,
smbData[virtualSMBTreeConnectCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBRequests,
prometheus.CounterValue,
smbData[virtualSMBRequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBSentBytes,
prometheus.CounterValue,
smbData[virtualSMBSentBytes].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSMBReceivedBytes,
prometheus.CounterValue,
smbData[virtualSMBReceivedBytes].FirstValue,
name,
)
}
return nil
}

View File

@@ -0,0 +1,235 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// Hyper-V Virtual Storage Device metrics
type collectorVirtualStorageDevice struct {
perfDataCollectorVirtualStorageDevice *perfdata.Collector
virtualStorageDeviceErrorCount *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Error Count
virtualStorageDeviceQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Queue Length
virtualStorageDeviceReadBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Bytes/sec
virtualStorageDeviceReadOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Read Operations/Sec
virtualStorageDeviceWriteBytes *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Bytes/sec
virtualStorageDeviceWriteOperations *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Write Operations/Sec
virtualStorageDeviceLatency *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Latency
virtualStorageDeviceThroughput *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Throughput
virtualStorageDeviceNormalizedThroughput *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Normalized Throughput
virtualStorageDeviceLowerQueueLength *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Lower Queue Length
virtualStorageDeviceLowerLatency *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\Lower Latency
virtualStorageDeviceIOQuotaReplenishmentRate *prometheus.Desc // \Hyper-V Virtual Storage Device(*)\IO Quota Replenishment Rate
}
const (
virtualStorageDeviceErrorCount = "Error Count"
virtualStorageDeviceQueueLength = "Queue Length"
virtualStorageDeviceReadBytes = "Read Bytes/sec"
virtualStorageDeviceReadOperations = "Read Count"
virtualStorageDeviceWriteBytes = "Write Bytes/sec"
virtualStorageDeviceWriteOperations = "Write Count"
virtualStorageDeviceLatency = "Latency"
virtualStorageDeviceThroughput = "Throughput"
virtualStorageDeviceNormalizedThroughput = "Normalized Throughput"
virtualStorageDeviceLowerQueueLength = "Lower Queue Length"
virtualStorageDeviceLowerLatency = "Lower Latency"
virtualStorageDeviceIOQuotaReplenishmentRate = "IO Quota Replenishment Rate"
)
func (c *Collector) buildVirtualStorageDevice() error {
var err error
c.perfDataCollectorVirtualStorageDevice, err = perfdata.NewCollector("Hyper-V Virtual Storage Device", perfdata.InstanceAll, []string{
virtualStorageDeviceErrorCount,
virtualStorageDeviceQueueLength,
virtualStorageDeviceReadBytes,
virtualStorageDeviceReadOperations,
virtualStorageDeviceWriteBytes,
virtualStorageDeviceWriteOperations,
virtualStorageDeviceLatency,
virtualStorageDeviceThroughput,
virtualStorageDeviceNormalizedThroughput,
virtualStorageDeviceLowerQueueLength,
virtualStorageDeviceLowerLatency,
virtualStorageDeviceIOQuotaReplenishmentRate,
})
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to create Hyper-V Virtual Storage Device collector: %w", err)
}
c.virtualStorageDeviceErrorCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_error_count_total"),
"Represents the total number of errors that have occurred on this virtual device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_queue_length"),
"Represents the average queue length on this virtual device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceReadBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_bytes_read"),
"Represents the total number of bytes that have been read on this virtual device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceReadOperations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_operations_read_total"),
"Represents the total number of read operations that have occurred on this virtual device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceWriteBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_bytes_written"),
"Represents the total number of bytes that have been written on this virtual device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceWriteOperations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_operations_written_total"),
"Represents the total number of write operations that have occurred on this virtual device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_latency_seconds"),
"Represents the average IO transfer latency for this virtual device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceThroughput = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_throughput"),
"Represents the average number of 8KB IO transfers completed by this virtual device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceNormalizedThroughput = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_normalized_throughput"),
"Represents the average number of IO transfers completed by this virtual device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceLowerQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_lower_queue_length"),
"Represents the average queue length on the underlying storage subsystem for this device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceLowerLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_lower_latency_seconds"),
"Represents the average IO transfer latency on the underlying storage subsystem for this virtual device.",
[]string{"device"},
nil,
)
c.virtualStorageDeviceIOQuotaReplenishmentRate = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "io_quota_replenishment_rate"),
"Represents the IO quota replenishment rate for this virtual device.",
[]string{"device"},
nil,
)
return nil
}
func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualStorageDevice.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to collect Hyper-V Virtual Storage Device metrics: %w", err)
}
for name, device := range data {
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceErrorCount,
prometheus.CounterValue,
device[virtualStorageDeviceErrorCount].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceQueueLength,
prometheus.GaugeValue,
device[virtualStorageDeviceQueueLength].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceReadBytes,
prometheus.CounterValue,
device[virtualStorageDeviceReadBytes].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceReadOperations,
prometheus.CounterValue,
device[virtualStorageDeviceReadOperations].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceWriteBytes,
prometheus.CounterValue,
device[virtualStorageDeviceWriteBytes].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceWriteOperations,
prometheus.CounterValue,
device[virtualStorageDeviceWriteOperations].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceLatency,
prometheus.GaugeValue,
device[virtualStorageDeviceLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceThroughput,
prometheus.GaugeValue,
device[virtualStorageDeviceThroughput].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceNormalizedThroughput,
prometheus.GaugeValue,
device[virtualStorageDeviceNormalizedThroughput].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceLowerQueueLength,
prometheus.GaugeValue,
device[virtualStorageDeviceLowerQueueLength].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceLowerLatency,
prometheus.GaugeValue,
device[virtualStorageDeviceLowerLatency].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceIOQuotaReplenishmentRate,
prometheus.GaugeValue,
device[virtualStorageDeviceIOQuotaReplenishmentRate].FirstValue,
name,
)
}
return nil
}

View File

@@ -0,0 +1,368 @@
package hyperv
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
// collectorVirtualMachineHealthSummary Hyper-V Virtual Switch Summary metrics
type collectorVirtualSwitch struct {
perfDataCollectorVirtualSwitch *perfdata.Collector
virtualSwitchBroadcastPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Broadcast Packets Received/sec
virtualSwitchBroadcastPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Broadcast Packets Sent/sec
virtualSwitchBytes *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes/sec
virtualSwitchBytesReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes Received/sec
virtualSwitchBytesSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Bytes Sent/sec
virtualSwitchDirectedPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Directed Packets Received/sec
virtualSwitchDirectedPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Directed Packets Sent/sec
virtualSwitchDroppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Switch(*)\Dropped Packets Incoming/sec
virtualSwitchDroppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Switch(*)\Dropped Packets Outgoing/sec
virtualSwitchExtensionsDroppedPacketsIncoming *prometheus.Desc // \Hyper-V Virtual Switch(*)\Extensions Dropped Packets Incoming/sec
virtualSwitchExtensionsDroppedPacketsOutgoing *prometheus.Desc // \Hyper-V Virtual Switch(*)\Extensions Dropped Packets Outgoing/sec
virtualSwitchLearnedMacAddresses *prometheus.Desc // \Hyper-V Virtual Switch(*)\Learned Mac Addresses
virtualSwitchMulticastPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Multicast Packets Received/sec
virtualSwitchMulticastPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Multicast Packets Sent/sec
virtualSwitchNumberOfSendChannelMoves *prometheus.Desc // \Hyper-V Virtual Switch(*)\Number of Send Channel Moves/sec
virtualSwitchNumberOfVMQMoves *prometheus.Desc // \Hyper-V Virtual Switch(*)\Number of VMQ Moves/sec
virtualSwitchPacketsFlooded *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Flooded
virtualSwitchPackets *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets/sec
virtualSwitchPacketsReceived *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Received/sec
virtualSwitchPacketsSent *prometheus.Desc // \Hyper-V Virtual Switch(*)\Packets Sent/sec
virtualSwitchPurgedMacAddresses *prometheus.Desc // \Hyper-V Virtual Switch(*)\Purged Mac Addresses
}
const (
virtualSwitchBroadcastPacketsReceived = "Broadcast Packets Received/sec"
virtualSwitchBroadcastPacketsSent = "Broadcast Packets Sent/sec"
virtualSwitchBytes = "Bytes/sec"
virtualSwitchBytesReceived = "Bytes Received/sec"
virtualSwitchBytesSent = "Bytes Sent/sec"
virtualSwitchDirectedPacketsReceived = "Directed Packets Received/sec"
virtualSwitchDirectedPacketsSent = "Directed Packets Sent/sec"
virtualSwitchDroppedPacketsIncoming = "Dropped Packets Incoming/sec"
virtualSwitchDroppedPacketsOutgoing = "Dropped Packets Outgoing/sec"
virtualSwitchExtensionsDroppedPacketsIncoming = "Extensions Dropped Packets Incoming/sec"
virtualSwitchExtensionsDroppedPacketsOutgoing = "Extensions Dropped Packets Outgoing/sec"
virtualSwitchLearnedMacAddresses = "Learned Mac Addresses"
virtualSwitchMulticastPacketsReceived = "Multicast Packets Received/sec"
virtualSwitchMulticastPacketsSent = "Multicast Packets Sent/sec"
virtualSwitchNumberOfSendChannelMoves = "Number of Send Channel Moves/sec"
virtualSwitchNumberOfVMQMoves = "Number of VMQ Moves/sec"
virtualSwitchPacketsFlooded = "Packets Flooded"
virtualSwitchPackets = "Packets/sec"
virtualSwitchPacketsReceived = "Packets Received/sec"
virtualSwitchPacketsSent = "Packets Sent/sec"
virtualSwitchPurgedMacAddresses = "Purged Mac Addresses"
)
func (c *Collector) buildVirtualSwitch() error {
var err error
c.perfDataCollectorVirtualSwitch, err = perfdata.NewCollector("Hyper-V Virtual Switch", perfdata.InstanceAll, []string{
virtualSwitchBroadcastPacketsReceived,
virtualSwitchBroadcastPacketsSent,
virtualSwitchBytes,
virtualSwitchBytesReceived,
virtualSwitchBytesSent,
virtualSwitchDirectedPacketsReceived,
virtualSwitchDirectedPacketsSent,
virtualSwitchDroppedPacketsIncoming,
virtualSwitchDroppedPacketsOutgoing,
virtualSwitchExtensionsDroppedPacketsIncoming,
virtualSwitchExtensionsDroppedPacketsOutgoing,
virtualSwitchLearnedMacAddresses,
virtualSwitchMulticastPacketsReceived,
virtualSwitchMulticastPacketsSent,
virtualSwitchNumberOfSendChannelMoves,
virtualSwitchNumberOfVMQMoves,
virtualSwitchPacketsFlooded,
virtualSwitchPackets,
virtualSwitchPacketsReceived,
virtualSwitchPacketsSent,
virtualSwitchPurgedMacAddresses,
})
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to create Hyper-V Virtual Switch collector: %w", err)
}
c.virtualSwitchBroadcastPacketsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_broadcast_packets_received_total"),
"Represents the total number of broadcast packets received per second by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchBroadcastPacketsSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_broadcast_packets_sent_total"),
"Represents the total number of broadcast packets sent per second by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_total"),
"Represents the total number of bytes per second traversing the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchBytesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_received_total"),
"Represents the total number of bytes received per second by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchBytesSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_bytes_sent_total"),
"Represents the total number of bytes sent per second by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchDirectedPacketsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_directed_packets_received_total"),
"Represents the total number of directed packets received per second by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchDirectedPacketsSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_directed_packets_send_total"),
"Represents the total number of directed packets sent per second by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchDroppedPacketsIncoming = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_dropped_packets_incoming_total"),
"Represents the total number of packet dropped per second by the virtual switch in the incoming direction",
[]string{"vswitch"},
nil,
)
c.virtualSwitchDroppedPacketsOutgoing = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_dropped_packets_outcoming_total"),
"Represents the total number of packet dropped per second by the virtual switch in the outgoing direction",
[]string{"vswitch"},
nil,
)
c.virtualSwitchExtensionsDroppedPacketsIncoming = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_extensions_dropped_packets_incoming_total"),
"Represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction",
[]string{"vswitch"},
nil,
)
c.virtualSwitchExtensionsDroppedPacketsOutgoing = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_extensions_dropped_packets_outcoming_total"),
"Represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction",
[]string{"vswitch"},
nil,
)
c.virtualSwitchLearnedMacAddresses = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_learned_mac_addresses_total"),
"Represents the total number of learned MAC addresses of the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchMulticastPacketsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_multicast_packets_received_total"),
"Represents the total number of multicast packets received per second by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchMulticastPacketsSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_multicast_packets_sent_total"),
"Represents the total number of multicast packets sent per second by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchNumberOfSendChannelMoves = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_number_of_send_channel_moves_total"),
"Represents the total number of send channel moves per second on this virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchNumberOfVMQMoves = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_number_of_vmq_moves_total"),
"Represents the total number of VMQ moves per second on this virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchPacketsFlooded = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_flooded_total"),
"Represents the total number of packets flooded by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchPackets = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_total"),
"Represents the total number of packets per second traversing the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchPacketsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_received_total"),
"Represents the total number of packets received per second by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchPacketsSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_packets_sent_total"),
"Represents the total number of packets send per second by the virtual switch",
[]string{"vswitch"},
nil,
)
c.virtualSwitchPurgedMacAddresses = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "vswitch_purged_mac_addresses_total"),
"Represents the total number of purged MAC addresses of the virtual switch",
[]string{"vswitch"},
nil,
)
return nil
}
func (c *Collector) collectVirtualSwitch(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualSwitch.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) {
return fmt.Errorf("failed to collect Hyper-V Virtual Switch metrics: %w", err)
}
for name, switchData := range data {
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchBroadcastPacketsReceived,
prometheus.CounterValue,
switchData[virtualSwitchBroadcastPacketsReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchBroadcastPacketsSent,
prometheus.CounterValue,
switchData[virtualSwitchBroadcastPacketsSent].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchBytes,
prometheus.CounterValue,
switchData[virtualSwitchBytes].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchBytesReceived,
prometheus.CounterValue,
switchData[virtualSwitchBytesReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchBytesSent,
prometheus.CounterValue,
switchData[virtualSwitchBytesSent].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchDirectedPacketsReceived,
prometheus.CounterValue,
switchData[virtualSwitchDirectedPacketsReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchDirectedPacketsSent,
prometheus.CounterValue,
switchData[virtualSwitchDirectedPacketsSent].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchDroppedPacketsIncoming,
prometheus.CounterValue,
switchData[virtualSwitchDroppedPacketsIncoming].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchDroppedPacketsOutgoing,
prometheus.CounterValue,
switchData[virtualSwitchDroppedPacketsOutgoing].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchExtensionsDroppedPacketsIncoming,
prometheus.CounterValue,
switchData[virtualSwitchExtensionsDroppedPacketsIncoming].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchExtensionsDroppedPacketsOutgoing,
prometheus.CounterValue,
switchData[virtualSwitchExtensionsDroppedPacketsOutgoing].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchLearnedMacAddresses,
prometheus.CounterValue,
switchData[virtualSwitchLearnedMacAddresses].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchMulticastPacketsReceived,
prometheus.CounterValue,
switchData[virtualSwitchMulticastPacketsReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchMulticastPacketsSent,
prometheus.CounterValue,
switchData[virtualSwitchMulticastPacketsSent].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchNumberOfSendChannelMoves,
prometheus.CounterValue,
switchData[virtualSwitchNumberOfSendChannelMoves].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchNumberOfVMQMoves,
prometheus.CounterValue,
switchData[virtualSwitchNumberOfVMQMoves].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchPacketsFlooded,
prometheus.CounterValue,
switchData[virtualSwitchPacketsFlooded].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchPackets,
prometheus.CounterValue,
switchData[virtualSwitchPackets].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchPacketsReceived,
prometheus.CounterValue,
switchData[virtualSwitchPacketsReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchPacketsSent,
prometheus.CounterValue,
switchData[virtualSwitchPacketsSent].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.virtualSwitchPurgedMacAddresses,
prometheus.CounterValue,
switchData[virtualSwitchPurgedMacAddresses].FirstValue,
name,
)
}
return nil
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,265 @@
//go:build windows
package iis
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
type collectorAppPoolWAS struct {
perfDataCollectorAppPoolWAS *perfdata.Collector
currentApplicationPoolState *prometheus.Desc
currentApplicationPoolUptime *prometheus.Desc
currentWorkerProcesses *prometheus.Desc
maximumWorkerProcesses *prometheus.Desc
recentWorkerProcessFailures *prometheus.Desc
timeSinceLastWorkerProcessFailure *prometheus.Desc
totalApplicationPoolRecycles *prometheus.Desc
totalApplicationPoolUptime *prometheus.Desc
totalWorkerProcessesCreated *prometheus.Desc
totalWorkerProcessFailures *prometheus.Desc
totalWorkerProcessPingFailures *prometheus.Desc
totalWorkerProcessShutdownFailures *prometheus.Desc
totalWorkerProcessStartupFailures *prometheus.Desc
}
const (
CurrentApplicationPoolState = "Current Application Pool State"
CurrentApplicationPoolUptime = "Current Application Pool Uptime"
CurrentWorkerProcesses = "Current Worker Processes"
MaximumWorkerProcesses = "Maximum Worker Processes"
RecentWorkerProcessFailures = "Recent Worker Process Failures"
TimeSinceLastWorkerProcessFailure = "Time Since Last Worker Process Failure"
TotalApplicationPoolRecycles = "Total Application Pool Recycles"
TotalApplicationPoolUptime = "Total Application Pool Uptime"
TotalWorkerProcessesCreated = "Total Worker Processes Created"
TotalWorkerProcessFailures = "Total Worker Process Failures"
TotalWorkerProcessPingFailures = "Total Worker Process Ping Failures"
TotalWorkerProcessShutdownFailures = "Total Worker Process Shutdown Failures"
TotalWorkerProcessStartupFailures = "Total Worker Process Startup Failures"
)
var applicationStates = map[uint32]string{
1: "Uninitialized",
2: "Initialized",
3: "Running",
4: "Disabling",
5: "Disabled",
6: "Shutdown Pending",
7: "Delete Pending",
}
func (c *Collector) buildAppPoolWAS() error {
var err error
c.perfDataCollectorAppPoolWAS, err = perfdata.NewCollector("APP_POOL_WAS", perfdata.InstanceAll, []string{
CurrentApplicationPoolState,
CurrentApplicationPoolUptime,
CurrentWorkerProcesses,
MaximumWorkerProcesses,
RecentWorkerProcessFailures,
TimeSinceLastWorkerProcessFailure,
TotalApplicationPoolRecycles,
TotalApplicationPoolUptime,
TotalWorkerProcessesCreated,
TotalWorkerProcessFailures,
TotalWorkerProcessPingFailures,
TotalWorkerProcessShutdownFailures,
TotalWorkerProcessStartupFailures,
})
if err != nil {
return fmt.Errorf("failed to create APP_POOL_WAS collector: %w", err)
}
// APP_POOL_WAS
c.currentApplicationPoolState = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_application_pool_state"),
"The current status of the application pool (1 - Uninitialized, 2 - Initialized, 3 - Running, 4 - Disabling, 5 - Disabled, 6 - Shutdown Pending, 7 - Delete Pending) (CurrentApplicationPoolState)",
[]string{"app", "state"},
nil,
)
c.currentApplicationPoolUptime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_application_pool_start_time"),
"The unix timestamp for the application pool start time (CurrentApplicationPoolUptime)",
[]string{"app"},
nil,
)
c.currentWorkerProcesses = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_worker_processes"),
"The current number of worker processes that are running in the application pool (CurrentWorkerProcesses)",
[]string{"app"},
nil,
)
c.maximumWorkerProcesses = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "maximum_worker_processes"),
"The maximum number of worker processes that have been created for the application pool since Windows Process Activation Service (WAS) started (MaximumWorkerProcesses)",
[]string{"app"},
nil,
)
c.recentWorkerProcessFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "recent_worker_process_failures"),
"The number of times that worker processes for the application pool failed during the rapid-fail protection interval (RecentWorkerProcessFailures)",
[]string{"app"},
nil,
)
c.timeSinceLastWorkerProcessFailure = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "time_since_last_worker_process_failure"),
"The length of time, in seconds, since the last worker process failure occurred for the application pool (TimeSinceLastWorkerProcessFailure)",
[]string{"app"},
nil,
)
c.totalApplicationPoolRecycles = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "total_application_pool_recycles"),
"The number of times that the application pool has been recycled since Windows Process Activation Service (WAS) started (TotalApplicationPoolRecycles)",
[]string{"app"},
nil,
)
c.totalApplicationPoolUptime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "total_application_pool_start_time"),
"The unix timestamp for the application pool of when the Windows Process Activation Service (WAS) started (TotalApplicationPoolUptime)",
[]string{"app"},
nil,
)
c.totalWorkerProcessesCreated = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "total_worker_processes_created"),
"The number of worker processes created for the application pool since Windows Process Activation Service (WAS) started (TotalWorkerProcessesCreated)",
[]string{"app"},
nil,
)
c.totalWorkerProcessFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "total_worker_process_failures"),
"The number of times that worker processes have crashed since the application pool was started (TotalWorkerProcessFailures)",
[]string{"app"},
nil,
)
c.totalWorkerProcessPingFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "total_worker_process_ping_failures"),
"The number of times that Windows Process Activation Service (WAS) did not receive a response to ping messages sent to a worker process (TotalWorkerProcessPingFailures)",
[]string{"app"},
nil,
)
c.totalWorkerProcessShutdownFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "total_worker_process_shutdown_failures"),
"The number of times that Windows Process Activation Service (WAS) failed to shut down a worker process (TotalWorkerProcessShutdownFailures)",
[]string{"app"},
nil,
)
c.totalWorkerProcessStartupFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "total_worker_process_startup_failures"),
"The number of times that Windows Process Activation Service (WAS) failed to start a worker process (TotalWorkerProcessStartupFailures)",
[]string{"app"},
nil,
)
return nil
}
func (c *Collector) collectAppPoolWAS(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorWebService.Collect()
if err != nil {
return fmt.Errorf("failed to collect APP_POOL_WAS metrics: %w", err)
}
deduplicateIISNames(perfData)
for name, app := range perfData {
if c.config.AppExclude.MatchString(name) || !c.config.AppInclude.MatchString(name) {
continue
}
for key, label := range applicationStates {
isCurrentState := 0.0
if key == uint32(app[CurrentApplicationPoolState].FirstValue) {
isCurrentState = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.currentApplicationPoolState,
prometheus.GaugeValue,
isCurrentState,
name,
label,
)
}
ch <- prometheus.MustNewConstMetric(
c.currentApplicationPoolUptime,
prometheus.GaugeValue,
app[CurrentApplicationPoolUptime].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.currentWorkerProcesses,
prometheus.GaugeValue,
app[CurrentWorkerProcesses].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.maximumWorkerProcesses,
prometheus.GaugeValue,
app[MaximumWorkerProcesses].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.recentWorkerProcessFailures,
prometheus.GaugeValue,
app[RecentWorkerProcessFailures].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.timeSinceLastWorkerProcessFailure,
prometheus.GaugeValue,
app[TimeSinceLastWorkerProcessFailure].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalApplicationPoolRecycles,
prometheus.CounterValue,
app[TotalApplicationPoolRecycles].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalApplicationPoolUptime,
prometheus.CounterValue,
app[TotalApplicationPoolUptime].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalWorkerProcessesCreated,
prometheus.CounterValue,
app[TotalWorkerProcessesCreated].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalWorkerProcessFailures,
prometheus.CounterValue,
app[TotalWorkerProcessFailures].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalWorkerProcessPingFailures,
prometheus.CounterValue,
app[TotalWorkerProcessPingFailures].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalWorkerProcessShutdownFailures,
prometheus.CounterValue,
app[TotalWorkerProcessShutdownFailures].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalWorkerProcessStartupFailures,
prometheus.CounterValue,
app[TotalWorkerProcessStartupFailures].FirstValue,
name,
)
}
return nil
}

View File

@@ -1,10 +1,12 @@
//go:build windows
package iis_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/iis"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,47 +0,0 @@
package iis
import (
"reflect"
"testing"
)
func TestIISDeduplication(t *testing.T) {
t.Parallel()
start := []perflibAPP_POOL_WAS{
{
Name: "foo",
Frequency_Object: 1,
},
{
Name: "foo1#999",
Frequency_Object: 2,
},
{
Name: "foo#2",
Frequency_Object: 3,
},
{
Name: "bar$2",
Frequency_Object: 4,
},
{
Name: "bar_2",
Frequency_Object: 5,
},
}
expected := make(map[string]perflibAPP_POOL_WAS)
// Should be deduplicated from "foo#2"
expected["foo"] = perflibAPP_POOL_WAS{Name: "foo#2", Frequency_Object: 3}
// Map key should have suffix stripped, but struct name field should be unchanged
expected["foo1"] = perflibAPP_POOL_WAS{Name: "foo1#999", Frequency_Object: 2}
// Map key and Name should be identical, as there is no suffix starting with "#"
expected["bar$2"] = perflibAPP_POOL_WAS{Name: "bar$2", Frequency_Object: 4}
// Map key and Name should be identical, as there is no suffix starting with "#"
expected["bar_2"] = perflibAPP_POOL_WAS{Name: "bar_2", Frequency_Object: 5}
deduplicated := dedupIISNames(start)
if !reflect.DeepEqual(expected, deduplicated) {
t.Errorf("Flattened values do not match!\nExpected result: %+v\nActual result: %+v", expected, deduplicated)
}
}

View File

@@ -0,0 +1,745 @@
//go:build windows
package iis
import (
"fmt"
"regexp"
"strings"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
type collectorW3SVCW3WP struct {
perfDataCollectorW3SVCW3WP *perfdata.Collector
// W3SVC_W3WP
threads *prometheus.Desc
maximumThreads *prometheus.Desc
requestsTotal *prometheus.Desc
requestsActive *prometheus.Desc
activeFlushedEntries *prometheus.Desc
currentFileCacheMemoryUsage *prometheus.Desc
maximumFileCacheMemoryUsage *prometheus.Desc
fileCacheFlushesTotal *prometheus.Desc
fileCacheQueriesTotal *prometheus.Desc
fileCacheHitsTotal *prometheus.Desc
filesCached *prometheus.Desc
filesCachedTotal *prometheus.Desc
filesFlushedTotal *prometheus.Desc
uriCacheFlushesTotal *prometheus.Desc
uriCacheQueriesTotal *prometheus.Desc
uriCacheHitsTotal *prometheus.Desc
urisCached *prometheus.Desc
urisCachedTotal *prometheus.Desc
urisFlushedTotal *prometheus.Desc
metadataCached *prometheus.Desc
metadataCacheFlushes *prometheus.Desc
metadataCacheQueriesTotal *prometheus.Desc
metadataCacheHitsTotal *prometheus.Desc
metadataCachedTotal *prometheus.Desc
metadataFlushedTotal *prometheus.Desc
outputCacheActiveFlushedItems *prometheus.Desc
outputCacheItems *prometheus.Desc
outputCacheMemoryUsage *prometheus.Desc
outputCacheQueriesTotal *prometheus.Desc
outputCacheHitsTotal *prometheus.Desc
outputCacheFlushedItemsTotal *prometheus.Desc
outputCacheFlushesTotal *prometheus.Desc
// IIS 8+ Only
requestErrorsTotal *prometheus.Desc
webSocketRequestsActive *prometheus.Desc
webSocketConnectionAttempts *prometheus.Desc
webSocketConnectionsAccepted *prometheus.Desc
webSocketConnectionsRejected *prometheus.Desc
}
var workerProcessNameExtractor = regexp.MustCompile(`^(\d+)_(.+)$`)
const (
Threads = "Active Threads Count"
MaximumThreads = "Maximum Threads Count"
RequestsTotal = "Total HTTP Requests Served"
RequestsActive = "Active Requests"
ActiveFlushedEntries = "Active Flushed Entries"
CurrentFileCacheMemoryUsage = "Current File Cache Memory Usage"
MaximumFileCacheMemoryUsage = "Maximum File Cache Memory Usage"
FileCacheFlushesTotal = "File Cache Flushes"
FileCacheHitsTotal = "File Cache Hits"
FileCacheMissesTotal = "File Cache Misses"
FilesCached = "Current Files Cached"
FilesCachedTotal = "Total Files Cached"
FilesFlushedTotal = "Total Flushed Files"
URICacheFlushesTotal = "Total Flushed URIs"
URICacheFlushesTotalKernel = "Total Flushed URIs"
URIsFlushedTotalKernel = "Kernel: Total Flushed URIs"
URICacheHitsTotal = "URI Cache Hits"
URICacheHitsTotalKernel = "Kernel: URI Cache Hits"
URICacheMissesTotal = "URI Cache Misses"
URICacheMissesTotalKernel = "Kernel: URI Cache Misses"
URIsCached = "Current URIs Cached"
URIsCachedKernel = "Kernel: Current URIs Cached"
URIsCachedTotal = "Total URIs Cached"
URIsCachedTotalKernel = "Total URIs Cached"
URIsFlushedTotal = "Total Flushed URIs"
MetaDataCacheHits = "Metadata Cache Hits"
MetaDataCacheMisses = "Metadata Cache Misses"
MetadataCached = "Current Metadata Cached"
MetadataCacheFlushes = "Metadata Cache Flushes"
MetadataCachedTotal = "Total Metadata Cached"
MetadataFlushedTotal = "Total Flushed Metadata"
OutputCacheActiveFlushedItems = "Output Cache Current Flushed Items"
OutputCacheItems = "Output Cache Current Items"
OutputCacheMemoryUsage = "Output Cache Current Memory Usage"
OutputCacheHitsTotal = "Output Cache Total Hits"
OutputCacheMissesTotal = "Output Cache Total Misses"
OutputCacheFlushedItemsTotal = "Output Cache Total Flushed Items"
OutputCacheFlushesTotal = "Output Cache Total Flushes"
// IIS8
RequestErrors500 = "% 500 HTTP Response Sent"
RequestErrors503 = "% 503 HTTP Response Sent"
RequestErrors404 = "% 404 HTTP Response Sent"
RequestErrors403 = "% 403 HTTP Response Sent"
RequestErrors401 = "% 401 HTTP Response Sent"
WebSocketRequestsActive = "WebSocket Active Requests"
WebSocketConnectionAttempts = "WebSocket Connection Attempts / Sec"
WebSocketConnectionsAccepted = "WebSocket Connections Accepted / Sec"
WebSocketConnectionsRejected = "WebSocket Connections Rejected / Sec"
)
func (c *Collector) buildW3SVCW3WP() error {
counters := []string{
Threads,
MaximumThreads,
RequestsTotal,
RequestsActive,
ActiveFlushedEntries,
CurrentFileCacheMemoryUsage,
MaximumFileCacheMemoryUsage,
FileCacheFlushesTotal,
FileCacheHitsTotal,
FileCacheMissesTotal,
FilesCached,
FilesCachedTotal,
FilesFlushedTotal,
URICacheFlushesTotal,
URICacheFlushesTotalKernel,
URIsFlushedTotalKernel,
URICacheHitsTotal,
URICacheHitsTotalKernel,
URICacheMissesTotal,
URICacheMissesTotalKernel,
URIsCached,
URIsCachedKernel,
URIsCachedTotal,
URIsCachedTotalKernel,
URIsFlushedTotal,
MetaDataCacheHits,
MetaDataCacheMisses,
MetadataCached,
MetadataCacheFlushes,
MetadataCachedTotal,
MetadataFlushedTotal,
OutputCacheActiveFlushedItems,
OutputCacheItems,
OutputCacheMemoryUsage,
OutputCacheHitsTotal,
OutputCacheMissesTotal,
OutputCacheFlushedItemsTotal,
OutputCacheFlushesTotal,
}
if c.iisVersion.major >= 8 {
counters = append(counters, []string{
RequestErrors500,
RequestErrors503,
RequestErrors404,
RequestErrors403,
RequestErrors401,
WebSocketRequestsActive,
WebSocketConnectionAttempts,
WebSocketConnectionsAccepted,
WebSocketConnectionsRejected,
}...)
}
var err error
c.perfDataCollectorW3SVCW3WP, err = perfdata.NewCollector("W3SVC_W3WP", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create W3SVC_W3WP collector: %w", err)
}
// W3SVC_W3WP
c.threads = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_threads"),
"Number of threads actively processing requests in the worker process",
[]string{"app", "pid", "state"},
nil,
)
c.maximumThreads = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_max_threads"),
"Maximum number of threads to which the thread pool can grow as needed",
[]string{"app", "pid"},
nil,
)
c.requestsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_requests_total"),
"Total number of HTTP requests served by the worker process",
[]string{"app", "pid"},
nil,
)
c.requestsActive = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_current_requests"),
"Current number of requests being processed by the worker process",
[]string{"app", "pid"},
nil,
)
c.activeFlushedEntries = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_cache_active_flushed_entries"),
"Number of file handles cached in user-mode that will be closed when all current transfers complete.",
[]string{"app", "pid"},
nil,
)
c.currentFileCacheMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_memory_bytes"),
"Current number of bytes used by user-mode file cache",
[]string{"app", "pid"},
nil,
)
c.maximumFileCacheMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_max_memory_bytes"),
"Maximum number of bytes used by user-mode file cache",
[]string{"app", "pid"},
nil,
)
c.fileCacheFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_flushes_total"),
"Total number of files removed from the user-mode cache",
[]string{"app", "pid"},
nil,
)
c.fileCacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_queries_total"),
"Total file cache queries (hits + misses)",
[]string{"app", "pid"},
nil,
)
c.fileCacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_hits_total"),
"Total number of successful lookups in the user-mode file cache",
[]string{"app", "pid"},
nil,
)
c.filesCached = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_items"),
"Current number of files whose contents are present in user-mode cache",
[]string{"app", "pid"},
nil,
)
c.filesCachedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_items_total"),
"Total number of files whose contents were ever added to the user-mode cache (since service startup)",
[]string{"app", "pid"},
nil,
)
c.filesFlushedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_items_flushed_total"),
"Total number of file handles that have been removed from the user-mode cache (since service startup)",
[]string{"app", "pid"},
nil,
)
c.uriCacheFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_flushes_total"),
"Total number of URI cache flushes (since service startup)",
[]string{"app", "pid"},
nil,
)
c.uriCacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_queries_total"),
"Total number of uri cache queries (hits + misses)",
[]string{"app", "pid"},
nil,
)
c.uriCacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_hits_total"),
"Total number of successful lookups in the user-mode URI cache (since service startup)",
[]string{"app", "pid"},
nil,
)
c.urisCached = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_items"),
"Number of URI information blocks currently in the user-mode cache",
[]string{"app", "pid"},
nil,
)
c.urisCachedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_items_total"),
"Total number of URI information blocks added to the user-mode cache (since service startup)",
[]string{"app", "pid"},
nil,
)
c.urisFlushedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_items_flushed_total"),
"The number of URI information blocks that have been removed from the user-mode cache (since service startup)",
[]string{"app", "pid"},
nil,
)
c.metadataCached = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_items"),
"Number of metadata information blocks currently present in user-mode cache",
[]string{"app", "pid"},
nil,
)
c.metadataCacheFlushes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_flushes_total"),
"Total number of user-mode metadata cache flushes (since service startup)",
[]string{"app", "pid"},
nil,
)
c.metadataCacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_queries_total"),
"Total metadata cache queries (hits + misses)",
[]string{"app", "pid"},
nil,
)
c.metadataCacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_hits_total"),
"Total number of successful lookups in the user-mode metadata cache (since service startup)",
[]string{"app", "pid"},
nil,
)
c.metadataCachedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_items_cached_total"),
"Total number of metadata information blocks added to the user-mode cache (since service startup)",
[]string{"app", "pid"},
nil,
)
c.metadataFlushedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_items_flushed_total"),
"Total number of metadata information blocks removed from the user-mode cache (since service startup)",
[]string{"app", "pid"},
nil,
)
c.outputCacheActiveFlushedItems = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_active_flushed_items"),
"",
[]string{"app", "pid"},
nil,
)
c.outputCacheItems = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_items"),
"Number of items current present in output cache",
[]string{"app", "pid"},
nil,
)
c.outputCacheMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_memory_bytes"),
"Current number of bytes used by output cache",
[]string{"app", "pid"},
nil,
)
c.outputCacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_queries_total"),
"Total number of output cache queries (hits + misses)",
[]string{"app", "pid"},
nil,
)
c.outputCacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_hits_total"),
"Total number of successful lookups in output cache (since service startup)",
[]string{"app", "pid"},
nil,
)
c.outputCacheFlushedItemsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_items_flushed_total"),
"Total number of items flushed from output cache (since service startup)",
[]string{"app", "pid"},
nil,
)
c.outputCacheFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_flushes_total"),
"Total number of flushes of output cache (since service startup)",
[]string{"app", "pid"},
nil,
)
// W3SVC_W3WP_IIS8
c.requestErrorsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_request_errors_total"),
"Total number of requests that returned an error",
[]string{"app", "pid", "status_code"},
nil,
)
c.webSocketRequestsActive = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_current_websocket_requests"),
"",
[]string{"app", "pid"},
nil,
)
c.webSocketConnectionAttempts = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_attempts_total"),
"",
[]string{"app", "pid"},
nil,
)
c.webSocketConnectionsAccepted = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_accepted_total"),
"",
[]string{"app", "pid"},
nil,
)
c.webSocketConnectionsRejected = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_rejected_total"),
"",
[]string{"app", "pid"},
nil,
)
return nil
}
func (c *Collector) collectW3SVCW3WP(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorW3SVCW3WP.Collect()
if err != nil {
return fmt.Errorf("failed to collect APP_POOL_WAS metrics: %w", err)
}
deduplicateIISNames(perfData)
for name, app := range perfData {
if c.config.AppExclude.MatchString(name) || !c.config.AppInclude.MatchString(name) {
continue
}
// Extract the apppool name from the format <PID>_<NAME>
pid := workerProcessNameExtractor.ReplaceAllString(name, "$1")
name := workerProcessNameExtractor.ReplaceAllString(name, "$2")
if name == "" || name == "_Total" ||
c.config.AppExclude.MatchString(name) ||
!c.config.AppInclude.MatchString(name) {
continue
}
// Duplicate instances are suffixed # with an index number. These should be ignored
if strings.Contains(name, "#") {
continue
}
ch <- prometheus.MustNewConstMetric(
c.threads,
prometheus.GaugeValue,
app[Threads].FirstValue,
name,
pid,
"busy",
)
ch <- prometheus.MustNewConstMetric(
c.maximumThreads,
prometheus.CounterValue,
app[MaximumThreads].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.requestsTotal,
prometheus.CounterValue,
app[RequestsTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.requestsActive,
prometheus.CounterValue,
app[RequestsActive].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.activeFlushedEntries,
prometheus.GaugeValue,
app[ActiveFlushedEntries].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.currentFileCacheMemoryUsage,
prometheus.GaugeValue,
app[CurrentFileCacheMemoryUsage].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.maximumFileCacheMemoryUsage,
prometheus.CounterValue,
app[MaximumFileCacheMemoryUsage].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.fileCacheFlushesTotal,
prometheus.CounterValue,
app[FileCacheFlushesTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.fileCacheQueriesTotal,
prometheus.CounterValue,
app[FileCacheHitsTotal].FirstValue+app[FileCacheMissesTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.fileCacheHitsTotal,
prometheus.CounterValue,
app[FileCacheHitsTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.filesCached,
prometheus.GaugeValue,
app[FilesCached].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.filesCachedTotal,
prometheus.CounterValue,
app[FilesCachedTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.filesFlushedTotal,
prometheus.CounterValue,
app[FilesFlushedTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.uriCacheFlushesTotal,
prometheus.CounterValue,
app[URICacheFlushesTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.uriCacheQueriesTotal,
prometheus.CounterValue,
app[URICacheHitsTotal].FirstValue+app[URICacheMissesTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.uriCacheHitsTotal,
prometheus.CounterValue,
app[URICacheHitsTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.urisCached,
prometheus.GaugeValue,
app[URIsCached].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.urisCachedTotal,
prometheus.CounterValue,
app[URIsCachedTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.urisFlushedTotal,
prometheus.CounterValue,
app[URIsFlushedTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.metadataCached,
prometheus.GaugeValue,
app[MetadataCached].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.metadataCacheFlushes,
prometheus.CounterValue,
app[MetadataCacheFlushes].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.metadataCacheQueriesTotal,
prometheus.CounterValue,
app[MetaDataCacheHits].FirstValue+app[MetaDataCacheMisses].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.metadataCacheHitsTotal,
prometheus.CounterValue,
app[MetaDataCacheHits].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.metadataCachedTotal,
prometheus.CounterValue,
app[MetadataCachedTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.metadataFlushedTotal,
prometheus.CounterValue,
app[MetadataFlushedTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.outputCacheActiveFlushedItems,
prometheus.CounterValue,
app[OutputCacheActiveFlushedItems].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.outputCacheItems,
prometheus.CounterValue,
app[OutputCacheItems].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.outputCacheMemoryUsage,
prometheus.CounterValue,
app[OutputCacheMemoryUsage].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.outputCacheQueriesTotal,
prometheus.CounterValue,
app[OutputCacheHitsTotal].FirstValue+app[OutputCacheMissesTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.outputCacheHitsTotal,
prometheus.CounterValue,
app[OutputCacheHitsTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.outputCacheFlushedItemsTotal,
prometheus.CounterValue,
app[OutputCacheFlushedItemsTotal].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.outputCacheFlushesTotal,
prometheus.CounterValue,
app[OutputCacheFlushesTotal].FirstValue,
name,
pid,
)
if c.iisVersion.major >= 8 {
ch <- prometheus.MustNewConstMetric(
c.requestErrorsTotal,
prometheus.CounterValue,
app[RequestErrors401].FirstValue,
name,
pid,
"401",
)
ch <- prometheus.MustNewConstMetric(
c.requestErrorsTotal,
prometheus.CounterValue,
app[RequestErrors403].FirstValue,
name,
pid,
"403",
)
ch <- prometheus.MustNewConstMetric(
c.requestErrorsTotal,
prometheus.CounterValue,
app[RequestErrors404].FirstValue,
name,
pid,
"404",
)
ch <- prometheus.MustNewConstMetric(
c.requestErrorsTotal,
prometheus.CounterValue,
app[RequestErrors500].FirstValue,
name,
pid,
"500",
)
ch <- prometheus.MustNewConstMetric(
c.requestErrorsTotal,
prometheus.CounterValue,
app[RequestErrors503].FirstValue,
name,
pid,
"503",
)
ch <- prometheus.MustNewConstMetric(
c.webSocketRequestsActive,
prometheus.CounterValue,
app[WebSocketRequestsActive].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.webSocketConnectionAttempts,
prometheus.CounterValue,
app[WebSocketConnectionAttempts].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.webSocketConnectionsAccepted,
prometheus.CounterValue,
app[WebSocketConnectionsAccepted].FirstValue,
name,
pid,
)
ch <- prometheus.MustNewConstMetric(
c.webSocketConnectionsRejected,
prometheus.CounterValue,
app[WebSocketConnectionsRejected].FirstValue,
name,
pid,
)
}
}
return nil
}

View File

@@ -0,0 +1,516 @@
//go:build windows
package iis
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
type collectorWebService struct {
perfDataCollectorWebService *perfdata.Collector
currentAnonymousUsers *prometheus.Desc
currentBlockedAsyncIORequests *prometheus.Desc
currentCGIRequests *prometheus.Desc
currentConnections *prometheus.Desc
currentISAPIExtensionRequests *prometheus.Desc
currentNonAnonymousUsers *prometheus.Desc
serviceUptime *prometheus.Desc
totalBytesReceived *prometheus.Desc
totalBytesSent *prometheus.Desc
totalAnonymousUsers *prometheus.Desc
totalBlockedAsyncIORequests *prometheus.Desc
totalCGIRequests *prometheus.Desc
totalConnectionAttemptsAllInstances *prometheus.Desc
totalRequests *prometheus.Desc
totalFilesReceived *prometheus.Desc
totalFilesSent *prometheus.Desc
totalISAPIExtensionRequests *prometheus.Desc
totalLockedErrors *prometheus.Desc
totalLogonAttempts *prometheus.Desc
totalNonAnonymousUsers *prometheus.Desc
totalNotFoundErrors *prometheus.Desc
totalRejectedAsyncIORequests *prometheus.Desc
}
const (
CurrentAnonymousUsers = "Current Anonymous Users"
CurrentBlockedAsyncIORequests = "Current Blocked Async I/O Requests"
CurrentCGIRequests = "Current CGI Requests"
CurrentConnections = "Current Connections"
CurrentISAPIExtensionRequests = "Current ISAPI Extension Requests"
CurrentNonAnonymousUsers = "Current NonAnonymous Users"
ServiceUptime = "Service Uptime"
TotalBytesReceived = "Total Bytes Received"
TotalBytesSent = "Total Bytes Sent"
TotalAnonymousUsers = "Total Anonymous Users"
TotalBlockedAsyncIORequests = "Total Blocked Async I/O Requests"
TotalCGIRequests = "Total CGI Requests"
TotalConnectionAttemptsAllInstances = "Total Connection Attempts (all instances)"
TotalFilesReceived = "Total Files Received"
TotalFilesSent = "Total Files Sent"
TotalISAPIExtensionRequests = "Total ISAPI Extension Requests"
TotalLockedErrors = "Total Locked Errors"
TotalLogonAttempts = "Total Logon Attempts"
TotalNonAnonymousUsers = "Total NonAnonymous Users"
TotalNotFoundErrors = "Total Not Found Errors"
TotalRejectedAsyncIORequests = "Total Rejected Async I/O Requests"
TotalCopyRequests = "Total Copy Requests"
TotalDeleteRequests = "Total Delete Requests"
TotalGetRequests = "Total Get Requests"
TotalHeadRequests = "Total Head Requests"
TotalLockRequests = "Total Lock Requests"
TotalMkcolRequests = "Total Mkcol Requests"
TotalMoveRequests = "Total Move Requests"
TotalOptionsRequests = "Total Options Requests"
TotalOtherRequests = "Total Other Request Methods"
TotalPostRequests = "Total Post Requests"
TotalPropfindRequests = "Total Propfind Requests"
TotalProppatchRequests = "Total Proppatch Requests"
TotalPutRequests = "Total Put Requests"
TotalSearchRequests = "Total Search Requests"
TotalTraceRequests = "Total Trace Requests"
TotalUnlockRequests = "Total Unlock Requests"
)
func (c *Collector) buildWebService() error {
var err error
c.perfDataCollectorWebService, err = perfdata.NewCollector("Web Service", perfdata.InstanceAll, []string{
CurrentAnonymousUsers,
CurrentBlockedAsyncIORequests,
CurrentCGIRequests,
CurrentConnections,
CurrentISAPIExtensionRequests,
CurrentNonAnonymousUsers,
ServiceUptime,
TotalBytesReceived,
TotalBytesSent,
TotalAnonymousUsers,
TotalBlockedAsyncIORequests,
TotalCGIRequests,
TotalConnectionAttemptsAllInstances,
TotalFilesReceived,
TotalFilesSent,
TotalISAPIExtensionRequests,
TotalLockedErrors,
TotalLogonAttempts,
TotalNonAnonymousUsers,
TotalNotFoundErrors,
TotalRejectedAsyncIORequests,
TotalCopyRequests,
TotalDeleteRequests,
TotalGetRequests,
TotalHeadRequests,
TotalLockRequests,
TotalMkcolRequests,
TotalMoveRequests,
TotalOptionsRequests,
TotalOtherRequests,
TotalPostRequests,
TotalPropfindRequests,
TotalProppatchRequests,
TotalPutRequests,
TotalSearchRequests,
TotalTraceRequests,
TotalUnlockRequests,
})
if err != nil {
return fmt.Errorf("failed to create Web Service collector: %w", err)
}
c.currentAnonymousUsers = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_anonymous_users"),
"Number of users who currently have an anonymous connection using the Web service (WebService.CurrentAnonymousUsers)",
[]string{"site"},
nil,
)
c.currentBlockedAsyncIORequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_blocked_async_io_requests"),
"Current requests temporarily blocked due to bandwidth throttling settings (WebService.CurrentBlockedAsyncIORequests)",
[]string{"site"},
nil,
)
c.currentCGIRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_cgi_requests"),
"Current number of CGI requests being simultaneously processed by the Web service (WebService.CurrentCGIRequests)",
[]string{"site"},
nil,
)
c.currentConnections = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_connections"),
"Current number of connections established with the Web service (WebService.CurrentConnections)",
[]string{"site"},
nil,
)
c.currentISAPIExtensionRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_isapi_extension_requests"),
"Current number of ISAPI requests being simultaneously processed by the Web service (WebService.CurrentISAPIExtensionRequests)",
[]string{"site"},
nil,
)
c.currentNonAnonymousUsers = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_non_anonymous_users"),
"Number of users who currently have a non-anonymous connection using the Web service (WebService.CurrentNonAnonymousUsers)",
[]string{"site"},
nil,
)
c.serviceUptime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "service_uptime"),
"Number of seconds the WebService is up (WebService.ServiceUptime)",
[]string{"site"},
nil,
)
c.totalBytesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "received_bytes_total"),
"Number of data bytes that have been received by the Web service (WebService.TotalBytesReceived)",
[]string{"site"},
nil,
)
c.totalBytesSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "sent_bytes_total"),
"Number of data bytes that have been sent by the Web service (WebService.TotalBytesSent)",
[]string{"site"},
nil,
)
c.totalAnonymousUsers = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "anonymous_users_total"),
"Total number of users who established an anonymous connection with the Web service (WebService.TotalAnonymousUsers)",
[]string{"site"},
nil,
)
c.totalBlockedAsyncIORequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "blocked_async_io_requests_total"),
"Total requests temporarily blocked due to bandwidth throttling settings (WebService.TotalBlockedAsyncIORequests)",
[]string{"site"},
nil,
)
c.totalCGIRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cgi_requests_total"),
"Total CGI requests is the total number of CGI requests (WebService.TotalCGIRequests)",
[]string{"site"},
nil,
)
c.totalConnectionAttemptsAllInstances = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "connection_attempts_all_instances_total"),
"Number of connections that have been attempted using the Web service (WebService.TotalConnectionAttemptsAllInstances)",
[]string{"site"},
nil,
)
c.totalRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "requests_total"),
"Number of HTTP requests (WebService.TotalRequests)",
[]string{"site", "method"},
nil,
)
c.totalFilesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "files_received_total"),
"Number of files received by the Web service (WebService.TotalFilesReceived)",
[]string{"site"},
nil,
)
c.totalFilesSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "files_sent_total"),
"Number of files sent by the Web service (WebService.TotalFilesSent)",
[]string{"site"},
nil,
)
c.totalISAPIExtensionRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "ipapi_extension_requests_total"),
"ISAPI Extension Requests received (WebService.TotalISAPIExtensionRequests)",
[]string{"site"},
nil,
)
c.totalLockedErrors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "locked_errors_total"),
"Number of requests that couldn't be satisfied by the server because the requested resource was locked (WebService.TotalLockedErrors)",
[]string{"site"},
nil,
)
c.totalLogonAttempts = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "logon_attempts_total"),
"Number of logons attempts to the Web Service (WebService.TotalLogonAttempts)",
[]string{"site"},
nil,
)
c.totalNonAnonymousUsers = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "non_anonymous_users_total"),
"Number of users who established a non-anonymous connection with the Web service (WebService.TotalNonAnonymousUsers)",
[]string{"site"},
nil,
)
c.totalNotFoundErrors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "not_found_errors_total"),
"Number of requests that couldn't be satisfied by the server because the requested document could not be found (WebService.TotalNotFoundErrors)",
[]string{"site"},
nil,
)
c.totalRejectedAsyncIORequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "rejected_async_io_requests_total"),
"Requests rejected due to bandwidth throttling settings (WebService.TotalRejectedAsyncIORequests)",
[]string{"site"},
nil,
)
return nil
}
func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorWebService.Collect()
if err != nil {
return fmt.Errorf("failed to collect Web Service metrics: %w", err)
}
deduplicateIISNames(perfData)
for name, app := range perfData {
if c.config.SiteExclude.MatchString(name) || !c.config.SiteInclude.MatchString(name) {
continue
}
ch <- prometheus.MustNewConstMetric(
c.currentAnonymousUsers,
prometheus.GaugeValue,
app[CurrentAnonymousUsers].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.currentBlockedAsyncIORequests,
prometheus.GaugeValue,
app[CurrentBlockedAsyncIORequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.currentCGIRequests,
prometheus.GaugeValue,
app[CurrentCGIRequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.currentConnections,
prometheus.GaugeValue,
app[CurrentConnections].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.currentISAPIExtensionRequests,
prometheus.GaugeValue,
app[CurrentISAPIExtensionRequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.currentNonAnonymousUsers,
prometheus.GaugeValue,
app[CurrentNonAnonymousUsers].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.serviceUptime,
prometheus.GaugeValue,
app[ServiceUptime].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalBytesReceived,
prometheus.CounterValue,
app[TotalBytesReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalBytesSent,
prometheus.CounterValue,
app[TotalBytesSent].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalAnonymousUsers,
prometheus.CounterValue,
app[TotalAnonymousUsers].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalBlockedAsyncIORequests,
prometheus.CounterValue,
app[TotalBlockedAsyncIORequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalCGIRequests,
prometheus.CounterValue,
app[TotalCGIRequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalConnectionAttemptsAllInstances,
prometheus.CounterValue,
app[TotalConnectionAttemptsAllInstances].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalFilesReceived,
prometheus.CounterValue,
app[TotalFilesReceived].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalFilesSent,
prometheus.CounterValue,
app[TotalFilesSent].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalISAPIExtensionRequests,
prometheus.CounterValue,
app[TotalISAPIExtensionRequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalLockedErrors,
prometheus.CounterValue,
app[TotalLockedErrors].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalLogonAttempts,
prometheus.CounterValue,
app[TotalLogonAttempts].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalNonAnonymousUsers,
prometheus.CounterValue,
app[TotalNonAnonymousUsers].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalNotFoundErrors,
prometheus.CounterValue,
app[TotalNotFoundErrors].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalRejectedAsyncIORequests,
prometheus.CounterValue,
app[TotalRejectedAsyncIORequests].FirstValue,
name,
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalOtherRequests].FirstValue,
name,
"other",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalCopyRequests].FirstValue,
name,
"COPY",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalDeleteRequests].FirstValue,
name,
"DELETE",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalGetRequests].FirstValue,
name,
"GET",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalHeadRequests].FirstValue,
name,
"HEAD",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalLockRequests].FirstValue,
name,
"LOCK",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalMkcolRequests].FirstValue,
name,
"MKCOL",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalMoveRequests].FirstValue,
name,
"MOVE",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalOptionsRequests].FirstValue,
name,
"OPTIONS",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalPostRequests].FirstValue,
name,
"POST",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalPropfindRequests].FirstValue,
name,
"PROPFIND",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalProppatchRequests].FirstValue,
name,
"PROPPATCH",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalPutRequests].FirstValue,
name,
"PUT",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalSearchRequests].FirstValue,
name,
"SEARCH",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalTraceRequests].FirstValue,
name,
"TRACE",
)
ch <- prometheus.MustNewConstMetric(
c.totalRequests,
prometheus.CounterValue,
app[TotalUnlockRequests].FirstValue,
name,
"UNLOCK",
)
}
return nil
}

View File

@@ -0,0 +1,501 @@
//go:build windows
package iis
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
type collectorWebServiceCache struct {
perfDataCollectorWebServiceCache *perfdata.Collector
serviceCacheActiveFlushedEntries *prometheus.Desc
serviceCacheCurrentFileCacheMemoryUsage *prometheus.Desc
serviceCacheMaximumFileCacheMemoryUsage *prometheus.Desc
serviceCacheFileCacheFlushesTotal *prometheus.Desc
serviceCacheFileCacheQueriesTotal *prometheus.Desc
serviceCacheFileCacheHitsTotal *prometheus.Desc
serviceCacheFilesCached *prometheus.Desc
serviceCacheFilesCachedTotal *prometheus.Desc
serviceCacheFilesFlushedTotal *prometheus.Desc
serviceCacheURICacheFlushesTotal *prometheus.Desc
serviceCacheURICacheQueriesTotal *prometheus.Desc
serviceCacheURICacheHitsTotal *prometheus.Desc
serviceCacheURIsCached *prometheus.Desc
serviceCacheURIsCachedTotal *prometheus.Desc
serviceCacheURIsFlushedTotal *prometheus.Desc
serviceCacheMetadataCached *prometheus.Desc
serviceCacheMetadataCacheFlushes *prometheus.Desc
serviceCacheMetadataCacheQueriesTotal *prometheus.Desc
serviceCacheMetadataCacheHitsTotal *prometheus.Desc
serviceCacheMetadataCachedTotal *prometheus.Desc
serviceCacheMetadataFlushedTotal *prometheus.Desc
serviceCacheOutputCacheActiveFlushedItems *prometheus.Desc
serviceCacheOutputCacheItems *prometheus.Desc
serviceCacheOutputCacheMemoryUsage *prometheus.Desc
serviceCacheOutputCacheQueriesTotal *prometheus.Desc
serviceCacheOutputCacheHitsTotal *prometheus.Desc
serviceCacheOutputCacheFlushedItemsTotal *prometheus.Desc
serviceCacheOutputCacheFlushesTotal *prometheus.Desc
}
const (
ServiceCacheActiveFlushedEntries = "Active Flushed Entries"
ServiceCacheCurrentFileCacheMemoryUsage = "Current File Cache Memory Usage"
ServiceCacheMaximumFileCacheMemoryUsage = "Maximum File Cache Memory Usage"
ServiceCacheFileCacheFlushesTotal = "File Cache Flushes"
ServiceCacheFileCacheHitsTotal = "File Cache Hits"
ServiceCacheFileCacheMissesTotal = "File Cache Misses"
ServiceCacheFilesCached = "Current Files Cached"
ServiceCacheFilesCachedTotal = "Total Files Cached"
ServiceCacheFilesFlushedTotal = "Total Flushed Files"
ServiceCacheURICacheFlushesTotal = "Total Flushed URIs"
ServiceCacheURICacheFlushesTotalKernel = "Total Flushed URIs"
ServiceCacheURIsFlushedTotalKernel = "Kernel: Total Flushed URIs"
ServiceCacheURICacheHitsTotal = "URI Cache Hits"
ServiceCacheURICacheHitsTotalKernel = "Kernel: URI Cache Hits"
ServiceCacheURICacheMissesTotal = "URI Cache Misses"
ServiceCacheURICacheMissesTotalKernel = "Kernel: URI Cache Misses"
ServiceCacheURIsCached = "Current URIs Cached"
ServiceCacheURIsCachedKernel = "Kernel: Current URIs Cached"
ServiceCacheURIsCachedTotal = "Total URIs Cached"
ServiceCacheURIsCachedTotalKernel = "Total URIs Cached"
ServiceCacheURIsFlushedTotal = "Total Flushed URIs"
ServiceCacheMetaDataCacheHits = "Metadata Cache Hits"
ServiceCacheMetaDataCacheMisses = "Metadata Cache Misses"
ServiceCacheMetadataCached = "Current Metadata Cached"
ServiceCacheMetadataCacheFlushes = "Metadata Cache Flushes"
ServiceCacheMetadataCachedTotal = "Total Metadata Cached"
ServiceCacheMetadataFlushedTotal = "Total Flushed Metadata"
ServiceCacheOutputCacheActiveFlushedItems = "Output Cache Current Flushed Items"
ServiceCacheOutputCacheItems = "Output Cache Current Items"
ServiceCacheOutputCacheMemoryUsage = "Output Cache Current Memory Usage"
ServiceCacheOutputCacheHitsTotal = "Output Cache Total Hits"
ServiceCacheOutputCacheMissesTotal = "Output Cache Total Misses"
ServiceCacheOutputCacheFlushedItemsTotal = "Output Cache Total Flushed Items"
ServiceCacheOutputCacheFlushesTotal = "Output Cache Total Flushes"
)
func (c *Collector) buildWebServiceCache() error {
var err error
c.perfDataCollectorWebService, err = perfdata.NewCollector("Web Service Cache", perfdata.InstanceAll, []string{
ServiceCacheActiveFlushedEntries,
ServiceCacheCurrentFileCacheMemoryUsage,
ServiceCacheMaximumFileCacheMemoryUsage,
ServiceCacheFileCacheFlushesTotal,
ServiceCacheFileCacheHitsTotal,
ServiceCacheFileCacheMissesTotal,
ServiceCacheFilesCached,
ServiceCacheFilesCachedTotal,
ServiceCacheFilesFlushedTotal,
ServiceCacheURICacheFlushesTotal,
ServiceCacheURICacheFlushesTotalKernel,
ServiceCacheURIsFlushedTotalKernel,
ServiceCacheURICacheHitsTotal,
ServiceCacheURICacheHitsTotalKernel,
ServiceCacheURICacheMissesTotal,
ServiceCacheURICacheMissesTotalKernel,
ServiceCacheURIsCached,
ServiceCacheURIsCachedKernel,
ServiceCacheURIsCachedTotal,
ServiceCacheURIsCachedTotalKernel,
ServiceCacheURIsFlushedTotal,
ServiceCacheMetaDataCacheHits,
ServiceCacheMetaDataCacheMisses,
ServiceCacheMetadataCached,
ServiceCacheMetadataCacheFlushes,
ServiceCacheMetadataCachedTotal,
ServiceCacheMetadataFlushedTotal,
ServiceCacheOutputCacheActiveFlushedItems,
ServiceCacheOutputCacheItems,
ServiceCacheOutputCacheMemoryUsage,
ServiceCacheOutputCacheHitsTotal,
ServiceCacheOutputCacheMissesTotal,
ServiceCacheOutputCacheFlushedItemsTotal,
ServiceCacheOutputCacheFlushesTotal,
})
if err != nil {
return fmt.Errorf("failed to create Web Service Cache collector: %w", err)
}
// Web Service Cache
c.serviceCacheActiveFlushedEntries = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_cache_active_flushed_entries"),
"Number of file handles cached that will be closed when all current transfers complete.",
nil,
nil,
)
c.serviceCacheCurrentFileCacheMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_memory_bytes"),
"Current number of bytes used by file cache",
nil,
nil,
)
c.serviceCacheMaximumFileCacheMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_max_memory_bytes"),
"Maximum number of bytes used by file cache",
nil,
nil,
)
c.serviceCacheFileCacheFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_flushes_total"),
"Total number of file cache flushes (since service startup)",
nil,
nil,
)
c.serviceCacheFileCacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_queries_total"),
"Total number of file cache queries (hits + misses)",
nil,
nil,
)
c.serviceCacheFileCacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_hits_total"),
"Total number of successful lookups in the user-mode file cache",
nil,
nil,
)
c.serviceCacheFilesCached = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_items"),
"Current number of files whose contents are present in cache",
nil,
nil,
)
c.serviceCacheFilesCachedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_items_total"),
"Total number of files whose contents were ever added to the cache (since service startup)",
nil,
nil,
)
c.serviceCacheFilesFlushedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_items_flushed_total"),
"Total number of file handles that have been removed from the cache (since service startup)",
nil,
nil,
)
c.serviceCacheURICacheFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_flushes_total"),
"Total number of URI cache flushes (since service startup)",
[]string{"mode"},
nil,
)
c.serviceCacheURICacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_queries_total"),
"Total number of uri cache queries (hits + misses)",
[]string{"mode"},
nil,
)
c.serviceCacheURICacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_hits_total"),
"Total number of successful lookups in the URI cache (since service startup)",
[]string{"mode"},
nil,
)
c.serviceCacheURIsCached = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_items"),
"Number of URI information blocks currently in the cache",
[]string{"mode"},
nil,
)
c.serviceCacheURIsCachedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_items_total"),
"Total number of URI information blocks added to the cache (since service startup)",
[]string{"mode"},
nil,
)
c.serviceCacheURIsFlushedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_items_flushed_total"),
"The number of URI information blocks that have been removed from the cache (since service startup)",
[]string{"mode"},
nil,
)
c.serviceCacheMetadataCached = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_items"),
"Number of metadata information blocks currently present in cache",
nil,
nil,
)
c.serviceCacheMetadataCacheFlushes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_flushes_total"),
"Total number of metadata cache flushes (since service startup)",
nil,
nil,
)
c.serviceCacheMetadataCacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_queries_total"),
"Total metadata cache queries (hits + misses)",
nil,
nil,
)
c.serviceCacheMetadataCacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_hits_total"),
"Total number of successful lookups in the metadata cache (since service startup)",
nil,
nil,
)
c.serviceCacheMetadataCachedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_items_cached_total"),
"Total number of metadata information blocks added to the cache (since service startup)",
nil,
nil,
)
c.serviceCacheMetadataFlushedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_items_flushed_total"),
"Total number of metadata information blocks removed from the cache (since service startup)",
nil,
nil,
)
c.serviceCacheOutputCacheActiveFlushedItems = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_active_flushed_items"),
"",
nil,
nil,
)
c.serviceCacheOutputCacheItems = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_items"),
"Number of items current present in output cache",
nil,
nil,
)
c.serviceCacheOutputCacheMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_memory_bytes"),
"Current number of bytes used by output cache",
nil,
nil,
)
c.serviceCacheOutputCacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_queries_total"),
"Total output cache queries (hits + misses)",
nil,
nil,
)
c.serviceCacheOutputCacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_hits_total"),
"Total number of successful lookups in output cache (since service startup)",
nil,
nil,
)
c.serviceCacheOutputCacheFlushedItemsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_items_flushed_total"),
"Total number of items flushed from output cache (since service startup)",
nil,
nil,
)
c.serviceCacheOutputCacheFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_flushes_total"),
"Total number of flushes of output cache (since service startup)",
nil,
nil,
)
return nil
}
func (c *Collector) collectWebServiceCache(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorWebService.Collect()
if err != nil {
return fmt.Errorf("failed to collect Web Service Cache metrics: %w", err)
}
deduplicateIISNames(perfData)
for name, app := range perfData {
if c.config.SiteExclude.MatchString(name) || !c.config.SiteInclude.MatchString(name) {
continue
}
ch <- prometheus.MustNewConstMetric(
c.serviceCacheActiveFlushedEntries,
prometheus.GaugeValue,
app[ServiceCacheActiveFlushedEntries].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheCurrentFileCacheMemoryUsage,
prometheus.GaugeValue,
app[ServiceCacheCurrentFileCacheMemoryUsage].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheMaximumFileCacheMemoryUsage,
prometheus.CounterValue,
app[ServiceCacheMaximumFileCacheMemoryUsage].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheFileCacheFlushesTotal,
prometheus.CounterValue,
app[ServiceCacheFileCacheFlushesTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheFileCacheQueriesTotal,
prometheus.CounterValue,
app[ServiceCacheFileCacheHitsTotal].FirstValue+app[ServiceCacheFileCacheMissesTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheFileCacheHitsTotal,
prometheus.CounterValue,
app[ServiceCacheFileCacheHitsTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheFilesCached,
prometheus.GaugeValue,
app[ServiceCacheFilesCached].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheFilesCachedTotal,
prometheus.CounterValue,
app[ServiceCacheFilesCachedTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheFilesFlushedTotal,
prometheus.CounterValue,
app[ServiceCacheFilesFlushedTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheFlushesTotal,
prometheus.CounterValue,
app[ServiceCacheURICacheFlushesTotal].FirstValue,
"user",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheFlushesTotal,
prometheus.CounterValue,
app[ServiceCacheURICacheFlushesTotalKernel].FirstValue,
"kernel",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheQueriesTotal,
prometheus.CounterValue,
app[ServiceCacheURICacheHitsTotal].FirstValue+app[ServiceCacheURICacheMissesTotal].FirstValue,
"user",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheQueriesTotal,
prometheus.CounterValue,
app[ServiceCacheURICacheHitsTotalKernel].FirstValue+app[ServiceCacheURICacheMissesTotalKernel].FirstValue,
"kernel",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheHitsTotal,
prometheus.CounterValue,
app[ServiceCacheURICacheHitsTotal].FirstValue,
"user",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheHitsTotal,
prometheus.CounterValue,
app[ServiceCacheURICacheHitsTotalKernel].FirstValue,
"kernel",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCached,
prometheus.GaugeValue,
app[ServiceCacheURIsCached].FirstValue,
"user",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCached,
prometheus.GaugeValue,
app[ServiceCacheURIsCachedKernel].FirstValue,
"kernel",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCachedTotal,
prometheus.CounterValue,
app[ServiceCacheURIsCachedTotal].FirstValue,
"user",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCachedTotal,
prometheus.CounterValue,
app[ServiceCacheURIsCachedTotalKernel].FirstValue,
"kernel",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsFlushedTotal,
prometheus.CounterValue,
app[ServiceCacheURIsFlushedTotal].FirstValue,
"user",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsFlushedTotal,
prometheus.CounterValue,
app[ServiceCacheURIsFlushedTotalKernel].FirstValue,
"kernel",
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCached,
prometheus.GaugeValue,
app[ServiceCacheMetadataCached].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCacheFlushes,
prometheus.CounterValue,
app[ServiceCacheMetadataCacheFlushes].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCacheQueriesTotal,
prometheus.CounterValue,
app[ServiceCacheMetaDataCacheHits].FirstValue+app[ServiceCacheMetaDataCacheMisses].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCacheHitsTotal,
prometheus.CounterValue,
0, // app[ServiceCacheMetadataCacheHitsTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCachedTotal,
prometheus.CounterValue,
app[ServiceCacheMetadataCachedTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataFlushedTotal,
prometheus.CounterValue,
app[ServiceCacheMetadataFlushedTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheActiveFlushedItems,
prometheus.CounterValue,
app[ServiceCacheOutputCacheActiveFlushedItems].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheItems,
prometheus.CounterValue,
app[ServiceCacheOutputCacheItems].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheMemoryUsage,
prometheus.CounterValue,
app[ServiceCacheOutputCacheMemoryUsage].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheQueriesTotal,
prometheus.CounterValue,
app[ServiceCacheOutputCacheHitsTotal].FirstValue+app[ServiceCacheOutputCacheMissesTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheHitsTotal,
prometheus.CounterValue,
app[ServiceCacheOutputCacheHitsTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheFlushedItemsTotal,
prometheus.CounterValue,
app[ServiceCacheOutputCacheFlushedItemsTotal].FirstValue,
)
ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheFlushesTotal,
prometheus.CounterValue,
app[ServiceCacheOutputCacheFlushesTotal].FirstValue,
)
}
return nil
}

View File

@@ -53,11 +53,7 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
@@ -74,20 +70,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
if err := c.collect(ch); err != nil {
logger.Error("failed collecting license metrics",
slog.Any("err", err),
)
return err
}
return nil
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
status, err := slc.SLIsWindowsGenuineLocal()
if err != nil {
return err

View File

@@ -1,10 +1,12 @@
//go:build windows
package license_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/license"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,3 +1,5 @@
//go:build windows
package logical_disk
const (
@@ -18,26 +20,3 @@ const (
percentIdleTime = "% Idle Time"
splitIOPerSec = "Split IO/Sec"
)
// Win32_PerfRawData_PerfDisk_LogicalDisk docs:
// - https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71) - Win32_PerfRawData_PerfDisk_LogicalDisk class
// - https://msdn.microsoft.com/en-us/library/ms803973.aspx - LogicalDisk object reference.
type logicalDisk struct {
Name string
CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"`
AvgDiskReadQueueLength float64 `perflib:"Avg. Disk Read Queue Length"`
AvgDiskWriteQueueLength float64 `perflib:"Avg. Disk Write Queue Length"`
DiskReadBytesPerSec float64 `perflib:"Disk Read Bytes/sec"`
DiskReadsPerSec float64 `perflib:"Disk Reads/sec"`
DiskWriteBytesPerSec float64 `perflib:"Disk Write Bytes/sec"`
DiskWritesPerSec float64 `perflib:"Disk Writes/sec"`
PercentDiskReadTime float64 `perflib:"% Disk Read Time"`
PercentDiskWriteTime float64 `perflib:"% Disk Write Time"`
PercentFreeSpace float64 `perflib:"% Free Space_Base"`
PercentFreeSpace_Base float64 `perflib:"Free Megabytes"`
PercentIdleTime float64 `perflib:"% Idle Time"`
SplitIOPerSec float64 `perflib:"Split IO/Sec"`
AvgDiskSecPerRead float64 `perflib:"Avg. Disk sec/Read"`
AvgDiskSecPerWrite float64 `perflib:"Avg. Disk sec/Write"`
AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"`
}

View File

@@ -14,9 +14,6 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/toggle"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows"
@@ -37,8 +34,9 @@ var ConfigDefaults = Config{
// A Collector is a Prometheus Collector for perflib logicalDisk metrics.
type Collector struct {
config Config
logger *slog.Logger
perfDataCollector perfdata.Collector
perfDataCollector *perfdata.Collector
avgReadQueue *prometheus.Desc
avgWriteQueue *prometheus.Desc
@@ -61,6 +59,7 @@ type Collector struct {
}
type volumeInfo struct {
diskIDs string
filesystem string
serialNumber string
label string
@@ -128,45 +127,35 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
if toggle.IsPDHEnabled() {
return []string{}, nil
}
return []string{"LogicalDisk"}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
if toggle.IsPDHEnabled() {
counters := []string{
currentDiskQueueLength,
avgDiskReadQueueLength,
avgDiskWriteQueueLength,
diskReadBytesPerSec,
diskReadsPerSec,
diskWriteBytesPerSec,
diskWritesPerSec,
percentDiskReadTime,
percentDiskWriteTime,
percentFreeSpace,
freeSpace,
percentIdleTime,
splitIOPerSec,
avgDiskSecPerRead,
avgDiskSecPerWrite,
avgDiskSecPerTransfer,
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name))
var err error
var err error
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V1, "LogicalDisk", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create LogicalDisk collector: %w", err)
}
c.perfDataCollector, err = perfdata.NewCollector("LogicalDisk", perfdata.InstanceAll, []string{
currentDiskQueueLength,
avgDiskReadQueueLength,
avgDiskWriteQueueLength,
diskReadBytesPerSec,
diskReadsPerSec,
diskWriteBytesPerSec,
diskWritesPerSec,
percentDiskReadTime,
percentDiskWriteTime,
percentFreeSpace,
freeSpace,
percentIdleTime,
splitIOPerSec,
avgDiskSecPerRead,
avgDiskSecPerWrite,
avgDiskSecPerTransfer,
})
if err != nil {
return fmt.Errorf("failed to create LogicalDisk collector: %w", err)
}
c.information = prometheus.NewDesc(
@@ -298,29 +287,10 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
if toggle.IsPDHEnabled() {
return c.collectPDH(logger, ch)
}
if err := c.collect(ctx, logger, ch); err != nil {
logger.Error("failed collecting logical_disk metrics",
slog.Any("err", err),
)
return err
}
return nil
}
func (c *Collector) collectPDH(logger *slog.Logger, ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
var (
err error
diskID string
info volumeInfo
err error
info volumeInfo
)
perfData, err := c.perfDataCollector.Collect()
@@ -329,22 +299,13 @@ func (c *Collector) collectPDH(logger *slog.Logger, ch chan<- prometheus.Metric)
}
for name, volume := range perfData {
if name == "_Total" ||
c.config.VolumeExclude.MatchString(name) ||
!c.config.VolumeInclude.MatchString(name) {
if c.config.VolumeExclude.MatchString(name) || !c.config.VolumeInclude.MatchString(name) {
continue
}
diskID, err = getDiskIDByVolume(name)
if err != nil {
logger.Warn("failed to get disk ID for "+name,
slog.Any("err", err),
)
}
info, err = getVolumeInfo(name)
if err != nil {
logger.Warn("failed to get volume information for "+name,
c.logger.Warn("failed to get volume information for "+name,
slog.Any("err", err),
)
}
@@ -353,7 +314,7 @@ func (c *Collector) collectPDH(logger *slog.Logger, ch chan<- prometheus.Metric)
c.information,
prometheus.GaugeValue,
1,
diskID,
info.diskIDs,
info.volumeType,
name,
info.label,
@@ -371,14 +332,14 @@ func (c *Collector) collectPDH(logger *slog.Logger, ch chan<- prometheus.Metric)
ch <- prometheus.MustNewConstMetric(
c.avgReadQueue,
prometheus.GaugeValue,
volume[avgDiskReadQueueLength].FirstValue*perftypes.TicksToSecondScaleFactor,
volume[avgDiskReadQueueLength].FirstValue*perfdata.TicksToSecondScaleFactor,
name,
)
ch <- prometheus.MustNewConstMetric(
c.avgWriteQueue,
prometheus.GaugeValue,
volume[avgDiskWriteQueueLength].FirstValue*perftypes.TicksToSecondScaleFactor,
volume[avgDiskWriteQueueLength].FirstValue*perfdata.TicksToSecondScaleFactor,
name,
)
@@ -434,7 +395,7 @@ func (c *Collector) collectPDH(logger *slog.Logger, ch chan<- prometheus.Metric)
ch <- prometheus.MustNewConstMetric(
c.totalSpace,
prometheus.GaugeValue,
volume[percentFreeSpace].FirstValue*1024*1024,
volume[percentFreeSpace].SecondValue*1024*1024,
name,
)
@@ -455,21 +416,21 @@ func (c *Collector) collectPDH(logger *slog.Logger, ch chan<- prometheus.Metric)
ch <- prometheus.MustNewConstMetric(
c.readLatency,
prometheus.CounterValue,
volume[avgDiskSecPerRead].FirstValue*perftypes.TicksToSecondScaleFactor,
volume[avgDiskSecPerRead].FirstValue*perfdata.TicksToSecondScaleFactor,
name,
)
ch <- prometheus.MustNewConstMetric(
c.writeLatency,
prometheus.CounterValue,
volume[avgDiskSecPerWrite].FirstValue*perftypes.TicksToSecondScaleFactor,
volume[avgDiskSecPerWrite].FirstValue*perfdata.TicksToSecondScaleFactor,
name,
)
ch <- prometheus.MustNewConstMetric(
c.readWriteLatency,
prometheus.CounterValue,
volume[avgDiskSecPerTransfer].FirstValue*perftypes.TicksToSecondScaleFactor,
volume[avgDiskSecPerTransfer].FirstValue*perfdata.TicksToSecondScaleFactor,
name,
)
}
@@ -477,167 +438,6 @@ func (c *Collector) collectPDH(logger *slog.Logger, ch chan<- prometheus.Metric)
return nil
}
func (c *Collector) collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
var (
err error
diskID string
info volumeInfo
dst []logicalDisk
)
if err = v1.UnmarshalObject(ctx.PerfObjects["LogicalDisk"], &dst, logger); err != nil {
return err
}
for _, volume := range dst {
if volume.Name == "_Total" ||
c.config.VolumeExclude.MatchString(volume.Name) ||
!c.config.VolumeInclude.MatchString(volume.Name) {
continue
}
diskID, err = getDiskIDByVolume(volume.Name)
if err != nil {
logger.Warn("failed to get disk ID for "+volume.Name,
slog.Any("err", err),
)
}
info, err = getVolumeInfo(volume.Name)
if err != nil {
logger.Warn("failed to get volume information for %s"+volume.Name,
slog.Any("err", err),
)
}
ch <- prometheus.MustNewConstMetric(
c.information,
prometheus.GaugeValue,
1,
diskID,
info.volumeType,
volume.Name,
info.label,
info.filesystem,
info.serialNumber,
)
ch <- prometheus.MustNewConstMetric(
c.requestsQueued,
prometheus.GaugeValue,
volume.CurrentDiskQueueLength,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.avgReadQueue,
prometheus.GaugeValue,
volume.AvgDiskReadQueueLength*perftypes.TicksToSecondScaleFactor,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.avgWriteQueue,
prometheus.GaugeValue,
volume.AvgDiskWriteQueueLength*perftypes.TicksToSecondScaleFactor,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.readBytesTotal,
prometheus.CounterValue,
volume.DiskReadBytesPerSec,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.readsTotal,
prometheus.CounterValue,
volume.DiskReadsPerSec,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.writeBytesTotal,
prometheus.CounterValue,
volume.DiskWriteBytesPerSec,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.writesTotal,
prometheus.CounterValue,
volume.DiskWritesPerSec,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.readTime,
prometheus.CounterValue,
volume.PercentDiskReadTime,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.writeTime,
prometheus.CounterValue,
volume.PercentDiskWriteTime,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.freeSpace,
prometheus.GaugeValue,
volume.PercentFreeSpace_Base*1024*1024,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.totalSpace,
prometheus.GaugeValue,
volume.PercentFreeSpace*1024*1024,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.idleTime,
prometheus.CounterValue,
volume.PercentIdleTime,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.splitIOs,
prometheus.CounterValue,
volume.SplitIOPerSec,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.readLatency,
prometheus.CounterValue,
volume.AvgDiskSecPerRead*perftypes.TicksToSecondScaleFactor,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.writeLatency,
prometheus.CounterValue,
volume.AvgDiskSecPerWrite*perftypes.TicksToSecondScaleFactor,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.readWriteLatency,
prometheus.CounterValue,
volume.AvgDiskSecPerTransfer*perftypes.TicksToSecondScaleFactor,
volume.Name,
)
}
return nil
}
func getDriveType(driveType uint32) string {
switch driveType {
case windows.DRIVE_UNKNOWN:
@@ -663,38 +463,60 @@ func getDriveType(driveType uint32) string {
const diskExtentSize = 24
// getDiskIDByVolume returns the disk ID for a given volume.
func getDiskIDByVolume(rootDrive string) (string, error) {
// Open a volume handle to the Disk Root.
var err error
func getVolumeInfo(rootDrive string) (volumeInfo, error) {
volumePath := rootDrive
var f windows.Handle
// If rootDrive is a NTFS directory, convert it to a volume GUID.
if strings.Contains(volumePath, `\`) {
volumePathName, err := windows.UTF16PtrFromString(volumePath + `\`)
if err != nil {
return volumeInfo{}, fmt.Errorf("could not convert rootDrive to volume path: %w", err)
}
volumeGUIDPtr := make([]uint16, 50)
if err := windows.GetVolumeNameForVolumeMountPoint(volumePathName, &volumeGUIDPtr[0], uint32(len(volumeGUIDPtr))); err != nil {
panic(fmt.Errorf("could not get volume GUID: %w", err))
}
volumePath = windows.UTF16ToString(volumeGUIDPtr)
// GetVolumeNameForVolumeMountPoint returns the volume GUID path as \\?\Volume{GUID}\
// According https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol#remarks
// Win32 Drive Namespace is prefixed with \\.\, so we need to remove the \\?\ prefix.
volumePath, _ = strings.CutPrefix(volumePath, `\\?\`)
// https://stackoverflow.com/questions/55710326/how-to-get-the-physical-device-that-a-volume-guid-path-belongs-to#comment98104360_55710326
// DeviceIoControl expects no trailing backslash in the volume GUID path.
volumePath = strings.TrimRight(volumePath, `\`)
}
volumePathPtr := windows.StringToUTF16Ptr(`\\.\` + volumePath)
// mode has to include FILE_SHARE permission to allow concurrent access to the disk.
// use 0 as access mode to avoid admin permission.
mode := uint32(windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE)
attr := uint32(windows.FILE_ATTRIBUTE_READONLY)
f, err = windows.CreateFile(
windows.StringToUTF16Ptr(`\\.\`+rootDrive),
0, mode, nil, windows.OPEN_EXISTING, uint32(windows.FILE_ATTRIBUTE_READONLY), 0)
volumeHandle, err := windows.CreateFile(volumePathPtr, 0, mode, nil, windows.OPEN_EXISTING, attr, 0)
if err != nil {
return "", err
return volumeInfo{}, fmt.Errorf("could not open volume for %s: %w", rootDrive, err)
}
defer windows.Close(f)
defer windows.Close(volumeHandle)
controlCode := uint32(5636096) // IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
volumeDiskExtents := make([]byte, 16*1024)
var bytesReturned uint32
err = windows.DeviceIoControl(f, controlCode, nil, 0, &volumeDiskExtents[0], uint32(len(volumeDiskExtents)), &bytesReturned, nil)
err = windows.DeviceIoControl(volumeHandle, controlCode, nil, 0, &volumeDiskExtents[0], uint32(len(volumeDiskExtents)), &bytesReturned, nil)
if err != nil {
return "", fmt.Errorf("could not identify physical drive for %s: %w", rootDrive, err)
return volumeInfo{}, fmt.Errorf("could not identify physical drive for %s: %w", rootDrive, err)
}
numDiskIDs := uint(binary.LittleEndian.Uint32(volumeDiskExtents))
if numDiskIDs < 1 {
return "", fmt.Errorf("could not identify physical drive for %s: no disk IDs returned", rootDrive)
return volumeInfo{}, fmt.Errorf("could not identify physical drive for %s: no disk IDs returned", rootDrive)
}
diskIDs := make([]string, numDiskIDs)
@@ -706,34 +528,35 @@ func getDiskIDByVolume(rootDrive string) (string, error) {
slices.Sort(diskIDs)
diskIDs = slices.Compact(diskIDs)
return strings.Join(diskIDs, ";"), nil
}
volumeInformationRootDrive := volumePath + `\`
func getVolumeInfo(rootDrive string) (volumeInfo, error) {
if !strings.HasSuffix(rootDrive, ":") {
return volumeInfo{}, nil
if strings.Contains(volumePath, `Volume`) {
volumeInformationRootDrive = `\\?\` + volumeInformationRootDrive
}
volPath := windows.StringToUTF16Ptr(rootDrive + `\`)
volumeInformationRootDrivePtr := windows.StringToUTF16Ptr(volumeInformationRootDrive)
driveType := windows.GetDriveType(volumeInformationRootDrivePtr)
volBufLabel := make([]uint16, windows.MAX_PATH+1)
volSerialNum := uint32(0)
fsFlags := uint32(0)
volBufType := make([]uint16, windows.MAX_PATH+1)
driveType := windows.GetDriveType(volPath)
err := windows.GetVolumeInformation(volPath, &volBufLabel[0], uint32(len(volBufLabel)),
&volSerialNum, nil, &fsFlags, &volBufType[0], uint32(len(volBufType)))
err = windows.GetVolumeInformation(
volumeInformationRootDrivePtr,
&volBufLabel[0], uint32(len(volBufLabel)),
&volSerialNum, nil, &fsFlags,
&volBufType[0], uint32(len(volBufType)),
)
if err != nil {
if driveType != windows.DRIVE_CDROM && driveType != windows.DRIVE_REMOVABLE {
return volumeInfo{}, err
if driveType == windows.DRIVE_CDROM || driveType == windows.DRIVE_REMOVABLE {
return volumeInfo{}, nil
}
return volumeInfo{}, nil
return volumeInfo{}, fmt.Errorf("could not get volume information for %s: %w", volumeInformationRootDrive, err)
}
return volumeInfo{
diskIDs: strings.Join(diskIDs, ";"),
volumeType: getDriveType(driveType),
label: windows.UTF16PtrToString(&volBufLabel[0]),
filesystem: windows.UTF16PtrToString(&volBufType[0]),

View File

@@ -1,3 +1,5 @@
//go:build windows
package logical_disk_test
import (
@@ -5,8 +7,8 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/collector/logical_disk"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -46,11 +46,7 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
@@ -67,15 +63,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error {
if err := c.collect(ch); err != nil {
return err
}
return nil
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
logonSessions, err := secur32.GetLogonSessions()
if err != nil {
return fmt.Errorf("failed to get logon sessions: %w", err)

View File

@@ -1,10 +1,12 @@
//go:build windows
package logon_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/logon"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,3 +1,5 @@
//go:build windows
package memory
const (
@@ -36,40 +38,3 @@ const (
transitionPagesRePurposedPerSec = "Transition Pages RePurposed/sec"
writeCopiesPerSec = "Write Copies/sec"
)
type memory struct {
AvailableBytes float64 `perflib:"Available Bytes"`
AvailableKBytes float64 `perflib:"Available KBytes"`
AvailableMBytes float64 `perflib:"Available MBytes"`
CacheBytes float64 `perflib:"Cache Bytes"`
CacheBytesPeak float64 `perflib:"Cache Bytes Peak"`
CacheFaultsPerSec float64 `perflib:"Cache Faults/sec"`
CommitLimit float64 `perflib:"Commit Limit"`
CommittedBytes float64 `perflib:"Committed Bytes"`
DemandZeroFaultsPerSec float64 `perflib:"Demand Zero Faults/sec"`
FreeAndZeroPageListBytes float64 `perflib:"Free & Zero Page List Bytes"`
FreeSystemPageTableEntries float64 `perflib:"Free System Page Table Entries"`
ModifiedPageListBytes float64 `perflib:"Modified Page List Bytes"`
PageFaultsPerSec float64 `perflib:"Page Faults/sec"`
PageReadsPerSec float64 `perflib:"Page Reads/sec"`
PagesInputPerSec float64 `perflib:"Pages Input/sec"`
PagesOutputPerSec float64 `perflib:"Pages Output/sec"`
PagesPerSec float64 `perflib:"Pages/sec"`
PageWritesPerSec float64 `perflib:"Page Writes/sec"`
PoolNonpagedAllocs float64 `perflib:"Pool Nonpaged Allocs"`
PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"`
PoolPagedAllocs float64 `perflib:"Pool Paged Allocs"`
PoolPagedBytes float64 `perflib:"Pool Paged Bytes"`
PoolPagedResidentBytes float64 `perflib:"Pool Paged Resident Bytes"`
StandbyCacheCoreBytes float64 `perflib:"Standby Cache Core Bytes"`
StandbyCacheNormalPriorityBytes float64 `perflib:"Standby Cache Normal Priority Bytes"`
StandbyCacheReserveBytes float64 `perflib:"Standby Cache Reserve Bytes"`
SystemCacheResidentBytes float64 `perflib:"System Cache Resident Bytes"`
SystemCodeResidentBytes float64 `perflib:"System Code Resident Bytes"`
SystemCodeTotalBytes float64 `perflib:"System Code Total Bytes"`
SystemDriverResidentBytes float64 `perflib:"System Driver Resident Bytes"`
SystemDriverTotalBytes float64 `perflib:"System Driver Total Bytes"`
TransitionFaultsPerSec float64 `perflib:"Transition Faults/sec"`
TransitionPagesRePurposedPerSec float64 `perflib:"Transition Pages RePurposed/sec"`
WriteCopiesPerSec float64 `perflib:"Write Copies/sec"`
}

View File

@@ -14,9 +14,6 @@ import (
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
"github.com/prometheus-community/windows_exporter/internal/toggle"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -31,7 +28,7 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config
perfDataCollector perfdata.Collector
perfDataCollector *perfdata.Collector
// Performance metrics
availableBytes *prometheus.Desc
@@ -94,62 +91,56 @@ func (c *Collector) GetName() string {
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
if toggle.IsPDHEnabled() {
return []string{}, nil
}
return []string{"Memory"}, nil
return []string{}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
if toggle.IsPDHEnabled() {
counters := []string{
availableBytes,
availableKBytes,
availableMBytes,
cacheBytes,
cacheBytesPeak,
cacheFaultsPerSec,
commitLimit,
committedBytes,
demandZeroFaultsPerSec,
freeAndZeroPageListBytes,
freeSystemPageTableEntries,
modifiedPageListBytes,
pageFaultsPerSec,
pageReadsPerSec,
pagesInputPerSec,
pagesOutputPerSec,
pagesPerSec,
pageWritesPerSec,
poolNonpagedAllocs,
poolNonpagedBytes,
poolPagedAllocs,
poolPagedBytes,
poolPagedResidentBytes,
standbyCacheCoreBytes,
standbyCacheNormalPriorityBytes,
standbyCacheReserveBytes,
systemCacheResidentBytes,
systemCodeResidentBytes,
systemCodeTotalBytes,
systemDriverResidentBytes,
systemDriverTotalBytes,
transitionFaultsPerSec,
transitionPagesRePurposedPerSec,
writeCopiesPerSec,
}
counters := []string{
availableBytes,
availableKBytes,
availableMBytes,
cacheBytes,
cacheBytesPeak,
cacheFaultsPerSec,
commitLimit,
committedBytes,
demandZeroFaultsPerSec,
freeAndZeroPageListBytes,
freeSystemPageTableEntries,
modifiedPageListBytes,
pageFaultsPerSec,
pageReadsPerSec,
pagesInputPerSec,
pagesOutputPerSec,
pagesPerSec,
pageWritesPerSec,
poolNonpagedAllocs,
poolNonpagedBytes,
poolPagedAllocs,
poolPagedBytes,
poolPagedResidentBytes,
standbyCacheCoreBytes,
standbyCacheNormalPriorityBytes,
standbyCacheReserveBytes,
systemCacheResidentBytes,
systemCodeResidentBytes,
systemCodeTotalBytes,
systemDriverResidentBytes,
systemDriverTotalBytes,
transitionFaultsPerSec,
transitionPagesRePurposedPerSec,
writeCopiesPerSec,
}
var err error
var err error
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V1, "Memory", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create LogicalDisk collector: %w", err)
}
c.perfDataCollector, err = perfdata.NewCollector("Memory", perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create Memory collector: %w", err)
}
c.availableBytes = prometheus.NewDesc(
@@ -380,32 +371,15 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
errs := make([]error, 0, 2)
var err error
if toggle.IsPDHEnabled() {
err = c.collectPDH(ch)
} else {
err = c.collectPerformanceData(ctx, logger, ch)
}
if err != nil {
logger.Error("failed collecting memory metrics",
slog.Any("err", err),
)
errs = append(errs, err)
if err := c.collectPDH(ch); err != nil {
errs = append(errs, fmt.Errorf("failed collecting memory metrics: %w", err))
}
if err := c.collectGlobalMemoryStatus(ch); err != nil {
logger.Error("failed collecting memory metrics",
slog.Any("err", err),
)
errs = append(errs, err)
errs = append(errs, fmt.Errorf("failed collecting global memory metrics: %w", err))
}
return errors.Join(errs...)
@@ -438,217 +412,13 @@ func (c *Collector) collectGlobalMemoryStatus(ch chan<- prometheus.Metric) error
return nil
}
func (c *Collector) collectPerformanceData(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
var dst []memory
if err := v1.UnmarshalObject(ctx.PerfObjects["Memory"], &dst, logger); err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(
c.availableBytes,
prometheus.GaugeValue,
dst[0].AvailableBytes,
)
ch <- prometheus.MustNewConstMetric(
c.cacheBytes,
prometheus.GaugeValue,
dst[0].CacheBytes,
)
ch <- prometheus.MustNewConstMetric(
c.cacheBytesPeak,
prometheus.GaugeValue,
dst[0].CacheBytesPeak,
)
ch <- prometheus.MustNewConstMetric(
c.cacheFaultsTotal,
prometheus.CounterValue,
dst[0].CacheFaultsPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.commitLimit,
prometheus.GaugeValue,
dst[0].CommitLimit,
)
ch <- prometheus.MustNewConstMetric(
c.committedBytes,
prometheus.GaugeValue,
dst[0].CommittedBytes,
)
ch <- prometheus.MustNewConstMetric(
c.demandZeroFaultsTotal,
prometheus.CounterValue,
dst[0].DemandZeroFaultsPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.freeAndZeroPageListBytes,
prometheus.GaugeValue,
dst[0].FreeAndZeroPageListBytes,
)
ch <- prometheus.MustNewConstMetric(
c.freeSystemPageTableEntries,
prometheus.GaugeValue,
dst[0].FreeSystemPageTableEntries,
)
ch <- prometheus.MustNewConstMetric(
c.modifiedPageListBytes,
prometheus.GaugeValue,
dst[0].ModifiedPageListBytes,
)
ch <- prometheus.MustNewConstMetric(
c.pageFaultsTotal,
prometheus.CounterValue,
dst[0].PageFaultsPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.swapPageReadsTotal,
prometheus.CounterValue,
dst[0].PageReadsPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.swapPagesReadTotal,
prometheus.CounterValue,
dst[0].PagesInputPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.swapPagesWrittenTotal,
prometheus.CounterValue,
dst[0].PagesOutputPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.swapPageOperationsTotal,
prometheus.CounterValue,
dst[0].PagesPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.swapPageWritesTotal,
prometheus.CounterValue,
dst[0].PageWritesPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.poolNonPagedAllocationsTotal,
prometheus.GaugeValue,
dst[0].PoolNonpagedAllocs,
)
ch <- prometheus.MustNewConstMetric(
c.poolNonPagedBytes,
prometheus.GaugeValue,
dst[0].PoolNonpagedBytes,
)
ch <- prometheus.MustNewConstMetric(
c.poolPagedAllocationsTotal,
prometheus.CounterValue,
dst[0].PoolPagedAllocs,
)
ch <- prometheus.MustNewConstMetric(
c.poolPagedBytes,
prometheus.GaugeValue,
dst[0].PoolPagedBytes,
)
ch <- prometheus.MustNewConstMetric(
c.poolPagedResidentBytes,
prometheus.GaugeValue,
dst[0].PoolPagedResidentBytes,
)
ch <- prometheus.MustNewConstMetric(
c.standbyCacheCoreBytes,
prometheus.GaugeValue,
dst[0].StandbyCacheCoreBytes,
)
ch <- prometheus.MustNewConstMetric(
c.standbyCacheNormalPriorityBytes,
prometheus.GaugeValue,
dst[0].StandbyCacheNormalPriorityBytes,
)
ch <- prometheus.MustNewConstMetric(
c.standbyCacheReserveBytes,
prometheus.GaugeValue,
dst[0].StandbyCacheReserveBytes,
)
ch <- prometheus.MustNewConstMetric(
c.systemCacheResidentBytes,
prometheus.GaugeValue,
dst[0].SystemCacheResidentBytes,
)
ch <- prometheus.MustNewConstMetric(
c.systemCodeResidentBytes,
prometheus.GaugeValue,
dst[0].SystemCodeResidentBytes,
)
ch <- prometheus.MustNewConstMetric(
c.systemCodeTotalBytes,
prometheus.GaugeValue,
dst[0].SystemCodeTotalBytes,
)
ch <- prometheus.MustNewConstMetric(
c.systemDriverResidentBytes,
prometheus.GaugeValue,
dst[0].SystemDriverResidentBytes,
)
ch <- prometheus.MustNewConstMetric(
c.systemDriverTotalBytes,
prometheus.GaugeValue,
dst[0].SystemDriverTotalBytes,
)
ch <- prometheus.MustNewConstMetric(
c.transitionFaultsTotal,
prometheus.CounterValue,
dst[0].TransitionFaultsPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.transitionPagesRepurposedTotal,
prometheus.CounterValue,
dst[0].TransitionPagesRePurposedPerSec,
)
ch <- prometheus.MustNewConstMetric(
c.writeCopiesTotal,
prometheus.CounterValue,
dst[0].WriteCopiesPerSec,
)
return nil
}
func (c *Collector) collectPDH(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect Memory metrics: %w", err)
}
data, ok := perfData[perftypes.EmptyInstance]
data, ok := perfData[perfdata.EmptyInstance]
if !ok {
return errors.New("perflib query for Memory returned empty result set")

View File

@@ -1,10 +1,12 @@
//go:build windows
package memory_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/memory"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

View File

@@ -1,3 +1,5 @@
//go:build windows
package mscluster
import (
@@ -9,7 +11,6 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -34,141 +35,11 @@ type Collector struct {
config Config
miSession *mi.Session
// cluster
clusterAddEvictDelay *prometheus.Desc
clusterAdminAccessPoint *prometheus.Desc
clusterAutoAssignNodeSite *prometheus.Desc
clusterAutoBalancerLevel *prometheus.Desc
clusterAutoBalancerMode *prometheus.Desc
clusterBackupInProgress *prometheus.Desc
clusterBlockCacheSize *prometheus.Desc
clusterClusSvcHangTimeout *prometheus.Desc
clusterClusSvcRegroupOpeningTimeout *prometheus.Desc
clusterClusSvcRegroupPruningTimeout *prometheus.Desc
clusterClusSvcRegroupStageTimeout *prometheus.Desc
clusterClusSvcRegroupTickInMilliseconds *prometheus.Desc
clusterClusterEnforcedAntiAffinity *prometheus.Desc
clusterClusterFunctionalLevel *prometheus.Desc
clusterClusterGroupWaitDelay *prometheus.Desc
clusterClusterLogLevel *prometheus.Desc
clusterClusterLogSize *prometheus.Desc
clusterClusterUpgradeVersion *prometheus.Desc
clusterCrossSiteDelay *prometheus.Desc
clusterCrossSiteThreshold *prometheus.Desc
clusterCrossSubnetDelay *prometheus.Desc
clusterCrossSubnetThreshold *prometheus.Desc
clusterCsvBalancer *prometheus.Desc
clusterDatabaseReadWriteMode *prometheus.Desc
clusterDefaultNetworkRole *prometheus.Desc
clusterDetectedCloudPlatform *prometheus.Desc
clusterDetectManagedEvents *prometheus.Desc
clusterDetectManagedEventsThreshold *prometheus.Desc
clusterDisableGroupPreferredOwnerRandomization *prometheus.Desc
clusterDrainOnShutdown *prometheus.Desc
clusterDynamicQuorumEnabled *prometheus.Desc
clusterEnableSharedVolumes *prometheus.Desc
clusterFixQuorum *prometheus.Desc
clusterGracePeriodEnabled *prometheus.Desc
clusterGracePeriodTimeout *prometheus.Desc
clusterGroupDependencyTimeout *prometheus.Desc
clusterHangRecoveryAction *prometheus.Desc
clusterIgnorePersistentStateOnStartup *prometheus.Desc
clusterLogResourceControls *prometheus.Desc
clusterLowerQuorumPriorityNodeId *prometheus.Desc
clusterMaxNumberOfNodes *prometheus.Desc
clusterMessageBufferLength *prometheus.Desc
clusterMinimumNeverPreemptPriority *prometheus.Desc
clusterMinimumPreemptorPriority *prometheus.Desc
clusterNetftIPSecEnabled *prometheus.Desc
clusterPlacementOptions *prometheus.Desc
clusterPlumbAllCrossSubnetRoutes *prometheus.Desc
clusterPreventQuorum *prometheus.Desc
clusterQuarantineDuration *prometheus.Desc
clusterQuarantineThreshold *prometheus.Desc
clusterQuorumArbitrationTimeMax *prometheus.Desc
clusterQuorumArbitrationTimeMin *prometheus.Desc
clusterQuorumLogFileSize *prometheus.Desc
clusterQuorumTypeValue *prometheus.Desc
clusterRequestReplyTimeout *prometheus.Desc
clusterResiliencyDefaultPeriod *prometheus.Desc
clusterResiliencyLevel *prometheus.Desc
clusterResourceDllDeadlockPeriod *prometheus.Desc
clusterRootMemoryReserved *prometheus.Desc
clusterRouteHistoryLength *prometheus.Desc
clusterS2DBusTypes *prometheus.Desc
clusterS2DCacheDesiredState *prometheus.Desc
clusterS2DCacheFlashReservePercent *prometheus.Desc
clusterS2DCachePageSizeKBytes *prometheus.Desc
clusterS2DEnabled *prometheus.Desc
clusterS2DIOLatencyThreshold *prometheus.Desc
clusterS2DOptimizations *prometheus.Desc
clusterSameSubnetDelay *prometheus.Desc
clusterSameSubnetThreshold *prometheus.Desc
clusterSecurityLevel *prometheus.Desc
clusterSecurityLevelForStorage *prometheus.Desc
clusterSharedVolumeVssWriterOperationTimeout *prometheus.Desc
clusterShutdownTimeoutInMinutes *prometheus.Desc
clusterUseClientAccessNetworksForSharedVolumes *prometheus.Desc
clusterWitnessDatabaseWriteTimeout *prometheus.Desc
clusterWitnessDynamicWeight *prometheus.Desc
clusterWitnessRestartInterval *prometheus.Desc
// network
networkCharacteristics *prometheus.Desc
networkFlags *prometheus.Desc
networkMetric *prometheus.Desc
networkRole *prometheus.Desc
networkState *prometheus.Desc
// node
nodeBuildNumber *prometheus.Desc
nodeCharacteristics *prometheus.Desc
nodeDetectedCloudPlatform *prometheus.Desc
nodeDynamicWeight *prometheus.Desc
nodeFlags *prometheus.Desc
nodeMajorVersion *prometheus.Desc
nodeMinorVersion *prometheus.Desc
nodeNeedsPreventQuorum *prometheus.Desc
nodeNodeDrainStatus *prometheus.Desc
nodeNodeHighestVersion *prometheus.Desc
nodeNodeLowestVersion *prometheus.Desc
nodeNodeWeight *prometheus.Desc
nodeState *prometheus.Desc
nodeStatusInformation *prometheus.Desc
resourceCharacteristics *prometheus.Desc
resourceDeadlockTimeout *prometheus.Desc
resourceEmbeddedFailureAction *prometheus.Desc
resourceFlags *prometheus.Desc
resourceIsAlivePollInterval *prometheus.Desc
resourceLooksAlivePollInterval *prometheus.Desc
resourceMonitorProcessId *prometheus.Desc
resourceOwnerNode *prometheus.Desc
resourcePendingTimeout *prometheus.Desc
resourceResourceClass *prometheus.Desc
resourceRestartAction *prometheus.Desc
resourceRestartDelay *prometheus.Desc
resourceRestartPeriod *prometheus.Desc
resourceRestartThreshold *prometheus.Desc
resourceRetryPeriodOnFailure *prometheus.Desc
resourceState *prometheus.Desc
resourceSubClass *prometheus.Desc
// ResourceGroup
resourceGroupAutoFailbackType *prometheus.Desc
resourceGroupCharacteristics *prometheus.Desc
resourceGroupColdStartSetting *prometheus.Desc
resourceGroupDefaultOwner *prometheus.Desc
resourceGroupFailbackWindowEnd *prometheus.Desc
resourceGroupFailbackWindowStart *prometheus.Desc
resourceGroupFailOverPeriod *prometheus.Desc
resourceGroupFailOverThreshold *prometheus.Desc
resourceGroupFlags *prometheus.Desc
resourceGroupGroupType *prometheus.Desc
resourceGroupOwnerNode *prometheus.Desc
resourceGroupPriority *prometheus.Desc
resourceGroupResiliencyPeriod *prometheus.Desc
resourceGroupState *prometheus.Desc
collectorCluster
collectorNetwork
collectorNode
collectorResource
collectorResourceGroup
}
func New(config *Config) *Collector {
@@ -217,7 +88,7 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{"Memory"}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
@@ -257,7 +128,7 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
if len(c.config.CollectorsEnabled) == 0 {
return nil
}

View File

@@ -1,3 +1,5 @@
//go:build windows
package mscluster
import (
@@ -11,6 +13,86 @@ import (
const nameCluster = Name + "_cluster"
type collectorCluster struct {
clusterAddEvictDelay *prometheus.Desc
clusterAdminAccessPoint *prometheus.Desc
clusterAutoAssignNodeSite *prometheus.Desc
clusterAutoBalancerLevel *prometheus.Desc
clusterAutoBalancerMode *prometheus.Desc
clusterBackupInProgress *prometheus.Desc
clusterBlockCacheSize *prometheus.Desc
clusterClusSvcHangTimeout *prometheus.Desc
clusterClusSvcRegroupOpeningTimeout *prometheus.Desc
clusterClusSvcRegroupPruningTimeout *prometheus.Desc
clusterClusSvcRegroupStageTimeout *prometheus.Desc
clusterClusSvcRegroupTickInMilliseconds *prometheus.Desc
clusterClusterEnforcedAntiAffinity *prometheus.Desc
clusterClusterFunctionalLevel *prometheus.Desc
clusterClusterGroupWaitDelay *prometheus.Desc
clusterClusterLogLevel *prometheus.Desc
clusterClusterLogSize *prometheus.Desc
clusterClusterUpgradeVersion *prometheus.Desc
clusterCrossSiteDelay *prometheus.Desc
clusterCrossSiteThreshold *prometheus.Desc
clusterCrossSubnetDelay *prometheus.Desc
clusterCrossSubnetThreshold *prometheus.Desc
clusterCsvBalancer *prometheus.Desc
clusterDatabaseReadWriteMode *prometheus.Desc
clusterDefaultNetworkRole *prometheus.Desc
clusterDetectedCloudPlatform *prometheus.Desc
clusterDetectManagedEvents *prometheus.Desc
clusterDetectManagedEventsThreshold *prometheus.Desc
clusterDisableGroupPreferredOwnerRandomization *prometheus.Desc
clusterDrainOnShutdown *prometheus.Desc
clusterDynamicQuorumEnabled *prometheus.Desc
clusterEnableSharedVolumes *prometheus.Desc
clusterFixQuorum *prometheus.Desc
clusterGracePeriodEnabled *prometheus.Desc
clusterGracePeriodTimeout *prometheus.Desc
clusterGroupDependencyTimeout *prometheus.Desc
clusterHangRecoveryAction *prometheus.Desc
clusterIgnorePersistentStateOnStartup *prometheus.Desc
clusterLogResourceControls *prometheus.Desc
clusterLowerQuorumPriorityNodeId *prometheus.Desc
clusterMaxNumberOfNodes *prometheus.Desc
clusterMessageBufferLength *prometheus.Desc
clusterMinimumNeverPreemptPriority *prometheus.Desc
clusterMinimumPreemptorPriority *prometheus.Desc
clusterNetftIPSecEnabled *prometheus.Desc
clusterPlacementOptions *prometheus.Desc
clusterPlumbAllCrossSubnetRoutes *prometheus.Desc
clusterPreventQuorum *prometheus.Desc
clusterQuarantineDuration *prometheus.Desc
clusterQuarantineThreshold *prometheus.Desc
clusterQuorumArbitrationTimeMax *prometheus.Desc
clusterQuorumArbitrationTimeMin *prometheus.Desc
clusterQuorumLogFileSize *prometheus.Desc
clusterQuorumTypeValue *prometheus.Desc
clusterRequestReplyTimeout *prometheus.Desc
clusterResiliencyDefaultPeriod *prometheus.Desc
clusterResiliencyLevel *prometheus.Desc
clusterResourceDllDeadlockPeriod *prometheus.Desc
clusterRootMemoryReserved *prometheus.Desc
clusterRouteHistoryLength *prometheus.Desc
clusterS2DBusTypes *prometheus.Desc
clusterS2DCacheDesiredState *prometheus.Desc
clusterS2DCacheFlashReservePercent *prometheus.Desc
clusterS2DCachePageSizeKBytes *prometheus.Desc
clusterS2DEnabled *prometheus.Desc
clusterS2DIOLatencyThreshold *prometheus.Desc
clusterS2DOptimizations *prometheus.Desc
clusterSameSubnetDelay *prometheus.Desc
clusterSameSubnetThreshold *prometheus.Desc
clusterSecurityLevel *prometheus.Desc
clusterSecurityLevelForStorage *prometheus.Desc
clusterSharedVolumeVssWriterOperationTimeout *prometheus.Desc
clusterShutdownTimeoutInMinutes *prometheus.Desc
clusterUseClientAccessNetworksForSharedVolumes *prometheus.Desc
clusterWitnessDatabaseWriteTimeout *prometheus.Desc
clusterWitnessDynamicWeight *prometheus.Desc
clusterWitnessRestartInterval *prometheus.Desc
}
// msClusterCluster represents the MSCluster_Cluster WMI class
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-cluster
type msClusterCluster struct {

View File

@@ -1,3 +1,5 @@
//go:build windows
package mscluster
import (
@@ -11,6 +13,14 @@ import (
const nameNetwork = Name + "_network"
type collectorNetwork struct {
networkCharacteristics *prometheus.Desc
networkFlags *prometheus.Desc
networkMetric *prometheus.Desc
networkRole *prometheus.Desc
networkState *prometheus.Desc
}
// msClusterNetwork represents the MSCluster_Network WMI class
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network
type msClusterNetwork struct {

View File

@@ -1,3 +1,5 @@
//go:build windows
package mscluster
import (
@@ -11,6 +13,23 @@ import (
const nameNode = Name + "_node"
type collectorNode struct {
nodeBuildNumber *prometheus.Desc
nodeCharacteristics *prometheus.Desc
nodeDetectedCloudPlatform *prometheus.Desc
nodeDynamicWeight *prometheus.Desc
nodeFlags *prometheus.Desc
nodeMajorVersion *prometheus.Desc
nodeMinorVersion *prometheus.Desc
nodeNeedsPreventQuorum *prometheus.Desc
nodeNodeDrainStatus *prometheus.Desc
nodeNodeHighestVersion *prometheus.Desc
nodeNodeLowestVersion *prometheus.Desc
nodeNodeWeight *prometheus.Desc
nodeState *prometheus.Desc
nodeStatusInformation *prometheus.Desc
}
// msClusterNode represents the MSCluster_Node WMI class
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node
type msClusterNode struct {

View File

@@ -1,3 +1,5 @@
//go:build windows
package mscluster
import (
@@ -11,6 +13,26 @@ import (
const nameResource = Name + "_resource"
type collectorResource struct {
resourceCharacteristics *prometheus.Desc
resourceDeadlockTimeout *prometheus.Desc
resourceEmbeddedFailureAction *prometheus.Desc
resourceFlags *prometheus.Desc
resourceIsAlivePollInterval *prometheus.Desc
resourceLooksAlivePollInterval *prometheus.Desc
resourceMonitorProcessId *prometheus.Desc
resourceOwnerNode *prometheus.Desc
resourcePendingTimeout *prometheus.Desc
resourceResourceClass *prometheus.Desc
resourceRestartAction *prometheus.Desc
resourceRestartDelay *prometheus.Desc
resourceRestartPeriod *prometheus.Desc
resourceRestartThreshold *prometheus.Desc
resourceRetryPeriodOnFailure *prometheus.Desc
resourceState *prometheus.Desc
resourceSubClass *prometheus.Desc
}
// msClusterResource represents the MSCluster_Resource WMI class
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource
type msClusterResource struct {

View File

@@ -1,3 +1,5 @@
//go:build windows
package mscluster
import (
@@ -11,6 +13,23 @@ import (
const nameResourceGroup = Name + "_resourcegroup"
type collectorResourceGroup struct {
resourceGroupAutoFailbackType *prometheus.Desc
resourceGroupCharacteristics *prometheus.Desc
resourceGroupColdStartSetting *prometheus.Desc
resourceGroupDefaultOwner *prometheus.Desc
resourceGroupFailbackWindowEnd *prometheus.Desc
resourceGroupFailbackWindowStart *prometheus.Desc
resourceGroupFailOverPeriod *prometheus.Desc
resourceGroupFailOverThreshold *prometheus.Desc
resourceGroupFlags *prometheus.Desc
resourceGroupGroupType *prometheus.Desc
resourceGroupOwnerNode *prometheus.Desc
resourceGroupPriority *prometheus.Desc
resourceGroupResiliencyPeriod *prometheus.Desc
resourceGroupState *prometheus.Desc
}
// msClusterResourceGroup represents the MSCluster_ResourceGroup WMI class
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup
type msClusterResourceGroup struct {

View File

@@ -68,11 +68,7 @@ func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close(_ *slog.Logger) error {
func (c *Collector) Close() error {
return nil
}
@@ -117,21 +113,6 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
return nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
logger = logger.With(slog.String("collector", Name))
if err := c.collect(ch); err != nil {
logger.Error("failed collecting msmq metrics",
slog.Any("err", err),
)
return err
}
return nil
}
type msmqQueue struct {
Name string `mi:"Name"`
@@ -141,7 +122,9 @@ type msmqQueue struct {
MessagesInQueue uint64 `mi:"MessagesInQueue"`
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
var dst []msmqQueue
query := "SELECT * FROM Win32_PerfRawData_MSMQ_MSMQQueue"

View File

@@ -1,10 +1,12 @@
//go:build windows
package msmq_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/msmq"
"github.com/prometheus-community/windows_exporter/internal/testutils"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,766 @@
//go:build windows
package mssql
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
type collectorAccessMethods struct {
accessMethodsPerfDataCollectors map[string]*perfdata.Collector
accessMethodsAUcleanupbatches *prometheus.Desc
accessMethodsAUcleanups *prometheus.Desc
accessMethodsByReferenceLobCreateCount *prometheus.Desc
accessMethodsByReferenceLobUseCount *prometheus.Desc
accessMethodsCountLobReadahead *prometheus.Desc
accessMethodsCountPullInRow *prometheus.Desc
accessMethodsCountPushOffRow *prometheus.Desc
accessMethodsDeferreddroppedAUs *prometheus.Desc
accessMethodsDeferredDroppedrowsets *prometheus.Desc
accessMethodsDroppedrowsetcleanups *prometheus.Desc
accessMethodsDroppedrowsetsskipped *prometheus.Desc
accessMethodsExtentDeallocations *prometheus.Desc
accessMethodsExtentsAllocated *prometheus.Desc
accessMethodsFailedAUcleanupbatches *prometheus.Desc
accessMethodsFailedleafpagecookie *prometheus.Desc
accessMethodsFailedtreepagecookie *prometheus.Desc
accessMethodsForwardedRecords *prometheus.Desc
accessMethodsFreeSpacePageFetches *prometheus.Desc
accessMethodsFreeSpaceScans *prometheus.Desc
accessMethodsFullScans *prometheus.Desc
accessMethodsIndexSearches *prometheus.Desc
accessMethodsInSysXactwaits *prometheus.Desc
accessMethodsLobHandleCreateCount *prometheus.Desc
accessMethodsLobHandleDestroyCount *prometheus.Desc
accessMethodsLobSSProviderCreateCount *prometheus.Desc
accessMethodsLobSSProviderDestroyCount *prometheus.Desc
accessMethodsLobSSProviderTruncationCount *prometheus.Desc
accessMethodsMixedPageAllocations *prometheus.Desc
accessMethodsPageCompressionAttempts *prometheus.Desc
accessMethodsPageDeallocations *prometheus.Desc
accessMethodsPagesAllocated *prometheus.Desc
accessMethodsPagesCompressed *prometheus.Desc
accessMethodsPageSplits *prometheus.Desc
accessMethodsProbeScans *prometheus.Desc
accessMethodsRangeScans *prometheus.Desc
accessMethodsScanPointRevalidations *prometheus.Desc
accessMethodsSkippedGhostedRecords *prometheus.Desc
accessMethodsTableLockEscalations *prometheus.Desc
accessMethodsUsedleafpagecookie *prometheus.Desc
accessMethodsUsedtreepagecookie *prometheus.Desc
accessMethodsWorkfilesCreated *prometheus.Desc
accessMethodsWorktablesCreated *prometheus.Desc
accessMethodsWorktablesFromCacheHits *prometheus.Desc
accessMethodsWorktablesFromCacheLookups *prometheus.Desc
}
const (
accessMethodsAUCleanupbatchesPerSec = "AU cleanup batches/sec"
accessMethodsAUCleanupsPerSec = "AU cleanups/sec"
accessMethodsByReferenceLobCreateCount = "By-reference Lob Create Count"
accessMethodsByReferenceLobUseCount = "By-reference Lob Use Count"
accessMethodsCountLobReadahead = "Count Lob Readahead"
accessMethodsCountPullInRow = "Count Pull In Row"
accessMethodsCountPushOffRow = "Count Push Off Row"
accessMethodsDeferredDroppedAUs = "Deferred dropped AUs"
accessMethodsDeferredDroppedRowsets = "Deferred Dropped rowsets"
accessMethodsDroppedRowsetCleanupsPerSec = "Dropped rowset cleanups/sec"
accessMethodsDroppedRowsetsSkippedPerSec = "Dropped rowsets skipped/sec"
accessMethodsExtentDeallocationsPerSec = "Extent Deallocations/sec"
accessMethodsExtentsAllocatedPerSec = "Extents Allocated/sec"
accessMethodsFailedAUCleanupBatchesPerSec = "Failed AU cleanup batches/sec"
accessMethodsFailedLeafPageCookie = "Failed leaf page cookie"
accessMethodsFailedTreePageCookie = "Failed tree page cookie"
accessMethodsForwardedRecordsPerSec = "Forwarded Records/sec"
accessMethodsFreeSpacePageFetchesPerSec = "FreeSpace Page Fetches/sec"
accessMethodsFreeSpaceScansPerSec = "FreeSpace Scans/sec"
accessMethodsFullScansPerSec = "Full Scans/sec"
accessMethodsIndexSearchesPerSec = "Index Searches/sec"
accessMethodsInSysXactWaitsPerSec = "InSysXact waits/sec"
accessMethodsLobHandleCreateCount = "LobHandle Create Count"
accessMethodsLobHandleDestroyCount = "LobHandle Destroy Count"
accessMethodsLobSSProviderCreateCount = "LobSS Provider Create Count"
accessMethodsLobSSProviderDestroyCount = "LobSS Provider Destroy Count"
accessMethodsLobSSProviderTruncationCount = "LobSS Provider Truncation Count"
accessMethodsMixedPageAllocationsPerSec = "Mixed page allocations/sec"
accessMethodsPageCompressionAttemptsPerSec = "Page compression attempts/sec"
accessMethodsPageDeallocationsPerSec = "Page Deallocations/sec"
accessMethodsPagesAllocatedPerSec = "Pages Allocated/sec"
accessMethodsPagesCompressedPerSec = "Pages compressed/sec"
accessMethodsPageSplitsPerSec = "Page Splits/sec"
accessMethodsProbeScansPerSec = "Probe Scans/sec"
accessMethodsRangeScansPerSec = "Range Scans/sec"
accessMethodsScanPointRevalidationsPerSec = "Scan Point Revalidations/sec"
accessMethodsSkippedGhostedRecordsPerSec = "Skipped Ghosted Records/sec"
accessMethodsTableLockEscalationsPerSec = "Table Lock Escalations/sec"
accessMethodsUsedLeafPageCookie = "Used leaf page cookie"
accessMethodsUsedTreePageCookie = "Used tree page cookie"
accessMethodsWorkfilesCreatedPerSec = "Workfiles Created/sec"
accessMethodsWorktablesCreatedPerSec = "Worktables Created/sec"
accessMethodsWorktablesFromCacheRatio = "Worktables From Cache Ratio"
accessMethodsWorktablesFromCacheRatioBase = "Worktables From Cache Base"
)
func (c *Collector) buildAccessMethods() error {
var err error
c.accessMethodsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
counters := []string{
accessMethodsAUCleanupbatchesPerSec,
accessMethodsAUCleanupsPerSec,
accessMethodsByReferenceLobCreateCount,
accessMethodsByReferenceLobUseCount,
accessMethodsCountLobReadahead,
accessMethodsCountPullInRow,
accessMethodsCountPushOffRow,
accessMethodsDeferredDroppedAUs,
accessMethodsDeferredDroppedRowsets,
accessMethodsDroppedRowsetCleanupsPerSec,
accessMethodsDroppedRowsetsSkippedPerSec,
accessMethodsExtentDeallocationsPerSec,
accessMethodsExtentsAllocatedPerSec,
accessMethodsFailedAUCleanupBatchesPerSec,
accessMethodsFailedLeafPageCookie,
accessMethodsFailedTreePageCookie,
accessMethodsForwardedRecordsPerSec,
accessMethodsFreeSpacePageFetchesPerSec,
accessMethodsFreeSpaceScansPerSec,
accessMethodsFullScansPerSec,
accessMethodsIndexSearchesPerSec,
accessMethodsInSysXactWaitsPerSec,
accessMethodsLobHandleCreateCount,
accessMethodsLobHandleDestroyCount,
accessMethodsLobSSProviderCreateCount,
accessMethodsLobSSProviderDestroyCount,
accessMethodsLobSSProviderTruncationCount,
accessMethodsMixedPageAllocationsPerSec,
accessMethodsPageCompressionAttemptsPerSec,
accessMethodsPageDeallocationsPerSec,
accessMethodsPagesAllocatedPerSec,
accessMethodsPagesCompressedPerSec,
accessMethodsPageSplitsPerSec,
accessMethodsProbeScansPerSec,
accessMethodsRangeScansPerSec,
accessMethodsScanPointRevalidationsPerSec,
accessMethodsSkippedGhostedRecordsPerSec,
accessMethodsTableLockEscalationsPerSec,
accessMethodsUsedLeafPageCookie,
accessMethodsUsedTreePageCookie,
accessMethodsWorkfilesCreatedPerSec,
accessMethodsWorktablesCreatedPerSec,
accessMethodsWorktablesFromCacheRatio,
accessMethodsWorktablesFromCacheRatioBase,
}
for sqlInstance := range c.mssqlInstances {
c.accessMethodsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Access Methods"), nil, counters)
if err != nil {
return fmt.Errorf("failed to create AccessMethods collector for instance %s: %w", sqlInstance, err)
}
}
// Win32_PerfRawData_{instance}_SQLServerAccessMethods
c.accessMethodsAUcleanupbatches = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_au_batch_cleanups"),
"(AccessMethods.AUcleanupbatches)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsAUcleanups = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_au_cleanups"),
"(AccessMethods.AUcleanups)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsByReferenceLobCreateCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_by_reference_lob_creates"),
"(AccessMethods.ByreferenceLobCreateCount)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsByReferenceLobUseCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_by_reference_lob_uses"),
"(AccessMethods.ByreferenceLobUseCount)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsCountLobReadahead = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_read_aheads"),
"(AccessMethods.CountLobReadahead)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsCountPullInRow = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_column_value_pulls"),
"(AccessMethods.CountPullInRow)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsCountPushOffRow = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_column_value_pushes"),
"(AccessMethods.CountPushOffRow)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsDeferreddroppedAUs = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_deferred_dropped_aus"),
"(AccessMethods.DeferreddroppedAUs)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsDeferredDroppedrowsets = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_deferred_dropped_rowsets"),
"(AccessMethods.DeferredDroppedrowsets)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsDroppedrowsetcleanups = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_dropped_rowset_cleanups"),
"(AccessMethods.Droppedrowsetcleanups)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsDroppedrowsetsskipped = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_dropped_rowset_skips"),
"(AccessMethods.Droppedrowsetsskipped)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsExtentDeallocations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_extent_deallocations"),
"(AccessMethods.ExtentDeallocations)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsExtentsAllocated = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_extent_allocations"),
"(AccessMethods.ExtentsAllocated)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsFailedAUcleanupbatches = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_au_batch_cleanup_failures"),
"(AccessMethods.FailedAUcleanupbatches)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsFailedleafpagecookie = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_leaf_page_cookie_failures"),
"(AccessMethods.Failedleafpagecookie)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsFailedtreepagecookie = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_tree_page_cookie_failures"),
"(AccessMethods.Failedtreepagecookie)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsForwardedRecords = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_forwarded_records"),
"(AccessMethods.ForwardedRecords)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsFreeSpacePageFetches = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_free_space_page_fetches"),
"(AccessMethods.FreeSpacePageFetches)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsFreeSpaceScans = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_free_space_scans"),
"(AccessMethods.FreeSpaceScans)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsFullScans = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_full_scans"),
"(AccessMethods.FullScans)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsIndexSearches = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_index_searches"),
"(AccessMethods.IndexSearches)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsInSysXactwaits = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_insysxact_waits"),
"(AccessMethods.InSysXactwaits)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsLobHandleCreateCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_handle_creates"),
"(AccessMethods.LobHandleCreateCount)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsLobHandleDestroyCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_handle_destroys"),
"(AccessMethods.LobHandleDestroyCount)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsLobSSProviderCreateCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_ss_provider_creates"),
"(AccessMethods.LobSSProviderCreateCount)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsLobSSProviderDestroyCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_ss_provider_destroys"),
"(AccessMethods.LobSSProviderDestroyCount)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsLobSSProviderTruncationCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_ss_provider_truncations"),
"(AccessMethods.LobSSProviderTruncationCount)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsMixedPageAllocations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_mixed_page_allocations"),
"(AccessMethods.MixedpageallocationsPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsPageCompressionAttempts = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_page_compression_attempts"),
"(AccessMethods.PagecompressionattemptsPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsPageDeallocations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_page_deallocations"),
"(AccessMethods.PageDeallocationsPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsPagesAllocated = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_page_allocations"),
"(AccessMethods.PagesAllocatedPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsPagesCompressed = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_page_compressions"),
"(AccessMethods.PagescompressedPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsPageSplits = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_page_splits"),
"(AccessMethods.PageSplitsPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsProbeScans = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_probe_scans"),
"(AccessMethods.ProbeScansPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsRangeScans = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_range_scans"),
"(AccessMethods.RangeScansPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsScanPointRevalidations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_scan_point_revalidations"),
"(AccessMethods.ScanPointRevalidationsPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsSkippedGhostedRecords = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_ghost_record_skips"),
"(AccessMethods.SkippedGhostedRecordsPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsTableLockEscalations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_table_lock_escalations"),
"(AccessMethods.TableLockEscalationsPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsUsedleafpagecookie = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_leaf_page_cookie_uses"),
"(AccessMethods.Usedleafpagecookie)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsUsedtreepagecookie = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_tree_page_cookie_uses"),
"(AccessMethods.Usedtreepagecookie)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsWorkfilesCreated = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_workfile_creates"),
"(AccessMethods.WorkfilesCreatedPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsWorktablesCreated = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_worktables_creates"),
"(AccessMethods.WorktablesCreatedPersec)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsWorktablesFromCacheHits = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_worktables_from_cache_hits"),
"(AccessMethods.WorktablesFromCacheRatio)",
[]string{"mssql_instance"},
nil,
)
c.accessMethodsWorktablesFromCacheLookups = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accessmethods_worktables_from_cache_lookups"),
"(AccessMethods.WorktablesFromCacheRatio_Base)",
[]string{"mssql_instance"},
nil,
)
return nil
}
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 string, perfDataCollector *perfdata.Collector) error {
perfData, err := perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "AccessMethods"), err)
}
data, ok := perfData[perfdata.EmptyInstance]
if !ok {
return fmt.Errorf("perflib query for %s returned empty result set", c.mssqlGetPerfObjectName(sqlInstance, "AccessMethods"))
}
ch <- prometheus.MustNewConstMetric(
c.accessMethodsAUcleanupbatches,
prometheus.CounterValue,
data[accessMethodsAUCleanupbatchesPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsAUcleanups,
prometheus.CounterValue,
data[accessMethodsAUCleanupsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsByReferenceLobCreateCount,
prometheus.CounterValue,
data[accessMethodsByReferenceLobCreateCount].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsByReferenceLobUseCount,
prometheus.CounterValue,
data[accessMethodsByReferenceLobUseCount].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsCountLobReadahead,
prometheus.CounterValue,
data[accessMethodsCountLobReadahead].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsCountPullInRow,
prometheus.CounterValue,
data[accessMethodsCountPullInRow].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsCountPushOffRow,
prometheus.CounterValue,
data[accessMethodsCountPushOffRow].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsDeferreddroppedAUs,
prometheus.GaugeValue,
data[accessMethodsDeferredDroppedAUs].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsDeferredDroppedrowsets,
prometheus.GaugeValue,
data[accessMethodsDeferredDroppedRowsets].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsDroppedrowsetcleanups,
prometheus.CounterValue,
data[accessMethodsDroppedRowsetCleanupsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsDroppedrowsetsskipped,
prometheus.CounterValue,
data[accessMethodsDroppedRowsetsSkippedPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsExtentDeallocations,
prometheus.CounterValue,
data[accessMethodsExtentDeallocationsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsExtentsAllocated,
prometheus.CounterValue,
data[accessMethodsExtentsAllocatedPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsFailedAUcleanupbatches,
prometheus.CounterValue,
data[accessMethodsFailedAUCleanupBatchesPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsFailedleafpagecookie,
prometheus.CounterValue,
data[accessMethodsFailedLeafPageCookie].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsFailedtreepagecookie,
prometheus.CounterValue,
data[accessMethodsFailedTreePageCookie].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsForwardedRecords,
prometheus.CounterValue,
data[accessMethodsForwardedRecordsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsFreeSpacePageFetches,
prometheus.CounterValue,
data[accessMethodsFreeSpacePageFetchesPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsFreeSpaceScans,
prometheus.CounterValue,
data[accessMethodsFreeSpaceScansPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsFullScans,
prometheus.CounterValue,
data[accessMethodsFullScansPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsIndexSearches,
prometheus.CounterValue,
data[accessMethodsIndexSearchesPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsInSysXactwaits,
prometheus.CounterValue,
data[accessMethodsInSysXactWaitsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsLobHandleCreateCount,
prometheus.CounterValue,
data[accessMethodsLobHandleCreateCount].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsLobHandleDestroyCount,
prometheus.CounterValue,
data[accessMethodsLobHandleDestroyCount].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsLobSSProviderCreateCount,
prometheus.CounterValue,
data[accessMethodsLobSSProviderCreateCount].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsLobSSProviderDestroyCount,
prometheus.CounterValue,
data[accessMethodsLobSSProviderDestroyCount].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsLobSSProviderTruncationCount,
prometheus.CounterValue,
data[accessMethodsLobSSProviderTruncationCount].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsMixedPageAllocations,
prometheus.CounterValue,
data[accessMethodsMixedPageAllocationsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsPageCompressionAttempts,
prometheus.CounterValue,
data[accessMethodsPageCompressionAttemptsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsPageDeallocations,
prometheus.CounterValue,
data[accessMethodsPageDeallocationsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsPagesAllocated,
prometheus.CounterValue,
data[accessMethodsPagesAllocatedPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsPagesCompressed,
prometheus.CounterValue,
data[accessMethodsPagesCompressedPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsPageSplits,
prometheus.CounterValue,
data[accessMethodsPageSplitsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsProbeScans,
prometheus.CounterValue,
data[accessMethodsProbeScansPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsRangeScans,
prometheus.CounterValue,
data[accessMethodsRangeScansPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsScanPointRevalidations,
prometheus.CounterValue,
data[accessMethodsScanPointRevalidationsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsSkippedGhostedRecords,
prometheus.CounterValue,
data[accessMethodsSkippedGhostedRecordsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsTableLockEscalations,
prometheus.CounterValue,
data[accessMethodsTableLockEscalationsPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsUsedleafpagecookie,
prometheus.CounterValue,
data[accessMethodsUsedLeafPageCookie].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsUsedtreepagecookie,
prometheus.CounterValue,
data[accessMethodsUsedTreePageCookie].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsWorkfilesCreated,
prometheus.CounterValue,
data[accessMethodsWorkfilesCreatedPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsWorktablesCreated,
prometheus.CounterValue,
data[accessMethodsWorktablesCreatedPerSec].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsWorktablesFromCacheHits,
prometheus.CounterValue,
data[accessMethodsWorktablesFromCacheRatio].FirstValue,
sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.accessMethodsWorktablesFromCacheLookups,
prometheus.CounterValue,
data[accessMethodsWorktablesFromCacheRatioBase].SecondValue,
sqlInstance,
)
return nil
}
func (c *Collector) closeAccessMethods() {
for _, perfDataCollector := range c.accessMethodsPerfDataCollectors {
perfDataCollector.Close()
}
}

Some files were not shown because too many files have changed in this diff Show More