mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-03-01 08:06:38 +00:00
performancecounter: rename collector (#1787)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
@@ -13,14 +13,12 @@
|
||||
|
||||
//go:build windows
|
||||
|
||||
package perfdata
|
||||
package performancecounter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"maps"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
@@ -30,7 +28,7 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const Name = "perfdata"
|
||||
const Name = "performancecounter"
|
||||
|
||||
type Config struct {
|
||||
Objects []Object `yaml:"objects"`
|
||||
@@ -41,9 +39,11 @@ var ConfigDefaults = Config{
|
||||
Objects: make([]Object, 0),
|
||||
}
|
||||
|
||||
// A Collector is a Prometheus collector for perfdata metrics.
|
||||
// A Collector is a Prometheus collector for performance counter metrics.
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
func New(config *Config) *Collector {
|
||||
@@ -70,7 +70,7 @@ func NewWithFlags(app *kingpin.Application) *Collector {
|
||||
var objects string
|
||||
|
||||
app.Flag(
|
||||
"collector.perfdata.objects",
|
||||
"collector.performancecounter.objects",
|
||||
"Objects of performance data to observe. See docs for more information on how to use this flag. By default, no objects are observed.",
|
||||
).Default("").StringVar(&objects)
|
||||
|
||||
@@ -102,10 +102,19 @@ func (c *Collector) Close() error {
|
||||
}
|
||||
|
||||
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||
logger.Warn("The perfdata collector is in an experimental state! The configuration may change in future. Please report any issues.")
|
||||
c.logger = logger.With(slog.String("collector", Name))
|
||||
|
||||
for i, object := range c.config.Objects {
|
||||
collector, err := perfdata.NewCollector(object.Object, object.Instances, slices.Sorted(maps.Keys(object.Counters)))
|
||||
counters := make([]string, 0, len(object.Counters))
|
||||
for j, counter := range object.Counters {
|
||||
counters = append(counters, counter.Name)
|
||||
|
||||
if counter.Metric == "" {
|
||||
c.config.Objects[i].Counters[j].Metric = sanitizeMetricName(fmt.Sprintf("%s_%s_%s_%s", types.Namespace, Name, object.Object, counter.Name))
|
||||
}
|
||||
}
|
||||
|
||||
collector, err := perfdata.NewCollector(object.Object, object.Instances, counters)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create v2 collector: %w", err)
|
||||
}
|
||||
@@ -123,40 +132,64 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
|
||||
for _, object := range c.config.Objects {
|
||||
data, err := object.collector.Collect()
|
||||
for _, perfDataObject := range c.config.Objects {
|
||||
collectedPerfData, err := perfDataObject.collector.Collect()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to collect data: %w", err)
|
||||
}
|
||||
|
||||
for instance, counters := range data {
|
||||
for counter, value := range counters {
|
||||
var labels prometheus.Labels
|
||||
if instance != perfdata.InstanceEmpty {
|
||||
labels = prometheus.Labels{object.InstanceLabel: instance}
|
||||
for collectedInstance, collectedInstanceCounters := range collectedPerfData {
|
||||
for _, counter := range perfDataObject.Counters {
|
||||
collectedCounterValue, ok := collectedInstanceCounters[counter.Name]
|
||||
if !ok {
|
||||
c.logger.Warn(fmt.Sprintf("counter %s not found in collected data", counter.Name))
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
metricType := value.Type
|
||||
labels := make(prometheus.Labels, len(counter.Labels)+1)
|
||||
if collectedInstance != perfdata.InstanceEmpty {
|
||||
labels[perfDataObject.InstanceLabel] = collectedInstance
|
||||
}
|
||||
|
||||
if val, ok := object.Counters[counter]; ok {
|
||||
switch val.Type {
|
||||
case "counter":
|
||||
metricType = prometheus.CounterValue
|
||||
case "gauge":
|
||||
metricType = prometheus.GaugeValue
|
||||
}
|
||||
for key, value := range counter.Labels {
|
||||
labels[key] = value
|
||||
}
|
||||
|
||||
var metricType prometheus.ValueType
|
||||
|
||||
switch counter.Type {
|
||||
case "counter":
|
||||
metricType = prometheus.CounterValue
|
||||
case "gauge":
|
||||
metricType = prometheus.GaugeValue
|
||||
default:
|
||||
metricType = collectedCounterValue.Type
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
prometheus.NewDesc(
|
||||
sanitizeMetricName(fmt.Sprintf("%s_perfdata_%s_%s", types.Namespace, object.Object, counter)),
|
||||
fmt.Sprintf("Performance data for \\%s\\%s", object.Object, counter),
|
||||
counter.Metric,
|
||||
"windows_exporter: custom Performance Counter metric",
|
||||
nil,
|
||||
labels,
|
||||
),
|
||||
metricType,
|
||||
value.FirstValue,
|
||||
collectedCounterValue.FirstValue,
|
||||
)
|
||||
|
||||
if collectedCounterValue.SecondValue != 0 {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
prometheus.NewDesc(
|
||||
counter.Metric+"_second",
|
||||
"windows_exporter: custom Performance Counter metric",
|
||||
nil,
|
||||
labels,
|
||||
),
|
||||
metricType,
|
||||
collectedCounterValue.SecondValue,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,19 +13,19 @@
|
||||
|
||||
//go:build windows
|
||||
|
||||
package perfdata_test
|
||||
package performancecounter_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/collector/perfdata"
|
||||
"github.com/prometheus-community/windows_exporter/internal/collector/performancecounter"
|
||||
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
|
||||
)
|
||||
|
||||
func BenchmarkCollector(b *testing.B) {
|
||||
perfDataObjects := `[{"object":"Processor Information","instances":["*"],"counters":{"*": {}}}]`
|
||||
perfDataObjects := `[{"object":"Processor Information","instances":["*"],"instance_label":"core","counters":[{"name":"% Processor Time","metric":"windows_performancecounter_processor_information_processor_time","labels":{"state":"active"}},{"name":"% Idle Time","metric":"windows_performancecounter_processor_information_processor_time","labels":{"state":"idle"}}]},{"object":"Memory","counters":[{"name":"Cache Faults/sec","type":"counter"}]}]`
|
||||
kingpin.CommandLine.GetArg("collector.perfdata.objects").StringVar(&perfDataObjects)
|
||||
|
||||
testutils.FuncBenchmarkCollector(b, perfdata.Name, perfdata.NewWithFlags)
|
||||
testutils.FuncBenchmarkCollector(b, performancecounter.Name, performancecounter.NewWithFlags)
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
//go:build windows
|
||||
|
||||
package perfdata_test
|
||||
package performancecounter_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/internal/collector/perfdata"
|
||||
"github.com/prometheus-community/windows_exporter/internal/collector/performancecounter"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
)
|
||||
|
||||
type collectorAdapter struct {
|
||||
perfdata.Collector
|
||||
performancecounter.Collector
|
||||
}
|
||||
|
||||
// Describe implements the prometheus.Collector interface.
|
||||
@@ -51,31 +51,40 @@ func TestCollector(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
object string
|
||||
instances []string
|
||||
counters map[string]perfdata.Counter
|
||||
instanceLabel string
|
||||
counters []performancecounter.Counter
|
||||
expectedMetrics *regexp.Regexp
|
||||
}{
|
||||
{
|
||||
object: "Memory",
|
||||
instances: nil,
|
||||
counters: map[string]perfdata.Counter{"Available Bytes": {Type: "gauge"}},
|
||||
expectedMetrics: regexp.MustCompile(`^# HELP windows_perfdata_memory_available_bytes Performance data for \\\\Memory\\\\Available Bytes\s*# TYPE windows_perfdata_memory_available_bytes gauge\s*windows_perfdata_memory_available_bytes \d`),
|
||||
counters: []performancecounter.Counter{{Name: "Available Bytes", Type: "gauge"}},
|
||||
expectedMetrics: regexp.MustCompile(`^# HELP windows_performancecounter_memory_available_bytes windows_exporter: custom Performance Counter metric\S*\s*# TYPE windows_performancecounter_memory_available_bytes gauge\s*windows_performancecounter_memory_available_bytes \d`),
|
||||
},
|
||||
{
|
||||
object: "Process",
|
||||
instances: []string{"*"},
|
||||
counters: map[string]perfdata.Counter{"Thread Count": {Type: "counter"}},
|
||||
expectedMetrics: regexp.MustCompile(`^# HELP windows_perfdata_process_thread_count Performance data for \\\\Process\\\\Thread Count\s*# TYPE windows_perfdata_process_thread_count counter\s*windows_perfdata_process_thread_count\{instance=".+"} \d`),
|
||||
counters: []performancecounter.Counter{{Name: "Thread Count", Type: "counter"}},
|
||||
expectedMetrics: regexp.MustCompile(`^# HELP windows_performancecounter_process_thread_count windows_exporter: custom Performance Counter metric\S*\s*# TYPE windows_performancecounter_process_thread_count counter\s*windows_performancecounter_process_thread_count\{instance=".+"} \d`),
|
||||
},
|
||||
{
|
||||
object: "Processor Information",
|
||||
instances: []string{"*"},
|
||||
instanceLabel: "core",
|
||||
counters: []performancecounter.Counter{{Name: "% Processor Time", Metric: "windows_performancecounter_processor_information_processor_time", Labels: map[string]string{"state": "active"}}, {Name: "% Idle Time", Metric: "windows_performancecounter_processor_information_processor_time", Labels: map[string]string{"state": "idle"}}},
|
||||
expectedMetrics: regexp.MustCompile(`^# HELP windows_performancecounter_processor_information_processor_time windows_exporter: custom Performance Counter metric\s+# TYPE windows_performancecounter_processor_information_processor_time counter\s+windows_performancecounter_processor_information_processor_time\{core="0,0",state="active"} [0-9.e+]+\s+windows_performancecounter_processor_information_processor_time\{core="0,0",state="idle"} [0-9.e+]+`),
|
||||
},
|
||||
} {
|
||||
t.Run(tc.object, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
perfDataCollector := perfdata.New(&perfdata.Config{
|
||||
Objects: []perfdata.Object{
|
||||
perfDataCollector := performancecounter.New(&performancecounter.Config{
|
||||
Objects: []performancecounter.Object{
|
||||
{
|
||||
Object: tc.object,
|
||||
Instances: tc.instances,
|
||||
Counters: tc.counters,
|
||||
Object: tc.object,
|
||||
Instances: tc.instances,
|
||||
InstanceLabel: tc.instanceLabel,
|
||||
Counters: tc.counters,
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -13,19 +13,24 @@
|
||||
|
||||
//go:build windows
|
||||
|
||||
package perfdata
|
||||
package performancecounter
|
||||
|
||||
import "github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||
|
||||
type Object struct {
|
||||
Object string `json:"object" yaml:"object"`
|
||||
Instances []string `json:"instances" yaml:"instances"`
|
||||
Counters map[string]Counter `json:"counters" yaml:"counters"`
|
||||
InstanceLabel string `json:"instance_label" yaml:"instance_label"` //nolint:tagliatelle
|
||||
Object string `json:"object" yaml:"object"`
|
||||
Instances []string `json:"instances" yaml:"instances"`
|
||||
Counters []Counter `json:"counters" yaml:"counters"`
|
||||
InstanceLabel string `json:"instance_label" yaml:"instance_label"` //nolint:tagliatelle
|
||||
|
||||
collector *perfdata.Collector
|
||||
}
|
||||
|
||||
type Counter struct {
|
||||
Type string `json:"type" yaml:"type"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Type string `json:"type" yaml:"type"`
|
||||
Metric string `json:"metric" yaml:"metric"`
|
||||
Labels map[string]string `json:"labels" yaml:"labels"`
|
||||
}
|
||||
|
||||
// https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/54691ebe11bb9ec32b4e35cd31fcb94a352de134/receiver/windowsperfcountersreceiver/README.md?plain=1#L150
|
||||
Reference in New Issue
Block a user