storage_spaces: add primordial label to pool info (#2650)

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-10 17:08:05 +02:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 3e013fe22b
commit ec82f90a79
3 changed files with 49 additions and 16 deletions
+29 -12
View File
@@ -20,14 +20,19 @@ Matching is case-sensitive.
### Pool ### Pool
| Name | Description | Type | Labels | | Name | Description | Type | Labels |
|------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|-------|----------------------------------| |------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|-------|-----------------------------------|
| `windows_storage_spaces_pool_info` | Storage pool information (value is always 1) | gauge | `name`, `unique_id` | | `windows_storage_spaces_pool_info` | Storage pool information (value is always 1). `primordial` is `true` for the built-in primordial pool | gauge | `name`, `unique_id`, `primordial` |
| `windows_storage_spaces_pool_health_status` | Health status of the storage pool. 0: Healthy, 1: Warning, 2: Unhealthy, 5: Unknown | gauge | `name`, `unique_id` | | `windows_storage_spaces_pool_health_status` | Health status of the storage pool. 0: Healthy, 1: Warning, 2: Unhealthy, 5: Unknown | gauge | `name`, `unique_id` |
| `windows_storage_spaces_pool_size_bytes` | Total size of the storage pool in bytes | gauge | `name`, `unique_id` | | `windows_storage_spaces_pool_size_bytes` | Total size of the storage pool in bytes | gauge | `name`, `unique_id` |
| `windows_storage_spaces_pool_allocated_size_bytes` | Allocated size of the storage pool in bytes | gauge | `name`, `unique_id` | | `windows_storage_spaces_pool_allocated_size_bytes` | Allocated size of the storage pool in bytes | gauge | `name`, `unique_id` |
| `windows_storage_spaces_pool_operational_status` | Operational status codes reported for the storage pool (one series per status value) | gauge | `name`, `unique_id`, `status` | | `windows_storage_spaces_pool_operational_status` | Operational status codes reported for the storage pool (one series per status value) | gauge | `name`, `unique_id`, `status` |
| `windows_storage_spaces_pool_thin_provisioning_alert_thresholds` | Thin provisioning alert thresholds configured for the storage pool, in percent (one series per configured threshold) | gauge | `name`, `unique_id`, `threshold` | | `windows_storage_spaces_pool_thin_provisioning_alert_thresholds` | Thin provisioning alert thresholds configured for the storage pool, in percent (one series per configured threshold) | gauge | `name`, `unique_id`, `threshold` |
Windows always reports a built-in pool named `Primordial` next to the concrete pools.
It groups every local physical disk that can be pooled but is not yet part of a concrete pool, so its size is the sum of those disks and not usable pool capacity.
Only `windows_storage_spaces_pool_info` carries the `primordial` label.
Join on `unique_id` to restrict other pool metrics to concrete pools, as shown in the queries below.
### Virtual Disk ### Virtual Disk
@@ -42,13 +47,20 @@ Matching is case-sensitive.
### Example metric ### Example metric
`windows_storage_spaces_pool_size_bytes{name="Pool01",unique_id="{8f2c...}"} 1.0995116277760e+12` ```
windows_storage_spaces_pool_info{name="Pool01",primordial="false",unique_id="{8f2c...}"} 1
windows_storage_spaces_pool_size_bytes{name="Pool01",unique_id="{8f2c...}"} 1.0995116277760e+12
```
## Useful queries ## Useful queries
Storage pool usage in percent Storage pool usage in percent, excluding the primordial pool
``` ```
windows_storage_spaces_pool_allocated_size_bytes / windows_storage_spaces_pool_size_bytes * 100 (
windows_storage_spaces_pool_allocated_size_bytes / windows_storage_spaces_pool_size_bytes * 100
)
* on (instance, unique_id) group_left ()
windows_storage_spaces_pool_info{primordial="false"}
``` ```
Find virtual disks with low storage efficiency (over-provisioned) Find virtual disks with low storage efficiency (over-provisioned)
@@ -66,7 +78,12 @@ sum(windows_storage_spaces_virtual_disk_size_bytes) / sum(windows_storage_spaces
#### Unhealthy storage pool #### Unhealthy storage pool
```yaml ```yaml
- alert: StoragePoolUnhealthy - alert: StoragePoolUnhealthy
expr: windows_storage_spaces_pool_health_status != 0 expr: |
(
windows_storage_spaces_pool_health_status != 0
)
* on (instance, unique_id) group_left ()
windows_storage_spaces_pool_info{primordial="false"}
for: 10m for: 10m
labels: labels:
severity: warning severity: warning
@@ -44,6 +44,7 @@ type collectorStoragePool struct {
type msftStoragePool struct { type msftStoragePool struct {
FriendlyName string `mi:"FriendlyName"` FriendlyName string `mi:"FriendlyName"`
UniqueId string `mi:"UniqueId"` UniqueId string `mi:"UniqueId"`
IsPrimordial bool `mi:"IsPrimordial"`
HealthStatus uint16 `mi:"HealthStatus"` HealthStatus uint16 `mi:"HealthStatus"`
Size uint64 `mi:"Size"` Size uint64 `mi:"Size"`
AllocatedSize uint64 `mi:"AllocatedSize"` AllocatedSize uint64 `mi:"AllocatedSize"`
@@ -53,7 +54,7 @@ type msftStoragePool struct {
} }
func (c *Collector) buildStoragePool() error { func (c *Collector) buildStoragePool() error {
wmiSelect := "FriendlyName,UniqueId,HealthStatus,Size,AllocatedSize,OperationalStatus,ThinProvisioningAlertThresholds" wmiSelect := "FriendlyName,UniqueId,IsPrimordial,HealthStatus,Size,AllocatedSize,OperationalStatus,ThinProvisioningAlertThresholds"
storagePoolMIQuery, err := mi.NewQuery(fmt.Sprintf("SELECT %s FROM MSFT_StoragePool", wmiSelect)) storagePoolMIQuery, err := mi.NewQuery(fmt.Sprintf("SELECT %s FROM MSFT_StoragePool", wmiSelect))
if err != nil { if err != nil {
@@ -64,8 +65,8 @@ func (c *Collector) buildStoragePool() error {
c.storagePoolInfo = prometheus.NewDesc( c.storagePoolInfo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameStoragePool, "info"), prometheus.BuildFQName(types.Namespace, nameStoragePool, "info"),
"Storage pool information (value is always 1)", "Storage pool information (value is always 1). primordial is true for the built-in primordial pool",
[]string{"name", "unique_id"}, []string{"name", "unique_id", "primordial"},
nil, nil,
) )
@@ -127,6 +128,7 @@ func (c *Collector) collectStoragePool(ch chan<- prometheus.Metric, maxScrapeDur
1.0, 1.0,
pool.FriendlyName, pool.FriendlyName,
pool.UniqueId, pool.UniqueId,
strconv.FormatBool(pool.IsPrimordial),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
@@ -36,7 +36,7 @@ func TestCollector(t *testing.T) {
pool := prometheus.Labels{"name": "GitHubActions"} pool := prometheus.Labels{"name": "GitHubActions"}
virtualDisk := prometheus.Labels{"name": "CIVirtualDisk"} virtualDisk := prometheus.Labels{"name": "CIVirtualDisk"}
testutils.RequireFixtureMetric(t, metrics, storage_spaces.Name, "windows_storage_spaces_pool_info", pool) testutils.RequireFixtureMetric(t, metrics, storage_spaces.Name, "windows_storage_spaces_pool_info", prometheus.Labels{"name": "GitHubActions", "primordial": "false"})
testutils.RequireFixtureMetric(t, metrics, storage_spaces.Name, "windows_storage_spaces_virtual_disk_info", virtualDisk) testutils.RequireFixtureMetric(t, metrics, storage_spaces.Name, "windows_storage_spaces_virtual_disk_info", virtualDisk)
for _, tc := range []struct { for _, tc := range []struct {
@@ -66,4 +66,18 @@ func TestCollector(t *testing.T) {
require.Greater(t, value, 0.0) require.Greater(t, value, 0.0)
require.LessOrEqual(t, value, 100.0) require.LessOrEqual(t, value, 100.0)
} }
// Every pool, including the built-in primordial pool, must carry a boolean primordial label.
for _, metric := range metrics["windows_storage_spaces_pool_info"].GetMetric() {
var primordial []string
for _, label := range metric.GetLabel() {
if label.GetName() == "primordial" {
primordial = append(primordial, label.GetValue())
}
}
require.Len(t, primordial, 1, "pool info metric %s", metric)
require.Contains(t, []string{"true", "false"}, primordial[0], "pool info metric %s", metric)
}
} }