From 70a177742206a1a685bbdcf34492c05dc8beb8e1 Mon Sep 17 00:00:00 2001 From: Dominik Eisenberg <64131471+Dominik-esb@users.noreply.github.com> Date: Fri, 26 Jun 2026 14:55:09 +0200 Subject: [PATCH] mscluster: use AllocatedSize for virtual disk storage efficiency (#2432) Co-authored-by: EisenbergD Signed-off-by: EisenbergD --- docs/collector.mscluster.md | 3 +- .../mscluster/mscluster_virtualdisk.go | 29 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/docs/collector.mscluster.md b/docs/collector.mscluster.md index 15dcd46f..29996c67 100644 --- a/docs/collector.mscluster.md +++ b/docs/collector.mscluster.md @@ -185,8 +185,9 @@ Matching is case-sensitive. | `mscluster_virtualdisk_info` | Virtual disk information (value is always 1) | gauge | `name`, `unique_id` | | `mscluster_virtualdisk_health_status` | Health status of the virtual disk. 0: Healthy, 1: Warning, 2: Unhealthy, 5: Unknown | gauge | `name`, `unique_id` | | `mscluster_virtualdisk_size_bytes` | Total size of the virtual disk in bytes | gauge | `name`, `unique_id` | +| `mscluster_virtualdisk_allocated_size_bytes` | Allocated size of the virtual disk in bytes (capacity actually provisioned, excludes thin-provisioned unused capacity) | gauge | `name`, `unique_id` | | `mscluster_virtualdisk_footprint_on_pool_bytes` | Physical storage consumed by the virtual disk on the storage pool in bytes | gauge | `name`, `unique_id` | -| `mscluster_virtualdisk_storage_efficiency_percent` | Storage efficiency percentage (Size / FootprintOnPool * 100) | gauge | `name`, `unique_id` | +| `mscluster_virtualdisk_storage_efficiency_percent` | Storage efficiency percentage (AllocatedSize / FootprintOnPool * 100) | gauge | `name`, `unique_id` | ### Example metric Query the state of all cluster resource owned by node1 diff --git a/internal/collector/mscluster/mscluster_virtualdisk.go b/internal/collector/mscluster/mscluster_virtualdisk.go index 4a90a087..5788e209 100644 --- a/internal/collector/mscluster/mscluster_virtualdisk.go +++ b/internal/collector/mscluster/mscluster_virtualdisk.go @@ -34,6 +34,7 @@ type collectorVirtualDisk struct { virtualDiskInfo *prometheus.Desc virtualDiskHealthStatus *prometheus.Desc virtualDiskSize *prometheus.Desc + virtualDiskAllocatedSize *prometheus.Desc virtualDiskFootprintOnPool *prometheus.Desc virtualDiskStorageEfficiency *prometheus.Desc } @@ -44,12 +45,13 @@ type msftVirtualDisk struct { UniqueId string `mi:"UniqueId"` HealthStatus uint16 `mi:"HealthStatus"` Size uint64 `mi:"Size"` + AllocatedSize uint64 `mi:"AllocatedSize"` FootprintOnPool uint64 `mi:"FootprintOnPool"` // OperationalStatus []uint16 `mi:"OperationalStatus"` Not supported my mi query: https://github.com/prometheus-community/windows_exporter/pull/2296#issuecomment-3736584632 } func (c *Collector) buildVirtualDisk() error { - wmiSelect := "FriendlyName,UniqueId,HealthStatus,Size,FootprintOnPool" + wmiSelect := "FriendlyName,UniqueId,HealthStatus,Size,AllocatedSize,FootprintOnPool" virtualDiskMIQuery, err := mi.NewQuery(fmt.Sprintf("SELECT %s FROM MSFT_VirtualDisk", wmiSelect)) if err != nil { @@ -79,6 +81,13 @@ func (c *Collector) buildVirtualDisk() error { nil, ) + c.virtualDiskAllocatedSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, nameVirtualDisk, "allocated_size_bytes"), + "Allocated size of the virtual disk in bytes (data actually provisioned, excludes thin-provisioned unused capacity)", + []string{"name", "unique_id"}, + nil, + ) + c.virtualDiskFootprintOnPool = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, nameVirtualDisk, "footprint_on_pool_bytes"), "Physical storage consumed by the virtual disk on the storage pool in bytes", @@ -88,7 +97,7 @@ func (c *Collector) buildVirtualDisk() error { c.virtualDiskStorageEfficiency = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, nameVirtualDisk, "storage_efficiency_percent"), - "Storage efficiency percentage (Size / FootprintOnPool * 100)", + "Storage efficiency percentage (AllocatedSize / FootprintOnPool * 100)", []string{"name", "unique_id"}, nil, ) @@ -134,6 +143,14 @@ func (c *Collector) collectVirtualDisk(ch chan<- prometheus.Metric, maxScrapeDur vdisk.UniqueId, ) + ch <- prometheus.MustNewConstMetric( + c.virtualDiskAllocatedSize, + prometheus.GaugeValue, + float64(vdisk.AllocatedSize), + vdisk.FriendlyName, + vdisk.UniqueId, + ) + ch <- prometheus.MustNewConstMetric( c.virtualDiskFootprintOnPool, prometheus.GaugeValue, @@ -142,10 +159,14 @@ func (c *Collector) collectVirtualDisk(ch chan<- prometheus.Metric, maxScrapeDur vdisk.UniqueId, ) - // Calculate storage efficiency (avoid division by zero) + // Calculate storage efficiency (avoid division by zero). + // AllocatedSize (not Size) is the correct numerator: Size is the + // thin-provisioned ceiling, while AllocatedSize reflects the capacity + // actually provisioned. Using Size inflates the ratio on thin-provisioned + // disks (e.g. S2D FTT2 CSVs). var storageEfficiency float64 if vdisk.FootprintOnPool > 0 { - storageEfficiency = float64(vdisk.Size) / float64(vdisk.FootprintOnPool) * 100 + storageEfficiency = float64(vdisk.AllocatedSize) / float64(vdisk.FootprintOnPool) * 100 } else { storageEfficiency = 0 }