logical_disk: deprecate cumulative avg_*_requests_queued gauges (#2563)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
Jan-Otto Kröpke
2026-10-09 08:56:47 +02:00
committed by GitHub
co-authored by Claude Opus 5.5
parent ee4c8ea0fe
commit c7fa244d0e
5 changed files with 89 additions and 22 deletions
+32 -18
View File
@@ -25,24 +25,38 @@ Comma-separated list of collectors to use. Available collectors: metrics, bitloc
## Metrics
| Name | Description | Type | Labels |
|--------------------------------------------------|----------------------------------------------------------------------------------------------------|---------|-------------------------------------------------------------------|
| `windows_logical_disk_info` | A metric with a constant '1' value labeled with logical disk information | gauge | `disk`,`filesystem`,`serial_number`,`volume`,`volume_name`,`type` |
| `windows_logical_disk_requests_queued` | Number of requests outstanding on the disk at the time the performance data is collected | gauge | `volume` |
| `windows_logical_disk_avg_read_requests_queued` | Average number of read requests that were queued for the selected disk during the sample interval | gauge | `volume` |
| `windows_logical_disk_avg_write_requests_queued` | Average number of write requests that were queued for the selected disk during the sample interval | gauge | `volume` |
| `windows_logical_disk_read_bytes_total` | Rate at which bytes are transferred from the disk during read operations | counter | `volume` |
| `windows_logical_disk_reads_total` | Rate of read operations on the disk | counter | `volume` |
| `windows_logical_disk_write_bytes_total` | Rate at which bytes are transferred to the disk during write operations | counter | `volume` |
| `windows_logical_disk_writes_total` | Rate of write operations on the disk | counter | `volume` |
| `windows_logical_disk_read_seconds_total` | Seconds the disk was busy servicing read requests | counter | `volume` |
| `windows_logical_disk_write_seconds_total` | Seconds the disk was busy servicing write requests | counter | `volume` |
| `windows_logical_disk_free_bytes` | Unused space of the disk in bytes (not real time, updates every 10-15 min) | gauge | `volume` |
| `windows_logical_disk_size_bytes` | Total size of the disk in bytes (not real time, updates every 10-15 min) | gauge | `volume` |
| `windows_logical_disk_idle_seconds_total` | Seconds the disk was idle (not servicing read/write requests) | counter | `volume` |
| `windows_logical_disk_split_ios_total` | Number of I/Os to the disk split into multiple I/Os | counter | `volume` |
| `windows_logical_disk_readonly` | Whether the logical disk is read-only | gauge | `volume` |
| `windows_logical_disk_bitlocker_status` | BitLocker status for the logical disk | gauge | `volume`,`status` |
| Name | Description | Type | Labels |
|--------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|---------|-------------------------------------------------------------------|
| `windows_logical_disk_info` | A metric with a constant '1' value labeled with logical disk information | gauge | `disk`,`filesystem`,`serial_number`,`volume`,`volume_name`,`type` |
| `windows_logical_disk_requests_queued` | Number of requests outstanding on the disk at the time the performance data is collected | gauge | `volume` |
| `windows_logical_disk_avg_read_requests_queued` | **Deprecated:** use `rate(windows_logical_disk_read_seconds_total)`. Cumulative read queue length in seconds, see below | gauge | `volume` |
| `windows_logical_disk_avg_write_requests_queued` | **Deprecated:** use `rate(windows_logical_disk_write_seconds_total)`. Cumulative write queue length in seconds, see below | gauge | `volume` |
| `windows_logical_disk_read_bytes_total` | Rate at which bytes are transferred from the disk during read operations | counter | `volume` |
| `windows_logical_disk_reads_total` | Rate of read operations on the disk | counter | `volume` |
| `windows_logical_disk_write_bytes_total` | Rate at which bytes are transferred to the disk during write operations | counter | `volume` |
| `windows_logical_disk_writes_total` | Rate of write operations on the disk | counter | `volume` |
| `windows_logical_disk_read_seconds_total` | Seconds the disk was busy servicing read requests | counter | `volume` |
| `windows_logical_disk_write_seconds_total` | Seconds the disk was busy servicing write requests | counter | `volume` |
| `windows_logical_disk_free_bytes` | Unused space of the disk in bytes (not real time, updates every 10-15 min) | gauge | `volume` |
| `windows_logical_disk_size_bytes` | Total size of the disk in bytes (not real time, updates every 10-15 min) | gauge | `volume` |
| `windows_logical_disk_idle_seconds_total` | Seconds the disk was idle (not servicing read/write requests) | counter | `volume` |
| `windows_logical_disk_split_ios_total` | Number of I/Os to the disk split into multiple I/Os | counter | `volume` |
| `windows_logical_disk_readonly` | Whether the logical disk is read-only | gauge | `volume` |
| `windows_logical_disk_bitlocker_status` | BitLocker status for the logical disk | gauge | `volume`,`status` |
### Deprecated average queue length metrics
`Avg. Disk Read Queue Length` and `Avg. Disk Write Queue Length` are averages that Windows computes from two samples.
windows_exporter reads their raw values, which only grow: the queue length summed over time, in seconds.
These raw values are the same as the ones of `% Disk Read Time` and `% Disk Write Time`,
which are exposed as `windows_logical_disk_read_seconds_total` and `windows_logical_disk_write_seconds_total`.
`windows_logical_disk_avg_read_requests_queued` and `windows_logical_disk_avg_write_requests_queued` keep exposing
the raw values as gauges for compatibility. They are deprecated and will be removed in a future release.
Use the rate of the `*_seconds_total` counters for the average queue length instead:
```
rate(windows_logical_disk_read_seconds_total[5m])
rate(windows_logical_disk_write_seconds_total[5m])
```
### Warning about size metrics
The `free_bytes` and `size_bytes` metrics are not updated in real time and might have a delay of 10-15min.
@@ -232,14 +232,16 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.avgReadQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "avg_read_requests_queued"),
"Average number of read requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskReadQueueLength)",
"DEPRECATED: use rate(windows_logical_disk_read_seconds_total). "+
"Cumulative read queue length in seconds, identical to windows_logical_disk_read_seconds_total (LogicalDisk.AvgDiskReadQueueLength)",
[]string{"volume"},
nil,
)
c.avgWriteQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "avg_write_requests_queued"),
"Average number of write requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskWriteQueueLength)",
"DEPRECATED: use rate(windows_logical_disk_write_seconds_total). "+
"Cumulative write queue length in seconds, identical to windows_logical_disk_write_seconds_total (LogicalDisk.AvgDiskWriteQueueLength)",
[]string{"volume"},
nil,
)
@@ -399,6 +401,10 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error
data.Name,
)
// The raw value of a PERF_COUNTER_100NS_QUEUELEN_TYPE counter is the queue length
// integrated over time in 100ns ticks, not an average. It shares its source with
// "% Disk Read/Write Time". Kept as gauge for compatibility: as a counter,
// OpenMetrics exposition would rename the series to *_total.
ch <- prometheus.MustNewConstMetric(
c.avgReadQueue,
prometheus.GaugeValue,
@@ -46,6 +46,31 @@ func TestCollector(t *testing.T) {
})
}
// TestCollectorAvgQueueIsCumulative checks that the raw "Avg. Disk Read/Write Queue Length"
// values are not averages, but the same cumulative values as "% Disk Read/Write Time".
// This is why the avg_*_requests_queued metrics are kept only for compatibility.
func TestCollectorAvgQueueIsCumulative(t *testing.T) {
metrics := testutils.TestCollector(t, logical_disk.New, &logical_disk.Config{
CollectorsEnabled: logical_disk.ConfigDefaults.CollectorsEnabled,
VolumeInclude: types.RegExpAny,
})
for deprecated, replacement := range map[string]string{
"windows_logical_disk_avg_read_requests_queued": "windows_logical_disk_read_seconds_total",
"windows_logical_disk_avg_write_requests_queued": "windows_logical_disk_write_seconds_total",
} {
want := testutils.MetricValuesByLabel(metrics, replacement, "volume")
values := testutils.MetricValuesByLabel(metrics, deprecated, "volume")
require.NotEmpty(t, values, "%s was not emitted", deprecated)
for volume, got := range values {
require.Contains(t, want, volume)
require.InDelta(t, want[volume], got, 1e-6, "%s{volume=%q}", deprecated, volume)
}
}
}
func TestCollectorBitlocker(t *testing.T) {
metrics := testutils.TestCollector(t, logical_disk.New, &logical_disk.Config{
CollectorsEnabled: []string{"metrics", "bitlocker_status"},
+22
View File
@@ -256,6 +256,28 @@ func RequireFixtureMetric(t *testing.T, families map[string]*dto.MetricFamily, c
return nil
}
// MetricValuesByLabel returns the gauge or counter values of metricName,
// keyed by the value of the label labelName.
func MetricValuesByLabel(families map[string]*dto.MetricFamily, metricName, labelName string) map[string]float64 {
values := make(map[string]float64)
for _, metric := range families[metricName].GetMetric() {
for _, label := range metric.GetLabel() {
if label.GetName() != labelName {
continue
}
if metric.GetCounter() != nil {
values[label.GetValue()] = metric.GetCounter().GetValue()
} else {
values[label.GetValue()] = metric.GetGauge().GetValue()
}
}
}
return values
}
func noDataOnly(err error) bool {
if joined, ok := err.(interface{ Unwrap() []error }); ok {
for _, cause := range joined.Unwrap() {
+2 -2
View File
@@ -147,9 +147,9 @@ windows_exporter_collector_timeout{collector="time"} 0
windows_exporter_collector_timeout{collector="udp"} 0
# HELP windows_exporter_scrape_duration_seconds windows_exporter: Total scrape duration.
# TYPE windows_exporter_scrape_duration_seconds gauge
# HELP windows_logical_disk_avg_read_requests_queued Average number of read requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskReadQueueLength)
# HELP windows_logical_disk_avg_read_requests_queued DEPRECATED: use rate(windows_logical_disk_read_seconds_total). Cumulative read queue length in seconds, identical to windows_logical_disk_read_seconds_total (LogicalDisk.AvgDiskReadQueueLength)
# TYPE windows_logical_disk_avg_read_requests_queued gauge
# HELP windows_logical_disk_avg_write_requests_queued Average number of write requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskWriteQueueLength)
# HELP windows_logical_disk_avg_write_requests_queued DEPRECATED: use rate(windows_logical_disk_write_seconds_total). Cumulative write queue length in seconds, identical to windows_logical_disk_write_seconds_total (LogicalDisk.AvgDiskWriteQueueLength)
# TYPE windows_logical_disk_avg_write_requests_queued gauge
# HELP windows_logical_disk_free_bytes Free space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace)
# TYPE windows_logical_disk_free_bytes gauge