mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-10-17 10:09:05 +02:00
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:
co-authored by
Claude Opus 5.5
parent
ee4c8ea0fe
commit
c7fa244d0e
@@ -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"},
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user