mssql: fix units and types of cumulative and current counters (#2723)

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
Jan-Otto Kröpke
2026-10-15 20:52:17 +02:00
committed by GitHub
parent 11aa13bb2f
commit 8c33aba631
12 changed files with 634 additions and 227 deletions
+32 -5
View File
@@ -17,9 +17,9 @@ Most installations need no changes. Go through the checklist below and read the
| You use the `container` collector | Replace `containerd-state-dir` with `cri-endpoint` | [container collector](#container-collector) |
| You query `windows_gpu_info` | Replace the `phys` label with `device_number` | [GPU collector](#gpu-collector) |
| You alert on BitLocker status | Replace `status="disabled"` with `status="off"` | [BitLocker status](#bitlocker-status) |
| You query Active Directory latency or security descriptor propagation, DFSR, DNS dynamic update, Hyper-V, logical disk queue, cache, IIS, memory, RemoteFX, scheduled task, SMB server share or terminal services metrics | Update queries | [Renamed, deprecated and retyped metrics](#renamed-deprecated-and-retyped-metrics) |
| You query Active Directory latency or security descriptor propagation, DFSR, DNS dynamic update, Hyper-V, logical disk queue, cache, IIS, memory, RemoteFX, SQL Server, scheduled task, SMB server share or terminal services metrics | Update queries | [Renamed, deprecated and retyped metrics](#renamed-deprecated-and-retyped-metrics) |
| You enable the `scheduled_task` collector and use tasks below `\Microsoft\` or missed runs | Set `--collector.scheduled_task.exclude` or `missed-runs` | [scheduled_task collector](#scheduled_task-collector) |
| You chart SQL Server latencies, SQL Server lock counts, DHCP denials, AD LSA writes, AD computer creations, AD FS database query times, DNS zone transfers or RemoteFX skipped frames | Expect corrected values | [Corrected values](#corrected-values) |
| You chart SQL Server latencies, lock counts or replica queues, DHCP denials, AD LSA writes, AD computer creations, AD FS database query times, DNS zone transfers or RemoteFX skipped frames | Expect corrected values | [Corrected values](#corrected-values) |
| You enable the `hyperv` or `mscluster` collector | Check the new default sub-collectors | [New default sub-collectors](#new-default-sub-collectors) |
| You set scrape timeouts above 5 minutes or below the timeout margin | Review the new limits | [Scrape timeouts](#scrape-timeouts) |
| You use the sample Grafana dashboard | Use Grafana 13 or later and import the new dashboard | [Dashboard and alerts](#dashboard-and-alerts) |
@@ -253,6 +253,28 @@ Renamed:
| `windows_iis_http_requests_arrival_rate` | `windows_iis_http_requests_arrived_total` | Was a running count, now a counter, use `rate()`; label `app` |
| `windows_iis_http_requests_max_queue_item_age` | `windows_iis_http_requests_max_queue_item_age_seconds` | Left out while the queue is empty; label `app` |
| `windows_dns_dynamic_updates_queued` | `windows_dns_dynamic_updates_queued_total` | Now a counter, use `rate()` |
| `windows_mssql_databases_log_flush_wait_seconds` | `windows_mssql_databases_log_flush_wait_seconds_total` | Now a counter, use `rate()` |
| `windows_mssql_databases_log_flush_write_seconds` | `windows_mssql_databases_log_flush_write_seconds_total` | Now a counter, use `rate()` |
| `windows_mssql_databases_log_growths` | `windows_mssql_databases_log_growths_total` | Now a counter, use `increase()` |
| `windows_mssql_databases_log_shrinks` | `windows_mssql_databases_log_shrinks_total` | Now a counter, use `increase()` |
| `windows_mssql_databases_log_truncations` | `windows_mssql_databases_log_truncations_total` | Now a counter, use `increase()` |
| `windows_mssql_databases_xtp_controller_dlc_fetch_latency_seconds` | `windows_mssql_databases_xtp_controller_dlc_fetch_latency_seconds_total` | Now a counter in seconds; divide its `rate()` by that of the new `windows_mssql_databases_xtp_controller_dlc_fetches_total` |
| `windows_mssql_dbreplica_database_flow_control_wait_seconds` | `windows_mssql_dbreplica_database_flow_control_wait_seconds_total` | Now a counter, use `rate()` |
| `windows_mssql_dbreplica_group_commit_stall_seconds` | `windows_mssql_dbreplica_group_commit_stall_seconds_total` | Now a counter, use `rate()` |
| `windows_mssql_dbreplica_transaction_delay_seconds` | `windows_mssql_dbreplica_transaction_delay_seconds_total` | Now a counter, use `rate()` |
| `windows_mssql_dbreplica_recovery_queue_records` | `windows_mssql_dbreplica_recovery_queue_bytes` | Was kilobytes, now bytes |
| `windows_mssql_dbreplica_log_send_queue` | `windows_mssql_dbreplica_log_send_queue_bytes` | Was kilobytes, now bytes |
| `windows_mssql_dbreplica_log_remaining_for_undo` | `windows_mssql_dbreplica_log_remaining_for_undo_bytes` | Was kilobytes, now bytes |
| `windows_mssql_dbreplica_total_log_requiring_undo` | `windows_mssql_dbreplica_total_log_requiring_undo_bytes` | Was kilobytes, now bytes |
| `windows_mssql_genstats_http_authenticated_requests`, `windows_mssql_genstats_mars_deadlocks`, `windows_mssql_genstats_soap_empty_requests`, `windows_mssql_genstats_soap_method_invocations`, `windows_mssql_genstats_soap_session_initiate_requests`, `windows_mssql_genstats_soap_session_terminate_requests`, `windows_mssql_genstats_soapsql_requests`, `windows_mssql_genstats_soapwsdl_requests`, `windows_mssql_genstats_sql_trace_io_provider_lock_waits`, `windows_mssql_genstats_tempdb_recovery_unit_ids_generated`, `windows_mssql_genstats_tempdb_rowset_ids_generated` | The same names with a `_total` suffix | Now counters, use `rate()` |
| `windows_mssql_locks_wait_time_seconds` | `windows_mssql_locks_wait_time_seconds_total` | Now a counter, use `rate()` |
| `windows_mssql_locks_count` | `windows_mssql_locks_count_total` | Now a counter, use `rate()` |
| `windows_mssql_locks_lock_wait_seconds` | `windows_mssql_locks_lock_wait_seconds_total` | Now a counter, use `rate()` |
| `windows_mssql_transactions_nonsnapshot_version_active_total` | `windows_mssql_transactions_nonsnapshot_version_active` | Now a gauge, query it directly |
| `windows_mssql_transactions_snapshot_active_total` | `windows_mssql_transactions_snapshot_active` | Now a gauge, query it directly |
| `windows_mssql_transactions_update_snapshot_active_total` | `windows_mssql_transactions_update_snapshot_active` | Now a gauge, query it directly |
| `windows_mssql_transactions_version_cleanup_rate_bytes` | `windows_mssql_transactions_version_cleanup_bytes_total` | Now a counter, use `rate()` |
| `windows_mssql_transactions_version_generation_rate_bytes` | `windows_mssql_transactions_version_generation_bytes_total` | Now a counter, use `rate()` |
The RemoteFX loss, FEC and retransmission gauges were not percentages. They exported the raw numerator of a Windows sample fraction, a running count that only grows.
The numerator and its base are now two counters. Get the ratio with `rate(windows_remote_fx_net_lost_packets_total[5m]) / rate(windows_remote_fx_net_loss_sampled_packets_total[5m])`, and likewise with `windows_remote_fx_net_fec_packets_total` / `windows_remote_fx_net_fec_sampled_packets_total` and `windows_remote_fx_net_retransmitted_packets_total` / `windows_remote_fx_net_retransmission_sampled_packets_total`.
@@ -297,10 +319,14 @@ Changed type, same name:
| `windows_cache_copy_read_hits_total` | gauge | counter |
| `windows_udp_datagram_received_total` | gauge | counter |
| `windows_hyperv_legacy_network_adapter_bytes_dropped_total` | gauge | counter |
| `windows_mssql_waitstats_*` (all 12 wait types) | counter | gauge |
| `windows_mssql_transactions_version_store_units` | counter | gauge |
The IIS and SMB values are current occupancy or, for `worker_max_threads`, the configured thread pool limit, so query them directly instead of with `rate()`.
If Prometheus scrapes with OpenMetrics, the IIS and SMB metrics were stored with a `_total` suffix, which counters get in that format. They now arrive without it.
If Prometheus scrapes with OpenMetrics, the IIS, SMB and SQL Server metrics above were stored with a `_total` suffix, which counters get in that format. They now arrive without it.
The cache, UDP and Hyper-V metrics already end in `_total`, so only their type metadata changes; `rate()` queries keep working.
The SQL Server wait statistics hold values that SQL Server computes over its last sampling interval (the `item` label names the statistic), and the version store unit count is a current value. Query them directly instead of with `rate()`.
The SQL Server metrics that gained a `_total` suffix hold running totals since the instance started, which 0.31 published as gauges.
Label changes on existing metrics:
@@ -317,11 +343,12 @@ Retired: `windows_net_route_info` was documented but never exported. It was remo
These metrics keep their names, but 0.31 reported wrong values. Graphs show a step at the upgrade.
- `windows_mssql_databases_xtp_controller_dlc_peak_latency_seconds`, `windows_mssql_dbreplica_database_flow_control_wait_seconds` and `windows_mssql_dbreplica_group_commit_stall_seconds` are now in seconds. SQL Server reports microseconds, which 0.31 did not convert correctly.
- `windows_mssql_locks_count` is no longer divided by 1000.
- `windows_ad_directory_operations_total{operation="write",origin="local_security_authority"}` now counts directory writes from the LSA. In 0.31 it repeated the LSA search count.
- `windows_ad_sam_computer_creation_requests_total` and `windows_ad_sam_computer_creation_successful_requests_total` were swapped in 0.31. Requests now count all attempts, successful requests only the successful ones.
- `windows_adfs_db_artifact_query_time_seconds_total` and `windows_adfs_db_config_query_time_seconds_total` are now in seconds. 0.31 scaled the raw ticks by a fixed `1e-8`, so on a typical 10 MHz time base the values were 10 times too small. The new `windows_adfs_db_artifact_queries_total` and `windows_adfs_db_config_queries_total` count the queries, so you can compute the average query time.
- `windows_mssql_databases_xtp_controller_dlc_peak_latency_seconds`, `windows_mssql_bufman_read_ahead_issuing_seconds`, `windows_mssql_dbreplica_database_flow_control_wait_seconds_total` and `windows_mssql_dbreplica_group_commit_stall_seconds_total` (renamed, see above) are now in seconds. SQL Server reports microseconds, which 0.31 did not convert correctly. `windows_mssql_databases_xtp_controller_dlc_fetch_latency_seconds_total` is converted from microseconds as well.
- `windows_mssql_locks_count_total` (renamed from `windows_mssql_locks_count`) is no longer divided by 1000.
- `windows_mssql_dbreplica_redo_remaining_bytes` is now in bytes. 0.31 exported kilobytes. The other renamed `windows_mssql_dbreplica_*_bytes` metrics are converted from kilobytes too.
- `windows_dhcp_denied_due_to_nonmatch_total` now counts denials due to a non-match. In 0.31 it repeated the match denial count.
- `windows_remote_fx_gfx_frames_skipped_insufficient_resource_total` with `resource="client"` and `resource="server"` now count the matching frames. In 0.31 the two label values were swapped.
- `windows_dns_zone_transfer_requests_sent_total{qtype="soa"}` now counts zone transfer SOA requests sent. In 0.31 it reported zone transfer requests received.
+86 -68
View File
@@ -75,8 +75,8 @@ Comma-separated list of MSSQL WMI classes to use. Supported values are `accessme
| `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_hits` | Number of pages found in the buffer cache without having to read from disk. Numerator of the Buffercachehitratio counter | gauge | `mssql_instance` |
| `windows_mssql_bufman_buffer_cache_lookups` | Number of buffer cache lookups. Denominator (base) of the Buffercachehitratio counter | gauge | `mssql_instance` |
| `windows_mssql_bufman_buffer_cache_hits` | Number of pages found in the buffer cache without a disk read, in the most recent sampling interval of SQL Server (a few seconds). Numerator of the Buffer cache hit ratio counter | gauge | `mssql_instance` |
| `windows_mssql_bufman_buffer_cache_lookups` | Number of buffer cache lookups in the most recent sampling interval of SQL Server (a few seconds). Base of the Buffer cache hit ratio counter | 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` |
@@ -95,13 +95,13 @@ Comma-separated list of MSSQL WMI classes to use. Supported values are `accessme
| `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_read_ahead_issuing_seconds` | Total time spent issuing read-ahead, in seconds | 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_flow_control_wait_seconds_total` | Total time spent in database flow control wait, in seconds | counter | `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_ | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_group_commit_stall_seconds_total` | Total time transactions waited for group commit, in seconds | 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` |
@@ -111,16 +111,16 @@ Comma-separated list of MSSQL WMI classes to use. Supported values are `accessme
| `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_log_remaining_for_undo_bytes` | The amount of log, in bytes, remaining to complete the undo phase | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_log_send_queue_bytes` | Amount of log, in bytes, in the log files of the primary database that has not 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_recovery_queue_bytes` | Amount of hardened log, in bytes, in the log files of the secondary replica that has 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_redo_remaining_bytes` | The amount of log, in bytes, 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_dbreplica_total_log_requiring_undo_bytes` | Total amount of log, in bytes, that must be undone | gauge | `mssql_instance`, `replica` |
| `windows_mssql_dbreplica_transaction_delay_seconds_total` | Total time transaction termination waited for commit acknowledgement, in seconds | counter | `mssql_instance`, `replica` |
| `windows_mssql_databases_active_transactions` | Number of active transactions for the database | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_active_parallel_redo_threads` | Number of active parallel redo threads | 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` |
@@ -129,18 +129,18 @@ Comma-separated list of MSSQL WMI classes to use. Supported values are `accessme
| `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_group_commit_stall_seconds` | Total group commit stall time, in seconds | 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_hits` | Number of log cache reads satisfied from the log cache. Numerator of the LogCacheHitRatio counter | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_cache_lookups` | Number of log cache lookups. Denominator (base) of the LogCacheHitRatio counter | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_cache_hits` | Number of log cache reads satisfied from the log cache. Numerator of the Log Cache Hit Ratio counter | gauge | `mssql_instance`, `database` |
| `windows_mssql_databases_log_cache_lookups` | Number of log cache lookups. Base of the Log Cache Hit Ratio counter | 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_flushes` | Number of log flushes | 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_flush_wait_seconds_total` | Total time commits waited for log flushes, in seconds | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_flush_write_seconds_total` | Total time spent writing log flushes, in seconds | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_growths_total` | Total number of times the transaction log for the database has been expanded | counter | `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` |
@@ -156,8 +156,8 @@ Comma-separated list of MSSQL WMI classes to use. Supported values are `accessme
| `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_shrinks_total` | Total number of log shrinks for this database | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_log_truncations_total` | The number of times the transaction log has been truncated (in Simple Recovery Model) | counter | `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` |
@@ -165,42 +165,43 @@ Comma-separated list of MSSQL WMI classes to use. Supported values are `accessme
| `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_dlc_fetch_latency_seconds_total` | Total latency between log blocks entering the Direct Log Consumer and being retrieved by the XTP controller, in seconds. Numerator of the XTP Controller DLC Latency/Fetch counter | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_xtp_controller_dlc_fetches_total` | Total number of fetches from the Direct Log Consumer by the XTP controller. Base of the XTP Controller DLC Latency/Fetch counter | counter | `mssql_instance`, `database` |
| `windows_mssql_databases_xtp_controller_dlc_peak_latency_seconds` | The largest recorded latency, in seconds, 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_http_authenticated_requests_total` | Total number of authenticated HTTP requests started | counter | `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_mars_deadlocks_total` | Total number of MARS deadlocks detected | counter | `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_soap_empty_requests_total` | Total number of empty SOAP requests started | counter | `mssql_instance` |
| `windows_mssql_genstats_soap_method_invocations_total` | Total number of SOAP method invocations started | counter | `mssql_instance` |
| `windows_mssql_genstats_soap_session_initiate_requests_total` | Total number of SOAP Session initiate requests started | counter | `mssql_instance` |
| `windows_mssql_genstats_soap_session_terminate_requests_total` | Total number of SOAP Session terminate requests started | counter | `mssql_instance` |
| `windows_mssql_genstats_soapsql_requests_total` | Total number of SOAP SQL requests started | counter | `mssql_instance` |
| `windows_mssql_genstats_soapwsdl_requests_total` | Total number of SOAP Web Service Description Language requests started | counter | `mssql_instance` |
| `windows_mssql_genstats_sql_trace_io_provider_lock_waits_total` | Total number of waits for the File IO Provider lock | counter | `mssql_instance` |
| `windows_mssql_genstats_tempdb_recovery_unit_ids_generated_total` | Total number of duplicate tempdb recovery unit IDs generated | counter | `mssql_instance` |
| `windows_mssql_genstats_tempdb_rowset_ids_generated_total` | Total number of duplicate tempdb rowset IDs generated | counter | `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_instance_info` | A metric with a constant '1' value labeled with mssql instance information | gauge | `edition`, `mssql_instance`, `patch`, `version` |
| `windows_mssql_locks_wait_time_seconds` | Total time in seconds which locks have been holding resources. Numerator of the AverageWaitTimems counter | gauge | `mssql_instance`, `resource` |
| `windows_mssql_locks_count` | Count of how often requests have run into locks. Denominator (base) of the AverageWaitTimems counter | gauge | `mssql_instance`, `resource` |
| `windows_mssql_locks_wait_time_seconds_total` | Total time lock requests waited, in seconds. Numerator of the Average Wait Time (ms) counter | counter | `mssql_instance`, `resource` |
| `windows_mssql_locks_count_total` | Total number of lock requests that waited. Base of the Average Wait Time (ms) counter | counter | `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_lock_waits` | Number of lock requests that required the caller to wait | counter | `mssql_instance`, `resource` |
| `windows_mssql_locks_lock_wait_seconds_total` | Total time lock requests waited, in seconds | counter | `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` |
@@ -234,31 +235,32 @@ Comma-separated list of MSSQL WMI classes to use. Supported values are `accessme
| `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_tempdb_free_space_bytes` | The amount of space, in bytes, 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_nonsnapshot_version_active` | 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 | gauge | `mssql_instance` |
| `windows_mssql_transactions_snapshot_active` | The number of currently active transactions using the snapshot isolation level | gauge | `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_update_conflicts_total` | Total number of update snapshot transactions that had an update conflict. Numerator of the Update conflict ratio counter | counter | `mssql_instance` |
| `windows_mssql_transactions_update_snapshot_transactions_total` | Total number of update snapshot transactions. Base of the Update conflict ratio counter | counter | `mssql_instance` |
| `windows_mssql_transactions_update_snapshot_active` | The number of currently active transactions using the snapshot isolation level and have modified data | gauge | `mssql_instance` |
| `windows_mssql_transactions_version_cleanup_bytes_total` | Total size of row versions removed from the version store in tempdb, in bytes | counter | `mssql_instance` |
| `windows_mssql_transactions_version_generation_bytes_total` | Total size of row versions added to the version store in tempdb, in bytes | counter | `mssql_instance` |
| `windows_mssql_transactions_version_store_size_bytes` | The amount of space, in bytes, in tempdb 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 | gauge | `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 | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_memory_grant_queue_waits` | Statistics for processes waiting for memory grant to become available | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_thread_safe_memory_objects_waits` | Statistics for processes waiting on thread-safe memory allocators | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_log_write_waits` | Statistics for processes waiting for log buffer to be written | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_log_buffer_waits` | Statistics for processes waiting for log buffer to be available | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_network_io_waits` | Statistics relevant to wait on network I/O | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_page_io_latch_waits` | Statistics relevant to page I/O latches | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_page_latch_waits` | Statistics relevant to page latches, not including I/O latches | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_nonpage_latch_waits` | Statistics relevant to non-page latches | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_wait_for_the_worker_waits` | Statistics relevant to processes waiting for worker to become available | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_workspace_synchronization_waits` | Statistics relevant to processes synchronizing access to workspace | counter | `mssql_instance`, `item` |
| `windows_mssql_waitstats_transaction_ownership_waits` | Statistics relevant to processes synchronizing access to transaction | counter | `mssql_instance`, `item` |
| `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
@@ -288,16 +290,32 @@ windows_mssql_bufman_buffer_cache_hits{instance="host:9182", mssql_instance="MSS
windows_mssql_bufman_buffer_cache_lookups{instance="host:9182", mssql_instance="MSSQLSERVER"}
```
This principal can be used for following metrics too:
- AccessMethodsWorktablesFromCacheHitRatio
- accessmethods_worktables_from_cache_hits
- accessmethods_worktables_from_cache_lookups
- LogCacheHitRatio
- databases_log_cache_hits
- databases_log_cache_lookups
- AverageLockWaitTime
- locks_wait_time_seconds
- locks_count
SQL Server refreshes both values every few seconds with the hits and lookups of the last interval, so they are gauges and need no `rate()`.
The same applies to `databases_log_cache_hits` and `databases_log_cache_lookups`.
### Ratios and averages of running totals
The Worktables From Cache Ratio, Average Wait Time (ms), XTP Controller DLC Latency/Fetch and Update conflict ratio counters are running totals.
Divide the rates of numerator and base:
```
# Worktables From Cache Ratio
rate(windows_mssql_accessmethods_worktables_from_cache_hits[5m]) / rate(windows_mssql_accessmethods_worktables_from_cache_lookups[5m])
# Average lock wait time in seconds
rate(windows_mssql_locks_wait_time_seconds_total[5m]) / rate(windows_mssql_locks_count_total[5m])
# Average XTP controller DLC latency per fetch in seconds
rate(windows_mssql_databases_xtp_controller_dlc_fetch_latency_seconds_total[5m]) / rate(windows_mssql_databases_xtp_controller_dlc_fetches_total[5m])
# Update conflict ratio
rate(windows_mssql_transactions_update_conflicts_total[5m]) / rate(windows_mssql_transactions_update_snapshot_transactions_total[5m])
```
### Wait statistics
Each `windows_mssql_waitstats_*` metric is a wait type. The `item` label names the statistic: `Average wait time (ms)`, `Cumulative wait time (ms) per second`, `Waits in progress` and `Waits started per second`.
SQL Server computes them over its most recent sampling interval, so they are gauges. Values of the `(ms)` items are in milliseconds.
## Alerting examples
+13 -2
View File
@@ -3,7 +3,10 @@
The collector reads the SQL Server performance objects (`Access Methods`,
`Buffer Manager`, `Databases`, `Locks`, `Wait Statistics` and others) with
`pdh.CounterTypeRaw`, one PDH collector per SQL Server instance. It needs a
SQL Server Database Engine; CI does not provision one. These notes were
SQL Server Database Engine. CI provisions SQL Server Express (instance
`CISQL`, database `CIWindowsExporter`) and lists `mssql` in
`WINDOWS_EXPORTER_TEST_COLLECTORS`, so live tests must fail there instead of
skipping. Express has no availability groups. These notes were
recorded on Windows Server 2025 (build 26100) with SQL Server 2022 Developer
Edition (`PatchLevel` 16.0.1000.6), named instance `NONDEFAULT`.
@@ -35,7 +38,15 @@ Edition (`PatchLevel` 16.0.1000.6), named instance `NONDEFAULT`.
`Cumulative wait time (ms) per second`, `Waits in progress` and
`Waits started per second`. All counters are
`PERF_COUNTER_LARGE_RAWCOUNT`, so the meaning comes from the instance name.
All values stayed 0 over 10 seconds on this idle instance.
SQL Server recomputes every item about every 5 seconds over its last
interval. Under lock contention, `Waits started per second` showed 5 and
then 0 while `sys.dm_os_wait_stats` kept growing, so all items are gauges.
- `Buffer cache hit ratio` (`PERF_RAW_FRACTION`) is windowed as well: value
and base are the page lookups of the last refresh, so it is a gauge.
`Worktables From Cache Ratio` has a growing base and is a running total.
- `TestMetricTypesMatchCounterTypes` compares the published types with
`pdh.Collector.MetricType` against a live instance; deliberate exceptions
(`Log Growths`, `Log Shrinks`, `Log Truncations`) are listed there.
- Every `.../sec` counter, and several counters without `/sec` (for example
`Mars Deadlocks`, the `SOAP ...` and `Lob...Count` counters,
`Log Flush Wait Time`, `Group Commit Time`, `Transaction Delay`,
+318 -23
View File
@@ -18,51 +18,346 @@
package mssql
import (
"log/slog"
"os"
"slices"
"strings"
"testing"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
"github.com/stretchr/testify/require"
"golang.org/x/sys/windows/registry"
)
// emitCollector is an unchecked collector that publishes the metrics of emit.
type emitCollector func(ch chan<- prometheus.Metric)
func (emitCollector) Describe(chan<- *prometheus.Desc) {}
func (e emitCollector) Collect(ch chan<- prometheus.Metric) { e(ch) }
type wantMetric struct {
metricType dto.MetricType
value float64
}
func gatherFirstSeries(t *testing.T, collector prometheus.Collector) map[string]*dto.Metric {
t.Helper()
registry := prometheus.NewPedanticRegistry()
require.NoError(t, registry.Register(collector))
families, err := registry.Gather()
require.NoError(t, err)
series := make(map[string]*dto.Metric, len(families))
for _, family := range families {
require.NotEmpty(t, family.GetMetric())
series[family.GetName()] = family.GetMetric()[0]
}
return series
}
func metricValue(m *dto.Metric) (dto.MetricType, float64) {
if m.GetCounter() != nil {
return dto.MetricType_COUNTER, m.GetCounter().GetValue()
}
return dto.MetricType_GAUGE, m.GetGauge().GetValue()
}
func TestCounterUnitConversions(t *testing.T) {
t.Parallel()
c := New(nil)
c.logger = slog.New(slog.DiscardHandler)
// No SQL instances are needed to build the metric descriptors.
require.NoError(t, c.buildBufferManager())
require.NoError(t, c.buildDatabases())
require.NoError(t, c.buildDatabaseReplica())
require.NoError(t, c.buildGeneralStatistics())
require.NoError(t, c.buildLocks())
c.databasesPerfDataObject = []perfDataCounterValuesDatabases{{Name: "db", DatabasesXTPControllerDLCPeakLatency: 1000}}
c.dbReplicaPerfDataObject = []perfDataCounterValuesDBReplica{{Name: "replica", DbReplicaDatabaseFlowControlDelay: 1000, DbReplicaGroupCommitTime: 1000}}
c.locksPerfDataObject = []perfDataCounterValuesLocks{{Name: "locks", LocksAverageWaitTimeMSBase: 1000}}
require.NoError(t, c.buildTransactions())
require.NoError(t, c.buildWaitStats())
c.bufManPerfDataObject = []perfDataCounterValuesBufMan{{BufManReadaheadTimePerSec: 882}}
c.databasesPerfDataObject = []perfDataCounterValuesDatabases{{
Name: "db",
DatabasesLogFlushWaitTime: 4,
DatabasesLogFlushWriteTimeMS: 3,
DatabasesLogGrowths: 2,
DatabasesLogShrinks: 1,
DatabasesLogTruncations: 5,
DatabasesXTPControllerDLCLatencyPerFetch: 2500,
DatabasesXTPControllerDLCLatencyPerFetchBase: 5,
DatabasesXTPControllerDLCPeakLatency: 1000,
}}
c.dbReplicaPerfDataObject = []perfDataCounterValuesDBReplica{{
Name: "replica",
DbReplicaDatabaseFlowControlDelay: 1000,
DbReplicaGroupCommitTime: 1000,
DbReplicaTransactionDelay: 1500,
DbReplicaRecoveryQueue: 2,
DbReplicaRedoBytesRemaining: 3,
DbReplicaLogSendQueue: 4,
DbReplicaTotalLogRequiringUndo: 5,
DbReplicaLogRemainingForUndo: 6,
}}
c.genStatsPerfDataObject = []perfDataCounterValuesGenStats{{
GenStatsHTTPAuthenticatedRequests: 1,
GenStatsMarsDeadlocks: 2,
GenStatsSOAPEmptyRequests: 3,
GenStatsSOAPMethodInvocations: 4,
GenStatsSOAPSessionInitiateRequests: 5,
GenStatsSOAPSessionTerminateRequests: 6,
GenStatsSOAPSQLRequests: 7,
GenStatsSOAPWSDLRequests: 8,
GenStatsSQLTraceIOProviderLockWaits: 9,
GenStatsTempdbRecoveryUnitID: 10,
GenStatsTempdbRowsetID: 11,
}}
c.locksPerfDataObject = []perfDataCounterValuesLocks{{
Name: "locks",
LocksAverageWaitTimeMS: 499,
LocksAverageWaitTimeMSBase: 3,
LocksLockWaitTimeMS: 499,
}}
c.transactionsPerfDataObject = []perfDataCounterValuesTransactions{{
TransactionsNonSnapshotVersionTransactions: 1,
TransactionsSnapshotTransactions: 2,
TransactionsUpdateSnapshotTransactions: 3,
TransactionsUpdateconflictratio: 4,
TransactionsUpdateconflictratioBase: 8,
TransactionsVersionCleanuprateKBPers: 5,
TransactionsVersionGenerationrateKBPers: 6,
TransactionsVersionStoreunitcount: 7,
}}
c.waitStatsPerfDataObject = []perfDataCounterValuesWaitStats{{
Name: "Waits started per second",
WaitStatsNetworkIOWaits: 2194,
}}
instance := mssqlInstance{name: "test"}
metrics := make(chan prometheus.Metric, 200)
c.emitDatabasesMetrics(metrics, instance)
c.emitDatabaseReplicaMetrics(metrics, instance)
c.emitLocksMetrics(metrics, instance)
close(metrics)
series := gatherFirstSeries(t, emitCollector(func(ch chan<- prometheus.Metric) {
c.emitBufferManagerMetrics(ch, instance)
c.emitDatabasesMetrics(ch, instance)
c.emitDatabaseReplicaMetrics(ch, instance)
c.emitGeneralStatisticsMetrics(ch, instance)
c.emitLocksMetrics(ch, instance)
c.emitTransactionsMetrics(ch, instance)
c.emitWaitStatsMetrics(ch, instance)
}))
want := map[*prometheus.Desc]float64{
c.databasesXTPControllerDLCPeakLatency: 0.001,
c.dbReplicaDatabaseFlowControlDelay: 0.001,
c.dbReplicaGroupCommitTime: 0.001,
c.locksCount: 1000,
counter := dto.MetricType_COUNTER
gauge := dto.MetricType_GAUGE
want := map[string]wantMetric{
"windows_mssql_bufman_read_ahead_issuing_seconds": {counter, 882e-6},
"windows_mssql_databases_log_flush_wait_seconds_total": {counter, 0.004},
"windows_mssql_databases_log_flush_write_seconds_total": {counter, 0.003},
"windows_mssql_databases_log_growths_total": {counter, 2},
"windows_mssql_databases_log_shrinks_total": {counter, 1},
"windows_mssql_databases_log_truncations_total": {counter, 5},
"windows_mssql_databases_xtp_controller_dlc_fetch_latency_seconds_total": {counter, 0.0025},
"windows_mssql_databases_xtp_controller_dlc_fetches_total": {counter, 5},
"windows_mssql_databases_xtp_controller_dlc_peak_latency_seconds": {gauge, 0.001},
"windows_mssql_dbreplica_database_flow_control_wait_seconds_total": {counter, 0.001},
"windows_mssql_dbreplica_group_commit_stall_seconds_total": {counter, 0.001},
"windows_mssql_dbreplica_transaction_delay_seconds_total": {counter, 1.5},
"windows_mssql_dbreplica_recovery_queue_bytes": {gauge, 2048},
"windows_mssql_dbreplica_redo_remaining_bytes": {gauge, 3072},
"windows_mssql_dbreplica_log_send_queue_bytes": {gauge, 4096},
"windows_mssql_dbreplica_total_log_requiring_undo_bytes": {gauge, 5120},
"windows_mssql_dbreplica_log_remaining_for_undo_bytes": {gauge, 6144},
"windows_mssql_genstats_http_authenticated_requests_total": {counter, 1},
"windows_mssql_genstats_mars_deadlocks_total": {counter, 2},
"windows_mssql_genstats_soap_empty_requests_total": {counter, 3},
"windows_mssql_genstats_soap_method_invocations_total": {counter, 4},
"windows_mssql_genstats_soap_session_initiate_requests_total": {counter, 5},
"windows_mssql_genstats_soap_session_terminate_requests_total": {counter, 6},
"windows_mssql_genstats_soapsql_requests_total": {counter, 7},
"windows_mssql_genstats_soapwsdl_requests_total": {counter, 8},
"windows_mssql_genstats_sql_trace_io_provider_lock_waits_total": {counter, 9},
"windows_mssql_genstats_tempdb_recovery_unit_ids_generated_total": {counter, 10},
"windows_mssql_genstats_tempdb_rowset_ids_generated_total": {counter, 11},
"windows_mssql_locks_wait_time_seconds_total": {counter, 0.499},
"windows_mssql_locks_count_total": {counter, 3},
"windows_mssql_locks_lock_wait_seconds_total": {counter, 0.499},
"windows_mssql_transactions_nonsnapshot_version_active": {gauge, 1},
"windows_mssql_transactions_snapshot_active": {gauge, 2},
"windows_mssql_transactions_update_snapshot_active": {gauge, 3},
"windows_mssql_transactions_update_conflicts_total": {counter, 4},
"windows_mssql_transactions_update_snapshot_transactions_total": {counter, 8},
"windows_mssql_transactions_version_cleanup_bytes_total": {counter, 5120},
"windows_mssql_transactions_version_generation_bytes_total": {counter, 6144},
"windows_mssql_transactions_version_store_units": {gauge, 7},
"windows_mssql_waitstats_network_io_waits": {gauge, 2194},
"windows_mssql_waitstats_lock_waits": {gauge, 0},
}
found := make(map[*prometheus.Desc]bool)
for metric := range metrics {
expected, ok := want[metric.Desc()]
if !ok {
for name, expected := range want {
metric, ok := series[name]
require.True(t, ok, "metric %s not emitted", name)
metricType, value := metricValue(metric)
require.Equal(t, expected.metricType, metricType, name)
require.InDelta(t, expected.value, value, 1e-9, name)
}
for _, removed := range []string{
"windows_mssql_databases_log_flush_wait_seconds",
"windows_mssql_databases_log_growths",
"windows_mssql_databases_xtp_controller_dlc_fetch_latency_seconds",
"windows_mssql_dbreplica_recovery_queue_records",
"windows_mssql_dbreplica_log_send_queue",
"windows_mssql_locks_count",
"windows_mssql_transactions_snapshot_active_total",
"windows_mssql_transactions_version_cleanup_rate_bytes",
} {
require.NotContains(t, series, removed)
}
}
// TestMetricTypesMatchCounterTypes checks the published types of the metrics
// against the PDH counter types of a local SQL Server instance.
func TestMetricTypesMatchCounterTypes(t *testing.T) {
t.Parallel()
// Collectors provisioned by CI must not be skipped, see docs/ci-testing.md.
required := slices.Contains(strings.Split(os.Getenv("WINDOWS_EXPORTER_TEST_COLLECTORS"), ","), Name)
key, err := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Microsoft SQL Server\Instance Names\SQL`, registry.QUERY_VALUE)
if err != nil {
require.False(t, required, "mssql is required but no SQL Server instance was found: %v", err)
t.Skipf("no SQL Server instance: %v", err)
}
_ = key.Close()
c := New(nil)
t.Cleanup(func() { require.NoError(t, c.Close()) })
require.NoError(t, c.Build(slog.New(slog.DiscardHandler), nil))
if len(c.mssqlInstances) == 0 {
require.False(t, required, "mssql is required but no SQL Server instance was discovered")
t.Skip("no SQL Server instance")
}
instance := c.mssqlInstances[0]
type check struct {
metric string
counter string
// cumulative marks PERF_COUNTER_LARGE_RAWCOUNT counters whose help text
// says they are running totals, which PDH reports as gauges.
cumulative bool
metricType func(counter string) (prometheus.ValueType, bool)
}
bufMan := c.bufManPerfDataCollectors[instance].MetricType
databases := c.databasesPerfDataCollectors[instance].MetricType
dbReplica := c.dbReplicaPerfDataCollectors[instance].MetricType
genStats := c.genStatsPerfDataCollectors[instance].MetricType
locks := c.locksPerfDataCollectors[instance].MetricType
transactions := c.transactionsPerfDataCollectors[instance].MetricType
waitStats := c.waitStatsPerfDataCollectors[instance].MetricType
checks := []check{
{"windows_mssql_bufman_read_ahead_issuing_seconds", "Readahead time/sec", false, bufMan},
{"windows_mssql_databases_log_flush_wait_seconds_total", "Log Flush Wait Time", false, databases},
{"windows_mssql_databases_log_flush_write_seconds_total", "Log Flush Write Time (ms)", false, databases},
{"windows_mssql_databases_log_growths_total", "Log Growths", true, databases},
{"windows_mssql_databases_log_shrinks_total", "Log Shrinks", true, databases},
{"windows_mssql_databases_log_truncations_total", "Log Truncations", true, databases},
{"windows_mssql_dbreplica_database_flow_control_wait_seconds_total", "Database Flow Control Delay", false, dbReplica},
{"windows_mssql_dbreplica_group_commit_stall_seconds_total", "Group Commit Time", false, dbReplica},
{"windows_mssql_dbreplica_transaction_delay_seconds_total", "Transaction Delay", false, dbReplica},
{"windows_mssql_dbreplica_recovery_queue_bytes", "Recovery Queue", false, dbReplica},
{"windows_mssql_dbreplica_redo_remaining_bytes", "Redo Bytes Remaining", false, dbReplica},
{"windows_mssql_genstats_http_authenticated_requests_total", "HTTP Authenticated Requests", false, genStats},
{"windows_mssql_genstats_mars_deadlocks_total", "Mars Deadlocks", false, genStats},
{"windows_mssql_genstats_soap_empty_requests_total", "SOAP Empty Requests", false, genStats},
{"windows_mssql_genstats_soap_method_invocations_total", "SOAP Method Invocations", false, genStats},
{"windows_mssql_genstats_soap_session_initiate_requests_total", "SOAP Session Initiate Requests", false, genStats},
{"windows_mssql_genstats_soap_session_terminate_requests_total", "SOAP Session Terminate Requests", false, genStats},
{"windows_mssql_genstats_soapsql_requests_total", "SOAP SQL Requests", false, genStats},
{"windows_mssql_genstats_soapwsdl_requests_total", "SOAP WSDL Requests", false, genStats},
{"windows_mssql_genstats_sql_trace_io_provider_lock_waits_total", "SQL Trace IO Provider Lock Waits", false, genStats},
{"windows_mssql_genstats_tempdb_recovery_unit_ids_generated_total", "Tempdb recovery unit id", false, genStats},
{"windows_mssql_genstats_tempdb_rowset_ids_generated_total", "Tempdb rowset id", false, genStats},
{"windows_mssql_locks_lock_wait_seconds_total", "Lock Wait Time (ms)", false, locks},
{"windows_mssql_transactions_nonsnapshot_version_active", "NonSnapshot Version Transactions", false, transactions},
{"windows_mssql_transactions_snapshot_active", "Snapshot Transactions", false, transactions},
{"windows_mssql_transactions_update_snapshot_active", "Update Snapshot Transactions", false, transactions},
{"windows_mssql_transactions_version_cleanup_bytes_total", "Version Cleanup rate (KB/s)", false, transactions},
{"windows_mssql_transactions_version_generation_bytes_total", "Version Generation rate (KB/s)", false, transactions},
{"windows_mssql_transactions_version_store_units", "Version Store unit count", false, transactions},
{"windows_mssql_waitstats_lock_waits", "Lock waits", false, waitStats},
{"windows_mssql_waitstats_network_io_waits", "Network IO waits", false, waitStats},
}
metrics := make(chan prometheus.Metric)
collected := make([]prometheus.Metric, 0, 1024)
done := make(chan struct{})
go func() {
defer close(done)
for metric := range metrics {
collected = append(collected, metric)
}
}()
collectErr := c.Collect(metrics, 0)
close(metrics)
<-done
require.NoError(t, collectErr)
series := gatherFirstSeries(t, emitCollector(func(ch chan<- prometheus.Metric) {
for _, metric := range collected {
ch <- metric
}
}))
for _, check := range checks {
pdhType, ok := check.metricType(check.counter)
require.True(t, ok, "counter %s not found", check.counter)
if check.cumulative {
require.Equal(t, prometheus.GaugeValue, pdhType, check.counter)
pdhType = prometheus.CounterValue
}
want := dto.MetricType_GAUGE
if pdhType == prometheus.CounterValue {
want = dto.MetricType_COUNTER
}
metric, ok := series[check.metric]
if !ok && strings.HasPrefix(check.metric, "windows_mssql_dbreplica_") {
// Database Replica has only _Total without availability groups.
t.Logf("metric %s not emitted on this instance", check.metric)
continue
}
var value dto.Metric
require.NoError(t, metric.Write(&value))
require.InDelta(t, expected, value.GetGauge().GetValue(), 1e-9)
require.True(t, ok, "metric %s not emitted", check.metric)
found[metric.Desc()] = true
metricType, _ := metricValue(metric)
require.Equal(t, want, metricType, check.metric)
}
require.Len(t, found, len(want))
}
@@ -119,8 +119,10 @@ type perfDataCounterValuesAccessMethods struct {
AccessMethodsUsedTreePageCookie float64 `perfdata:"Used tree page cookie"`
AccessMethodsWorkfilesCreatedPerSec float64 `perfdata:"Workfiles Created/sec"`
AccessMethodsWorktablesCreatedPerSec float64 `perfdata:"Worktables Created/sec"`
AccessMethodsWorktablesFromCacheRatio float64 `perfdata:"Worktables From Cache Ratio"`
AccessMethodsWorktablesFromCacheRatioBase float64 `perfdata:"Worktables From Cache Ratio,secondvalue"`
// PERF_LARGE_RAW_FRACTION, but SQL Server keeps both values as running totals since
// the instance started, unlike Buffer cache hit ratio. Published as counters.
AccessMethodsWorktablesFromCacheRatio float64 `perfdata:"Worktables From Cache Ratio"`
AccessMethodsWorktablesFromCacheRatioBase float64 `perfdata:"Worktables From Cache Ratio,secondvalue"`
}
func (c *Collector) buildAccessMethods() error {
@@ -56,7 +56,9 @@ type collectorBufferManager struct {
}
type perfDataCounterValuesBufMan struct {
BufManBackgroundWriterPagesPerSec float64 `perfdata:"Background writer pages/sec"`
BufManBackgroundWriterPagesPerSec float64 `perfdata:"Background writer pages/sec"`
// PERF_LARGE_RAW_FRACTION. SQL Server refreshes value and base every few seconds with the
// hits and lookups of the last interval, so both are gauges.
BufManBufferCacheHitRatio float64 `perfdata:"Buffer cache hit ratio"`
BufManBufferCacheHitRatioBase float64 `perfdata:"Buffer cache hit ratio,secondvalue"`
BufManCheckpointPagesPerSec float64 `perfdata:"Checkpoint pages/sec"`
@@ -222,7 +224,7 @@ func (c *Collector) buildBufferManager() error {
)
c.bufManReadaheadtime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "bufman_read_ahead_issuing_seconds"),
"(BufferManager.Readaheadtime)",
"(BufferManager.Readaheadtime) Total time spent issuing read-ahead, in seconds",
[]string{"mssql_instance"},
nil,
)
@@ -246,6 +248,12 @@ func (c *Collector) collectBufferManagerInstance(ch chan<- prometheus.Metric, sq
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Buffer Manager"), err)
}
c.emitBufferManagerMetrics(ch, sqlInstance)
return nil
}
func (c *Collector) emitBufferManagerMetrics(ch chan<- prometheus.Metric, sqlInstance mssqlInstance) {
for _, data := range c.bufManPerfDataObject {
ch <- prometheus.MustNewConstMetric(
c.bufManBackgroundwriterpages,
@@ -397,7 +405,7 @@ func (c *Collector) collectBufferManagerInstance(ch chan<- prometheus.Metric, sq
ch <- prometheus.MustNewConstMetric(
c.bufManReadaheadtime,
prometheus.CounterValue,
data.BufManReadaheadTimePerSec,
data.BufManReadaheadTimePerSec/1e6, // microseconds
sqlInstance.name,
)
@@ -408,8 +416,6 @@ func (c *Collector) collectBufferManagerInstance(ch chan<- prometheus.Metric, sq
sqlInstance.name,
)
}
return nil
}
func (c *Collector) closeBufferManager() {
+38 -22
View File
@@ -77,6 +77,7 @@ type collectorDatabases struct {
databasesTransactions *prometheus.Desc
databasesWriteTransactions *prometheus.Desc
databasesXTPControllerDLCLatencyPerFetch *prometheus.Desc
databasesXTPControllerDLCFetches *prometheus.Desc
databasesXTPControllerDLCPeakLatency *prometheus.Desc
databasesXTPControllerLogProcessed *prometheus.Desc
databasesXTPMemoryUsedKB *prometheus.Desc
@@ -129,9 +130,11 @@ type perfDataCounterValuesDatabases struct {
DatabasesTransactionsPerSec float64 `perfdata:"Transactions/sec"`
DatabasesWriteTransactionsPerSec float64 `perfdata:"Write Transactions/sec"`
DatabasesXTPControllerDLCLatencyPerFetch float64 `perfdata:"XTP Controller DLC Latency/Fetch"`
DatabasesXTPControllerDLCPeakLatency float64 `perfdata:"XTP Controller DLC Peak Latency"`
DatabasesXTPControllerLogProcessedPerSec float64 `perfdata:"XTP Controller Log Processed/sec"`
DatabasesXTPMemoryUsedKB float64 `perfdata:"XTP Memory Used (KB)"`
// PERF_AVERAGE_BULK: the base is the number of fetches.
DatabasesXTPControllerDLCLatencyPerFetchBase float64 `perfdata:"XTP Controller DLC Latency/Fetch,secondvalue"`
DatabasesXTPControllerDLCPeakLatency float64 `perfdata:"XTP Controller DLC Peak Latency"`
DatabasesXTPControllerLogProcessedPerSec float64 `perfdata:"XTP Controller Log Processed/sec"`
DatabasesXTPMemoryUsedKB float64 `perfdata:"XTP Memory Used (KB)"`
}
type perfDataCounterValuesDatabases2019 struct {
@@ -264,20 +267,20 @@ func (c *Collector) buildDatabases() error {
nil,
)
c.databasesLogFlushWaitTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "databases_log_flush_wait_seconds"),
"(Databases.LogFlushWaitTime)",
prometheus.BuildFQName(types.Namespace, Name, "databases_log_flush_wait_seconds_total"),
"(Databases.LogFlushWaitTime) Total time commits waited for log flushes, in seconds",
[]string{"mssql_instance", "database"},
nil,
)
c.databasesLogFlushWriteTimeMS = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "databases_log_flush_write_seconds"),
"(Databases.LogFlushWriteTimems)",
prometheus.BuildFQName(types.Namespace, Name, "databases_log_flush_write_seconds_total"),
"(Databases.LogFlushWriteTimems) Total time spent writing log flushes, in seconds",
[]string{"mssql_instance", "database"},
nil,
)
c.databasesLogGrowths = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "databases_log_growths"),
"(Databases.LogGrowths)",
prometheus.BuildFQName(types.Namespace, Name, "databases_log_growths_total"),
"(Databases.LogGrowths) Total number of log growths for this database",
[]string{"mssql_instance", "database"},
nil,
)
@@ -372,14 +375,14 @@ func (c *Collector) buildDatabases() error {
nil,
)
c.databasesLogShrinks = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "databases_log_shrinks"),
"(Databases.LogShrinks)",
prometheus.BuildFQName(types.Namespace, Name, "databases_log_shrinks_total"),
"(Databases.LogShrinks) Total number of log shrinks for this database",
[]string{"mssql_instance", "database"},
nil,
)
c.databasesLogTruncations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "databases_log_truncations"),
"(Databases.LogTruncations)",
prometheus.BuildFQName(types.Namespace, Name, "databases_log_truncations_total"),
"(Databases.LogTruncations) Total number of log truncations for this database",
[]string{"mssql_instance", "database"},
nil,
)
@@ -426,8 +429,14 @@ func (c *Collector) buildDatabases() error {
nil,
)
c.databasesXTPControllerDLCLatencyPerFetch = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "databases_xtp_controller_dlc_fetch_latency_seconds"),
"(Databases.XTPControllerDLCLatencyPerFetch)",
prometheus.BuildFQName(types.Namespace, Name, "databases_xtp_controller_dlc_fetch_latency_seconds_total"),
"(Databases.XTPControllerDLCLatencyPerFetch) Total latency of fetches from the Direct Log Consumer by the XTP controller, in seconds",
[]string{"mssql_instance", "database"},
nil,
)
c.databasesXTPControllerDLCFetches = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "databases_xtp_controller_dlc_fetches_total"),
"(Databases.XTPControllerDLCLatencyBase) Total number of fetches from the Direct Log Consumer by the XTP controller",
[]string{"mssql_instance", "database"},
nil,
)
@@ -587,21 +596,21 @@ func (c *Collector) emitDatabasesMetrics(ch chan<- prometheus.Metric, sqlInstanc
ch <- prometheus.MustNewConstMetric(
c.databasesLogFlushWaitTime,
prometheus.GaugeValue,
prometheus.CounterValue,
data.DatabasesLogFlushWaitTime/1000.0,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.databasesLogFlushWriteTimeMS,
prometheus.GaugeValue,
prometheus.CounterValue,
data.DatabasesLogFlushWriteTimeMS/1000.0,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.databasesLogGrowths,
prometheus.GaugeValue,
prometheus.CounterValue,
data.DatabasesLogGrowths,
sqlInstance.name, data.Name,
)
@@ -713,14 +722,14 @@ func (c *Collector) emitDatabasesMetrics(ch chan<- prometheus.Metric, sqlInstanc
ch <- prometheus.MustNewConstMetric(
c.databasesLogShrinks,
prometheus.GaugeValue,
prometheus.CounterValue,
data.DatabasesLogShrinks,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.databasesLogTruncations,
prometheus.GaugeValue,
prometheus.CounterValue,
data.DatabasesLogTruncations,
sqlInstance.name, data.Name,
)
@@ -776,8 +785,15 @@ func (c *Collector) emitDatabasesMetrics(ch chan<- prometheus.Metric, sqlInstanc
ch <- prometheus.MustNewConstMetric(
c.databasesXTPControllerDLCLatencyPerFetch,
prometheus.GaugeValue,
data.DatabasesXTPControllerDLCLatencyPerFetch,
prometheus.CounterValue,
data.DatabasesXTPControllerDLCLatencyPerFetch/1e6, // microseconds
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.databasesXTPControllerDLCFetches,
prometheus.CounterValue,
data.DatabasesXTPControllerDLCLatencyPerFetchBase,
sqlInstance.name, data.Name,
)
@@ -100,8 +100,8 @@ func (c *Collector) buildDatabaseReplica() error {
// Win32_PerfRawData_{instance}_SQLServerDatabaseReplica
c.dbReplicaDatabaseFlowControlDelay = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_database_flow_control_wait_seconds"),
"(DatabaseReplica.DatabaseFlowControlDelay)",
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_database_flow_control_wait_seconds_total"),
"(DatabaseReplica.DatabaseFlowControlDelay) Total time spent in database flow control wait, in seconds",
[]string{"mssql_instance", "replica"},
nil,
)
@@ -124,8 +124,8 @@ func (c *Collector) buildDatabaseReplica() error {
nil,
)
c.dbReplicaGroupCommitTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_group_commit_stall_seconds"),
"(DatabaseReplica.GroupCommitTime)",
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_group_commit_stall_seconds_total"),
"(DatabaseReplica.GroupCommitTime) Total time transactions waited for group commit, in seconds",
[]string{"mssql_instance", "replica"},
nil,
)
@@ -184,14 +184,14 @@ func (c *Collector) buildDatabaseReplica() error {
nil,
)
c.dbReplicaLogremainingforundo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_remaining_for_undo"),
"(DatabaseReplica.Logremainingforundo)",
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_remaining_for_undo_bytes"),
"(DatabaseReplica.Logremainingforundo) Log remaining to finish the undo phase, in bytes",
[]string{"mssql_instance", "replica"},
nil,
)
c.dbReplicaLogSendQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_send_queue"),
"(DatabaseReplica.LogSendQueue)",
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_send_queue_bytes"),
"(DatabaseReplica.LogSendQueue) Log waiting to be sent to the database replica, in bytes",
[]string{"mssql_instance", "replica"},
nil,
)
@@ -202,8 +202,8 @@ func (c *Collector) buildDatabaseReplica() error {
nil,
)
c.dbReplicaRecoveryQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_recovery_queue_records"),
"(DatabaseReplica.RecoveryQueue)",
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_recovery_queue_bytes"),
"(DatabaseReplica.RecoveryQueue) Hardened log waiting to be redone on the secondary, in bytes",
[]string{"mssql_instance", "replica"},
nil,
)
@@ -215,7 +215,7 @@ func (c *Collector) buildDatabaseReplica() error {
)
c.dbReplicaRedoBytesRemaining = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_redo_remaining_bytes"),
"(DatabaseReplica.RedoBytesRemaining)",
"(DatabaseReplica.RedoBytesRemaining) Log remaining to be redone to finish the reverting phase, in bytes",
[]string{"mssql_instance", "replica"},
nil,
)
@@ -232,14 +232,14 @@ func (c *Collector) buildDatabaseReplica() error {
nil,
)
c.dbReplicaTotalLogrequiringundo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_total_log_requiring_undo"),
"(DatabaseReplica.TotalLogrequiringundo)",
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_total_log_requiring_undo_bytes"),
"(DatabaseReplica.TotalLogrequiringundo) Log that needs to be undone, in bytes",
[]string{"mssql_instance", "replica"},
nil,
)
c.dbReplicaTransactionDelay = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_transaction_delay_seconds"),
"(DatabaseReplica.TransactionDelay)",
prometheus.BuildFQName(types.Namespace, Name, "dbreplica_transaction_delay_seconds_total"),
"(DatabaseReplica.TransactionDelay) Total time transaction termination waited for acknowledgement, in seconds",
[]string{"mssql_instance", "replica"},
nil,
)
@@ -266,7 +266,7 @@ func (c *Collector) emitDatabaseReplicaMetrics(ch chan<- prometheus.Metric, sqlI
for _, data := range c.dbReplicaPerfDataObject {
ch <- prometheus.MustNewConstMetric(
c.dbReplicaDatabaseFlowControlDelay,
prometheus.GaugeValue,
prometheus.CounterValue,
data.DbReplicaDatabaseFlowControlDelay/1e6,
sqlInstance.name, data.Name,
)
@@ -294,7 +294,7 @@ func (c *Collector) emitDatabaseReplicaMetrics(ch chan<- prometheus.Metric, sqlI
ch <- prometheus.MustNewConstMetric(
c.dbReplicaGroupCommitTime,
prometheus.GaugeValue,
prometheus.CounterValue,
data.DbReplicaGroupCommitTime/1e6,
sqlInstance.name, data.Name,
)
@@ -365,14 +365,14 @@ func (c *Collector) emitDatabaseReplicaMetrics(ch chan<- prometheus.Metric, sqlI
ch <- prometheus.MustNewConstMetric(
c.dbReplicaLogremainingforundo,
prometheus.GaugeValue,
data.DbReplicaLogRemainingForUndo,
data.DbReplicaLogRemainingForUndo*1024,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.dbReplicaLogSendQueue,
prometheus.GaugeValue,
data.DbReplicaLogSendQueue,
data.DbReplicaLogSendQueue*1024,
sqlInstance.name, data.Name,
)
@@ -386,7 +386,7 @@ func (c *Collector) emitDatabaseReplicaMetrics(ch chan<- prometheus.Metric, sqlI
ch <- prometheus.MustNewConstMetric(
c.dbReplicaRecoveryQueue,
prometheus.GaugeValue,
data.DbReplicaRecoveryQueue,
data.DbReplicaRecoveryQueue*1024,
sqlInstance.name, data.Name,
)
@@ -400,7 +400,7 @@ func (c *Collector) emitDatabaseReplicaMetrics(ch chan<- prometheus.Metric, sqlI
ch <- prometheus.MustNewConstMetric(
c.dbReplicaRedoBytesRemaining,
prometheus.GaugeValue,
data.DbReplicaRedoBytesRemaining,
data.DbReplicaRedoBytesRemaining*1024,
sqlInstance.name, data.Name,
)
@@ -421,13 +421,13 @@ func (c *Collector) emitDatabaseReplicaMetrics(ch chan<- prometheus.Metric, sqlI
ch <- prometheus.MustNewConstMetric(
c.dbReplicaTotalLogrequiringundo,
prometheus.GaugeValue,
data.DbReplicaTotalLogRequiringUndo,
data.DbReplicaTotalLogRequiringUndo*1024,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.dbReplicaTransactionDelay,
prometheus.GaugeValue,
prometheus.CounterValue,
data.DbReplicaTransactionDelay/1000.0,
sqlInstance.name, data.Name,
)
@@ -116,7 +116,7 @@ func (c *Collector) buildGeneralStatistics() error {
nil,
)
c.genStatsHTTPAuthenticatedRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_http_authenticated_requests"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_http_authenticated_requests_total"),
"(GeneralStatistics.HTTPAuthenticatedRequests)",
[]string{"mssql_instance"},
nil,
@@ -140,7 +140,7 @@ func (c *Collector) buildGeneralStatistics() error {
nil,
)
c.genStatsMarsDeadlocks = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_mars_deadlocks"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_mars_deadlocks_total"),
"(GeneralStatistics.MarsDeadlocks)",
[]string{"mssql_instance"},
nil,
@@ -158,55 +158,55 @@ func (c *Collector) buildGeneralStatistics() error {
nil,
)
c.genStatsSOAPEmptyRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_empty_requests"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_empty_requests_total"),
"(GeneralStatistics.SOAPEmptyRequests)",
[]string{"mssql_instance"},
nil,
)
c.genStatsSOAPMethodInvocations = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_method_invocations"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_method_invocations_total"),
"(GeneralStatistics.SOAPMethodInvocations)",
[]string{"mssql_instance"},
nil,
)
c.genStatsSOAPSessionInitiateRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_session_initiate_requests"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_session_initiate_requests_total"),
"(GeneralStatistics.SOAPSessionInitiateRequests)",
[]string{"mssql_instance"},
nil,
)
c.genStatsSOAPSessionTerminateRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_session_terminate_requests"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_session_terminate_requests_total"),
"(GeneralStatistics.SOAPSessionTerminateRequests)",
[]string{"mssql_instance"},
nil,
)
c.genStatsSOAPSQLRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_soapsql_requests"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_soapsql_requests_total"),
"(GeneralStatistics.SOAPSQLRequests)",
[]string{"mssql_instance"},
nil,
)
c.genStatsSOAPWSDLRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_soapwsdl_requests"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_soapwsdl_requests_total"),
"(GeneralStatistics.SOAPWSDLRequests)",
[]string{"mssql_instance"},
nil,
)
c.genStatsSQLTraceIOProviderLockWaits = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_sql_trace_io_provider_lock_waits"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_sql_trace_io_provider_lock_waits_total"),
"(GeneralStatistics.SQLTraceIOProviderLockWaits)",
[]string{"mssql_instance"},
nil,
)
c.genStatsTempDBRecoveryUnitID = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_tempdb_recovery_unit_ids_generated"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_tempdb_recovery_unit_ids_generated_total"),
"(GeneralStatistics.Tempdbrecoveryunitid)",
[]string{"mssql_instance"},
nil,
)
c.genStatsTempDBrowSetID = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "genstats_tempdb_rowset_ids_generated"),
prometheus.BuildFQName(types.Namespace, Name, "genstats_tempdb_rowset_ids_generated_total"),
"(GeneralStatistics.Tempdbrowsetid)",
[]string{"mssql_instance"},
nil,
@@ -255,6 +255,12 @@ func (c *Collector) collectGeneralStatisticsInstance(ch chan<- prometheus.Metric
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "General Statistics"), err)
}
c.emitGeneralStatisticsMetrics(ch, sqlInstance)
return nil
}
func (c *Collector) emitGeneralStatisticsMetrics(ch chan<- prometheus.Metric, sqlInstance mssqlInstance) {
ch <- prometheus.MustNewConstMetric(
c.genStatsActiveTempTables,
prometheus.GaugeValue,
@@ -278,7 +284,7 @@ func (c *Collector) collectGeneralStatisticsInstance(ch chan<- prometheus.Metric
ch <- prometheus.MustNewConstMetric(
c.genStatsHTTPAuthenticatedRequests,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsHTTPAuthenticatedRequests,
sqlInstance.name,
)
@@ -306,7 +312,7 @@ func (c *Collector) collectGeneralStatisticsInstance(ch chan<- prometheus.Metric
ch <- prometheus.MustNewConstMetric(
c.genStatsMarsDeadlocks,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsMarsDeadlocks,
sqlInstance.name,
)
@@ -327,63 +333,63 @@ func (c *Collector) collectGeneralStatisticsInstance(ch chan<- prometheus.Metric
ch <- prometheus.MustNewConstMetric(
c.genStatsSOAPEmptyRequests,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsSOAPEmptyRequests,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.genStatsSOAPMethodInvocations,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsSOAPMethodInvocations,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.genStatsSOAPSessionInitiateRequests,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsSOAPSessionInitiateRequests,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.genStatsSOAPSessionTerminateRequests,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsSOAPSessionTerminateRequests,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.genStatsSOAPSQLRequests,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsSOAPSQLRequests,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.genStatsSOAPWSDLRequests,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsSOAPWSDLRequests,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.genStatsSQLTraceIOProviderLockWaits,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsSQLTraceIOProviderLockWaits,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.genStatsTempDBRecoveryUnitID,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsTempdbRecoveryUnitID,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.genStatsTempDBrowSetID,
prometheus.GaugeValue,
prometheus.CounterValue,
c.genStatsPerfDataObject[0].GenStatsTempdbRowsetID,
sqlInstance.name,
)
@@ -422,8 +428,6 @@ func (c *Collector) collectGeneralStatisticsInstance(ch chan<- prometheus.Metric
c.genStatsPerfDataObject[0].GenStatsUserConnections,
sqlInstance.name,
)
return nil
}
func (c *Collector) closeGeneralStatistics() {
+9 -9
View File
@@ -68,14 +68,14 @@ func (c *Collector) buildLocks() error {
}
c.locksWaitTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "locks_wait_time_seconds"),
"(Locks.AverageWaitTimems Total time in seconds which locks have been holding resources)",
prometheus.BuildFQName(types.Namespace, Name, "locks_wait_time_seconds_total"),
"(Locks.AverageWaitTimems) Total time lock requests waited, in seconds. Numerator of Average Wait Time (ms)",
[]string{"mssql_instance", "resource"},
nil,
)
c.locksCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "locks_count"),
"(Locks.AverageWaitTimems_Base count of how often requests have run into locks)",
prometheus.BuildFQName(types.Namespace, Name, "locks_count_total"),
"(Locks.AverageWaitTimems_Base) Total number of lock requests that waited. Base of Average Wait Time (ms)",
[]string{"mssql_instance", "resource"},
nil,
)
@@ -104,8 +104,8 @@ func (c *Collector) buildLocks() error {
nil,
)
c.locksLockWaitTimeMS = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "locks_lock_wait_seconds"),
"(Locks.LockWaitTimems)",
prometheus.BuildFQName(types.Namespace, Name, "locks_lock_wait_seconds_total"),
"(Locks.LockWaitTimems) Total time lock requests waited, in seconds",
[]string{"mssql_instance", "resource"},
nil,
)
@@ -138,14 +138,14 @@ func (c *Collector) emitLocksMetrics(ch chan<- prometheus.Metric, sqlInstance ms
for _, data := range c.locksPerfDataObject {
ch <- prometheus.MustNewConstMetric(
c.locksWaitTime,
prometheus.GaugeValue,
prometheus.CounterValue,
data.LocksAverageWaitTimeMS/1000.0,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.locksCount,
prometheus.GaugeValue,
prometheus.CounterValue,
data.LocksAverageWaitTimeMSBase,
sqlInstance.name, data.Name,
)
@@ -180,7 +180,7 @@ func (c *Collector) emitLocksMetrics(ch chan<- prometheus.Metric, sqlInstance ms
ch <- prometheus.MustNewConstMetric(
c.locksLockWaitTimeMS,
prometheus.GaugeValue,
prometheus.CounterValue,
data.LocksLockWaitTimeMS/1000.0,
sqlInstance.name, data.Name,
)
+49 -30
View File
@@ -32,13 +32,14 @@ type collectorTransactions struct {
transactionsTempDbFreeSpaceBytes *prometheus.Desc
transactionsLongestTransactionRunningSeconds *prometheus.Desc
transactionsNonSnapshotVersionActiveTotal *prometheus.Desc
transactionsSnapshotActiveTotal *prometheus.Desc
transactionsNonSnapshotVersionActive *prometheus.Desc
transactionsSnapshotActive *prometheus.Desc
transactionsActive *prometheus.Desc
transactionsUpdateConflictsTotal *prometheus.Desc
transactionsUpdateSnapshotActiveTotal *prometheus.Desc
transactionsVersionCleanupRateBytes *prometheus.Desc
transactionsVersionGenerationRateBytes *prometheus.Desc
transactionsUpdateSnapshotTotal *prometheus.Desc
transactionsUpdateSnapshotActive *prometheus.Desc
transactionsVersionCleanupBytes *prometheus.Desc
transactionsVersionGenerationBytes *prometheus.Desc
transactionsVersionStoreSizeBytes *prometheus.Desc
transactionsVersionStoreUnits *prometheus.Desc
transactionsVersionStoreCreationUnits *prometheus.Desc
@@ -52,6 +53,7 @@ type perfDataCounterValuesTransactions struct {
TransactionsSnapshotTransactions float64 `perfdata:"Snapshot Transactions"`
TransactionsTransactions float64 `perfdata:"Transactions"`
TransactionsUpdateconflictratio float64 `perfdata:"Update conflict ratio"`
TransactionsUpdateconflictratioBase float64 `perfdata:"Update conflict ratio,secondvalue"`
TransactionsUpdateSnapshotTransactions float64 `perfdata:"Update Snapshot Transactions"`
TransactionsVersionCleanuprateKBPers float64 `perfdata:"Version Cleanup rate (KB/s)"`
TransactionsVersionGenerationrateKBPers float64 `perfdata:"Version Generation rate (KB/s)"`
@@ -86,14 +88,14 @@ func (c *Collector) buildTransactions() error {
[]string{"mssql_instance"},
nil,
)
c.transactionsNonSnapshotVersionActiveTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_nonsnapshot_version_active_total"),
c.transactionsNonSnapshotVersionActive = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_nonsnapshot_version_active"),
"(Transactions.NonSnapshotVersionTransactions)",
[]string{"mssql_instance"},
nil,
)
c.transactionsSnapshotActiveTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_snapshot_active_total"),
c.transactionsSnapshotActive = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_snapshot_active"),
"(Transactions.SnapshotTransactions)",
[]string{"mssql_instance"},
nil,
@@ -106,25 +108,31 @@ func (c *Collector) buildTransactions() error {
)
c.transactionsUpdateConflictsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_update_conflicts_total"),
"(Transactions.UpdateConflictRatio)",
"(Transactions.UpdateConflictRatio) Total number of update snapshot transactions that had an update conflict",
[]string{"mssql_instance"},
nil,
)
c.transactionsUpdateSnapshotActiveTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_update_snapshot_active_total"),
c.transactionsUpdateSnapshotTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_update_snapshot_transactions_total"),
"(Transactions.UpdateConflictRatio_Base) Total number of update snapshot transactions",
[]string{"mssql_instance"},
nil,
)
c.transactionsUpdateSnapshotActive = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_update_snapshot_active"),
"(Transactions.UpdateSnapshotTransactions)",
[]string{"mssql_instance"},
nil,
)
c.transactionsVersionCleanupRateBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_version_cleanup_rate_bytes"),
"(Transactions.VersionCleanupRateKBs)",
c.transactionsVersionCleanupBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_version_cleanup_bytes_total"),
"(Transactions.VersionCleanupRateKBs) Total size of row versions removed from the version store, in bytes",
[]string{"mssql_instance"},
nil,
)
c.transactionsVersionGenerationRateBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_version_generation_rate_bytes"),
"(Transactions.VersionGenerationRateKBs)",
c.transactionsVersionGenerationBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transactions_version_generation_bytes_total"),
"(Transactions.VersionGenerationRateKBs) Total size of row versions added to the version store, in bytes",
[]string{"mssql_instance"},
nil,
)
@@ -168,6 +176,12 @@ func (c *Collector) collectTransactionsInstance(ch chan<- prometheus.Metric, sql
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Transactions"), err)
}
c.emitTransactionsMetrics(ch, sqlInstance)
return nil
}
func (c *Collector) emitTransactionsMetrics(ch chan<- prometheus.Metric, sqlInstance mssqlInstance) {
ch <- prometheus.MustNewConstMetric(
c.transactionsTempDbFreeSpaceBytes,
prometheus.GaugeValue,
@@ -183,15 +197,15 @@ func (c *Collector) collectTransactionsInstance(ch chan<- prometheus.Metric, sql
)
ch <- prometheus.MustNewConstMetric(
c.transactionsNonSnapshotVersionActiveTotal,
prometheus.CounterValue,
c.transactionsNonSnapshotVersionActive,
prometheus.GaugeValue,
c.transactionsPerfDataObject[0].TransactionsNonSnapshotVersionTransactions,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.transactionsSnapshotActiveTotal,
prometheus.CounterValue,
c.transactionsSnapshotActive,
prometheus.GaugeValue,
c.transactionsPerfDataObject[0].TransactionsSnapshotTransactions,
sqlInstance.name,
)
@@ -211,22 +225,29 @@ func (c *Collector) collectTransactionsInstance(ch chan<- prometheus.Metric, sql
)
ch <- prometheus.MustNewConstMetric(
c.transactionsUpdateSnapshotActiveTotal,
c.transactionsUpdateSnapshotTotal,
prometheus.CounterValue,
c.transactionsPerfDataObject[0].TransactionsUpdateconflictratioBase,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.transactionsUpdateSnapshotActive,
prometheus.GaugeValue,
c.transactionsPerfDataObject[0].TransactionsUpdateSnapshotTransactions,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.transactionsVersionCleanupRateBytes,
prometheus.GaugeValue,
c.transactionsVersionCleanupBytes,
prometheus.CounterValue,
c.transactionsPerfDataObject[0].TransactionsVersionCleanuprateKBPers*1024,
sqlInstance.name,
)
ch <- prometheus.MustNewConstMetric(
c.transactionsVersionGenerationRateBytes,
prometheus.GaugeValue,
c.transactionsVersionGenerationBytes,
prometheus.CounterValue,
c.transactionsPerfDataObject[0].TransactionsVersionGenerationrateKBPers*1024,
sqlInstance.name,
)
@@ -240,7 +261,7 @@ func (c *Collector) collectTransactionsInstance(ch chan<- prometheus.Metric, sql
ch <- prometheus.MustNewConstMetric(
c.transactionsVersionStoreUnits,
prometheus.CounterValue,
prometheus.GaugeValue,
c.transactionsPerfDataObject[0].TransactionsVersionStoreunitcount,
sqlInstance.name,
)
@@ -258,8 +279,6 @@ func (c *Collector) collectTransactionsInstance(ch chan<- prometheus.Metric, sql
c.transactionsPerfDataObject[0].TransactionsVersionStoreunittruncation,
sqlInstance.name,
)
return nil
}
func (c *Collector) closeTransactions() {
+23 -14
View File
@@ -161,93 +161,102 @@ func (c *Collector) collectWaitStatsInstance(ch chan<- prometheus.Metric, sqlIns
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Wait Statistics"), err)
}
c.emitWaitStatsMetrics(ch, sqlInstance)
return nil
}
// emitWaitStatsMetrics publishes every wait statistic as a gauge. The instance
// (label "item") names the statistic: "Average wait time (ms)",
// "Cumulative wait time (ms) per second", "Waits in progress" and
// "Waits started per second". SQL Server computes them over its most recent
// sampling interval, so none of them only grows.
func (c *Collector) emitWaitStatsMetrics(ch chan<- prometheus.Metric, sqlInstance mssqlInstance) {
for _, data := range c.waitStatsPerfDataObject {
ch <- prometheus.MustNewConstMetric(
c.waitStatsLockWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsLockWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsMemoryGrantQueueWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsMemoryGrantQueueWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsThreadSafeMemoryObjectsWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsThreadSafeMemoryObjectsWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsLogWriteWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsLogWriteWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsLogBufferWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsLogBufferWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsNetworkIOWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsNetworkIOWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsPageIOLatchWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsPageIOLatchWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsPageLatchWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsPageLatchWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsNonPageLatchWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsNonpageLatchWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsWaitForTheWorkerWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsWaitForTheWorkerWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsWorkspaceSynchronizationWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsWorkspaceSynchronizationWaits,
sqlInstance.name, data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.waitStatsTransactionOwnershipWaits,
prometheus.CounterValue,
prometheus.GaugeValue,
data.WaitStatsTransactionOwnershipWaits,
sqlInstance.name, data.Name,
)
}
return nil
}
func (c *Collector) closeWaitStats() {