diff --git a/internal/collector/performancecounter/performancecounter.go b/internal/collector/performancecounter/performancecounter.go index d0ee5d39..3a6616ed 100644 --- a/internal/collector/performancecounter/performancecounter.go +++ b/internal/collector/performancecounter/performancecounter.go @@ -323,7 +323,7 @@ func (c *Collector) collectObject(ch chan<- prometheus.Metric, perfDataObject Ob continue } - if field.Kind() != reflect.TypeFor[prometheus.ValueType]().Kind() { + if field.Type() != reflect.TypeFor[prometheus.ValueType]() { errs = append(errs, fmt.Errorf("failed to cast MetricType for %s to prometheus.ValueType", counter.Name)) continue diff --git a/internal/collector/textfile/textfile.go b/internal/collector/textfile/textfile.go index 0a97d015..d5f0e868 100644 --- a/internal/collector/textfile/textfile.go +++ b/internal/collector/textfile/textfile.go @@ -22,9 +22,9 @@ import ( "fmt" "io" "log/slog" + "maps" "os" "path/filepath" - "reflect" "slices" "sort" "strings" @@ -140,7 +140,7 @@ func duplicateMetricEntry(metricFamilies []*dto.MetricFamily) bool { _, mapContainsKey := uniqueMetrics[metricName] // Duplicate metric found with identical labels & label values - if mapContainsKey && reflect.DeepEqual(uniqueMetrics[metricName], labels) { + if mapContainsKey && maps.Equal(uniqueMetrics[metricName], labels) { return true } diff --git a/internal/config/flatten_test.go b/internal/config/flatten_test.go index 22987f16..41709b81 100644 --- a/internal/config/flatten_test.go +++ b/internal/config/flatten_test.go @@ -18,7 +18,7 @@ package config import ( - "reflect" + "maps" "testing" "go.yaml.in/yaml/v3" @@ -49,7 +49,7 @@ func TestConfigFlattening(t *testing.T) { } flattenedValues := flatten(data) - if !reflect.DeepEqual(expectedResult, flattenedValues) { + if !maps.Equal(expectedResult, flattenedValues) { t.Errorf("Flattened values do not match!\nExpected result: %s\nActual result: %s", expectedResult, flattenedValues) } } diff --git a/internal/pdh/collector.go b/internal/pdh/collector.go index 2d9cb63f..285e5bef 100644 --- a/internal/pdh/collector.go +++ b/internal/pdh/collector.go @@ -110,7 +110,7 @@ func NewCollectorWithReflection(logger *slog.Logger, resultType CounterType, obj } if f, ok := valueType.FieldByName("MetricType"); ok { - if f.Type.Kind() == reflect.TypeFor[prometheus.ValueType]().Kind() { + if f.Type == reflect.TypeFor[prometheus.ValueType]() { collector.metricsTypeIndexValue = f.Index[0] } } diff --git a/internal/pdh/registry/collector.go b/internal/pdh/registry/collector.go index 5b13c8fa..5409f0de 100644 --- a/internal/pdh/registry/collector.go +++ b/internal/pdh/registry/collector.go @@ -109,13 +109,13 @@ func (c *Collector) Collect(data any) error { dv = dv.Elem() - elemType := dv.Type().Elem() - elemValue := reflect.ValueOf(reflect.New(elemType).Interface()).Elem() - - if dv.Kind() != reflect.Slice || elemType.Kind() != reflect.Struct { + if dv.Kind() != reflect.Slice || dv.Type().Elem().Kind() != reflect.Struct { return mi.ErrInvalidEntityType } + elemType := dv.Type().Elem() + elemValue := reflect.ValueOf(reflect.New(elemType).Interface()).Elem() + perfObjects, err := QueryPerformanceData(c.query, c.object) if err != nil { return fmt.Errorf("QueryPerformanceData: %w", err) diff --git a/internal/pdh/registry/perflib_test.go b/internal/pdh/registry/perflib_test.go index c3340b4d..cbd14f69 100644 --- a/internal/pdh/registry/perflib_test.go +++ b/internal/pdh/registry/perflib_test.go @@ -18,7 +18,10 @@ package registry import ( + "errors" "testing" + + "github.com/prometheus-community/windows_exporter/internal/mi" ) // TestNewCollectorStructTypeParam guards against a regression where @@ -37,6 +40,35 @@ func TestNewCollectorStructTypeParam(t *testing.T) { } } +// TestCollectInvalidEntityType guards against a regression where Collect +// called reflect.Type.Elem() on a non-slice destination and panicked instead +// of returning mi.ErrInvalidEntityType. +func TestCollectInvalidEntityType(t *testing.T) { + t.Parallel() + + type counterValues struct { + Name string + } + + c := &Collector{} + + for name, dst := range map[string]any{ + "nil": nil, + "non-pointer": []counterValues{}, + "pointer to struct": &counterValues{}, + "pointer to []int": &[]int{}, + "pointer to integer": new(int), + } { + t.Run(name, func(t *testing.T) { + t.Parallel() + + if err := c.Collect(dst); !errors.Is(err, mi.ErrInvalidEntityType) { + t.Errorf("expected %v, got %v", mi.ErrInvalidEntityType, err) + } + }) + } +} + func BenchmarkQueryPerformanceData(b *testing.B) { for b.Loop() { _, _ = QueryPerformanceData("Global", "")