hyperv: locale-independent wmi_health query; assert hyperv/dmi in CI (#2510)

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-07 16:08:23 +02:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 4063c3800d
commit eea3689ec9
5 changed files with 37 additions and 4 deletions
+1 -1
View File
@@ -342,7 +342,7 @@ jobs:
WINDOWS_EXPORTER_TEST_RDP_USER: rdp-ci
WINDOWS_TEST_OS: ${{ matrix.os }}
# These collectors must work on the fixtures below; missing features are failures.
WINDOWS_EXPORTER_TEST_COLLECTORS: "cache,container,cpu,cpu_info,dhcp,diskdrive,dns,fsrmquota,hyperv,iis,license,logical_disk,memory,mscluster,msmq,mssql,net,netframework,nps,os,pagefile,physical_disk,printer,process,scheduled_task,service,smb,smbclient,system,tcp,terminal_services,time,udp,update${{ matrix.smtp && ',smtp' || '' }}"
WINDOWS_EXPORTER_TEST_COLLECTORS: "cache,container,cpu,cpu_info,dhcp,diskdrive,dmi,dns,fsrmquota,hyperv,iis,license,logical_disk,memory,mscluster,msmq,mssql,net,netframework,nps,os,pagefile,physical_disk,printer,process,scheduled_task,service,smb,smbclient,system,tcp,terminal_services,time,udp,update${{ matrix.smtp && ',smtp' || '' }}"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
+1 -1
View File
@@ -276,7 +276,7 @@ Multiply by the number of threads per core to get the ratio per **physical** cor
### Hyper-V WMI Health
Sub-collector `wmi_health`, enabled by default. It runs a minimal WQL query
(`SELECT Name FROM Msvm_ComputerSystem WHERE Caption = 'Hosting Computer System'`) against the
(`SELECT Name FROM Msvm_ComputerSystem WHERE Name = '<computer name>'`) against the
`root/virtualization/v2` namespace on every scrape, so remove it from `--collectors.hyperv.enabled` if you don't need it.
| Name | Description | Type | Labels |
+17 -1
View File
@@ -22,6 +22,7 @@ import (
"github.com/prometheus-community/windows_exporter/internal/collector/dmi"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
"github.com/stretchr/testify/require"
)
func BenchmarkCollector(b *testing.B) {
@@ -29,5 +30,20 @@ func BenchmarkCollector(b *testing.B) {
}
func TestCollector(t *testing.T) {
testutils.TestCollector(t, dmi.New, nil)
metrics := testutils.TestCollector(t, dmi.New, nil)
metric := testutils.RequireFixtureMetric(t, metrics, dmi.Name, "windows_dmi_info", nil)
if metric == nil {
return
}
for _, label := range metric.GetLabel() {
if label.GetName() == "product_uuid" {
require.NotEmpty(t, label.GetValue(), "SMBIOS system UUID is empty")
return
}
}
t.Fatalf("windows_dmi_info has no product_uuid label: %s", metric)
}
+6
View File
@@ -23,6 +23,7 @@ import (
"github.com/prometheus-community/windows_exporter/internal/collector/hyperv"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
)
func BenchmarkCollector(b *testing.B) {
@@ -33,4 +34,9 @@ func TestCollector(t *testing.T) {
metrics := testutils.TestCollector(t, hyperv.New, nil)
testutils.RequireFixtureMetric(t, metrics, hyperv.Name, "windows_hyperv_dynamic_memory_vm_physical_bytes", prometheus.Labels{"vm": "GitHubActions"})
testutils.RequireFixtureMetric(t, metrics, hyperv.Name, "windows_hyperv_vm_processor_count", prometheus.Labels{"vm": "GitHubActions"})
// The health query reports failures as 0 instead of an error, so check the value.
if metric := testutils.RequireFixtureMetric(t, metrics, hyperv.Name, "windows_hyperv_wmi_health", nil); metric != nil {
require.InDelta(t, 1, metric.GetGauge().GetValue(), 0, "Hyper-V WMI health query failed")
}
}
+12 -1
View File
@@ -20,8 +20,10 @@ package hyperv
import (
"fmt"
"log/slog"
"strings"
"time"
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -49,7 +51,16 @@ func (c *Collector) buildWMIHealth() error {
return mi.ErrNotInitialized
}
miQuery, err := mi.NewQuery("SELECT Name FROM Msvm_ComputerSystem WHERE Caption = 'Hosting Computer System'")
// The host's Msvm_ComputerSystem is named after the physical NetBIOS name.
// Caption is localized, so it can't be used to select the host.
hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNamePhysicalNetBIOS)
if err != nil {
return fmt.Errorf("failed to get computer name: %w", err)
}
hostname = strings.NewReplacer(`\`, `\\`, `'`, `\'`).Replace(hostname)
miQuery, err := mi.NewQuery("SELECT Name FROM Msvm_ComputerSystem WHERE Name = '" + hostname + "'")
if err != nil {
return fmt.Errorf("failed to create WMI query: %w", err)
}