process, gpu, hyperv, netframework: reuse label pairs of unchanged series (#2685)

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
Jan-Otto Kröpke
2026-10-11 18:47:21 +02:00
committed by GitHub
parent a04d6df97f
commit 897855ac16
36 changed files with 1002 additions and 384 deletions
+41 -26
View File
@@ -26,6 +26,7 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/cfgmgr32"
"github.com/prometheus-community/windows_exporter/internal/headers/gdi32"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -57,6 +58,12 @@ type Collector struct {
// It is replaced in tests to make the discovery deterministic.
discoverGPUDevices func() ([]gdi32.GPUDevice, error)
// labels keeps the label pairs of the series of the last scrape, and
// instances the parsed counter instance names, so neither is built again
// while the GPU process or engine stays.
labels labelcache.Cache
instances instanceCache
// GPU Engine
gpuEnginePerfDataCollector *pdh.Collector[gpuEnginePerfDataCounterValues]
gpuEnginePerfDataObject []gpuEnginePerfDataCounterValues
@@ -140,6 +147,8 @@ func (c *Collector) Close() error {
c.gpuLocalAdapterMemoryPerfDataCollector.Close()
c.gpuNonLocalAdapterMemoryPerfDataCollector.Close()
c.gpuProcessMemoryPerfDataCollector.Close()
c.labels.Reset()
c.instances.reset()
return nil
}
@@ -400,23 +409,29 @@ func (c *Collector) getGPUDevice(luid string) (gpuDevice, bool) {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if err := c.collectGpuEngineMetrics(ch); err != nil {
scrape := c.labels.Begin()
defer scrape.Commit()
instances := c.instances.begin()
defer instances.commit()
if err := c.collectGpuEngineMetrics(ch, scrape, instances); err != nil {
errs = append(errs, err)
}
if err := c.collectGpuAdapterMemoryMetrics(ch); err != nil {
if err := c.collectGpuAdapterMemoryMetrics(ch, scrape, instances); err != nil {
errs = append(errs, err)
}
if err := c.collectGpuLocalAdapterMemoryMetrics(ch); err != nil {
if err := c.collectGpuLocalAdapterMemoryMetrics(ch, scrape, instances); err != nil {
errs = append(errs, err)
}
if err := c.collectGpuNonLocalAdapterMemoryMetrics(ch); err != nil {
if err := c.collectGpuNonLocalAdapterMemoryMetrics(ch, scrape, instances); err != nil {
errs = append(errs, err)
}
if err := c.collectGpuProcessMemoryMetrics(ch); err != nil {
if err := c.collectGpuProcessMemoryMetrics(ch, scrape, instances); err != nil {
errs = append(errs, err)
}
@@ -471,7 +486,7 @@ func (c *Collector) collectGpuInfo(ch chan<- prometheus.Metric) {
}
}
func (c *Collector) collectGpuEngineMetrics(ch chan<- prometheus.Metric) error {
func (c *Collector) collectGpuEngineMetrics(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, instances *instanceScrape) error {
// Collect the GPU Engine perf data.
if err := c.gpuEnginePerfDataCollector.Collect(&c.gpuEnginePerfDataObject); err != nil {
return fmt.Errorf("failed to collect GPU Engine perf data: %w", err)
@@ -479,14 +494,14 @@ func (c *Collector) collectGpuEngineMetrics(ch chan<- prometheus.Metric) error {
// Iterate over the GPU Engine perf data and aggregate the values.
for _, data := range c.gpuEnginePerfDataObject {
instance := parseGPUCounterInstanceString(data.Name)
instance := instances.parse(data.Name)
device, ok := c.getGPUDevice(instance.Luid)
if !ok {
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuEngineRunningTime,
prometheus.CounterValue,
data.RunningTime/10_000_000,
@@ -497,35 +512,35 @@ func (c *Collector) collectGpuEngineMetrics(ch chan<- prometheus.Metric) error {
return nil
}
func (c *Collector) collectGpuAdapterMemoryMetrics(ch chan<- prometheus.Metric) error {
func (c *Collector) collectGpuAdapterMemoryMetrics(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, instances *instanceScrape) error {
// Collect the GPU Adapter Memory perf data.
if err := c.gpuAdapterMemoryPerfDataCollector.Collect(&c.gpuAdapterMemoryPerfDataObject); err != nil {
return fmt.Errorf("failed to collect GPU Adapter Memory perf data: %w", err)
}
for _, data := range c.gpuAdapterMemoryPerfDataObject {
instance := parseGPUCounterInstanceString(data.Name)
instance := instances.parse(data.Name)
device, ok := c.getGPUDevice(instance.Luid)
if !ok {
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuAdapterMemoryDedicatedUsage,
prometheus.GaugeValue,
data.DedicatedUsage,
instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuAdapterMemorySharedUsage,
prometheus.GaugeValue,
data.SharedUsage,
instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuAdapterMemoryTotalCommitted,
prometheus.GaugeValue,
data.TotalCommitted,
@@ -536,21 +551,21 @@ func (c *Collector) collectGpuAdapterMemoryMetrics(ch chan<- prometheus.Metric)
return nil
}
func (c *Collector) collectGpuLocalAdapterMemoryMetrics(ch chan<- prometheus.Metric) error {
func (c *Collector) collectGpuLocalAdapterMemoryMetrics(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, instances *instanceScrape) error {
// Collect the GPU Local Adapter Memory perf data.
if err := c.gpuLocalAdapterMemoryPerfDataCollector.Collect(&c.gpuLocalAdapterMemoryPerfDataObject); err != nil {
return fmt.Errorf("failed to collect GPU Local Adapter Memory perf data: %w", err)
}
for _, data := range c.gpuLocalAdapterMemoryPerfDataObject {
instance := parseGPUCounterInstanceString(data.Name)
instance := instances.parse(data.Name)
device, ok := c.getGPUDevice(instance.Luid)
if !ok {
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuLocalAdapterMemoryUsage,
prometheus.GaugeValue,
data.LocalUsage,
@@ -561,21 +576,21 @@ func (c *Collector) collectGpuLocalAdapterMemoryMetrics(ch chan<- prometheus.Met
return nil
}
func (c *Collector) collectGpuNonLocalAdapterMemoryMetrics(ch chan<- prometheus.Metric) error {
func (c *Collector) collectGpuNonLocalAdapterMemoryMetrics(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, instances *instanceScrape) error {
// Collect the GPU Non Local Adapter Memory perf data.
if err := c.gpuNonLocalAdapterMemoryPerfDataCollector.Collect(&c.gpuNonLocalAdapterMemoryPerfDataObject); err != nil {
return fmt.Errorf("failed to collect GPU Non Local Adapter Memory perf data: %w", err)
}
for _, data := range c.gpuNonLocalAdapterMemoryPerfDataObject {
instance := parseGPUCounterInstanceString(data.Name)
instance := instances.parse(data.Name)
device, ok := c.getGPUDevice(instance.Luid)
if !ok {
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuNonLocalAdapterMemoryUsage,
prometheus.GaugeValue,
data.NonLocalUsage,
@@ -586,49 +601,49 @@ func (c *Collector) collectGpuNonLocalAdapterMemoryMetrics(ch chan<- prometheus.
return nil
}
func (c *Collector) collectGpuProcessMemoryMetrics(ch chan<- prometheus.Metric) error {
func (c *Collector) collectGpuProcessMemoryMetrics(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, instances *instanceScrape) error {
// Collect the GPU Process Memory perf data.
if err := c.gpuProcessMemoryPerfDataCollector.Collect(&c.gpuProcessMemoryPerfDataObject); err != nil {
return fmt.Errorf("failed to collect GPU Process Memory perf data: %w", err)
}
for _, data := range c.gpuProcessMemoryPerfDataObject {
instance := parseGPUCounterInstanceString(data.Name)
instance := instances.parse(data.Name)
device, ok := c.getGPUDevice(instance.Luid)
if !ok {
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuProcessMemoryDedicatedUsage,
prometheus.GaugeValue,
data.DedicatedUsage,
instance.Pid, instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuProcessMemoryLocalUsage,
prometheus.GaugeValue,
data.LocalUsage,
instance.Pid, instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuProcessMemoryNonLocalUsage,
prometheus.GaugeValue,
data.NonLocalUsage,
instance.Pid, instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuProcessMemorySharedUsage,
prometheus.GaugeValue,
data.SharedUsage,
instance.Pid, instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.gpuProcessMemoryTotalCommitted,
prometheus.GaugeValue,
data.TotalCommitted,
+74
View File
@@ -20,6 +20,7 @@ package gpu
import (
"fmt"
"strings"
"sync"
"github.com/prometheus-community/windows_exporter/internal/headers/gdi32"
)
@@ -84,3 +85,76 @@ func parseGPUCounterInstanceString(s string) Instance {
return instance
}
// instanceCache keeps the parsed counter instance names of the last scrape.
// The same instances appear in every scrape while a GPU process or engine
// exists, so they are only parsed once.
type instanceCache struct {
mu sync.Mutex
entries map[string]Instance
}
// instanceScrape parses the instance names of one scrape.
type instanceScrape struct {
cache *instanceCache
// prev is the last committed generation. It is never modified, so it is
// read without holding mu.
prev map[string]Instance
mu sync.Mutex
next map[string]Instance
}
func (c *instanceCache) begin() *instanceScrape {
c.mu.Lock()
prev := c.entries
c.mu.Unlock()
return &instanceScrape{cache: c, prev: prev, next: make(map[string]Instance, len(prev))}
}
func (c *instanceCache) reset() {
c.mu.Lock()
c.entries = nil
c.mu.Unlock()
}
// parse returns parseGPUCounterInstanceString(name), reusing the result of
// the previous scrape.
func (s *instanceScrape) parse(name string) Instance {
instance, ok := s.prev[name]
s.mu.Lock()
if !ok {
instance, ok = s.next[name]
}
s.mu.Unlock()
if !ok {
instance = parseGPUCounterInstanceString(name)
}
s.mu.Lock()
if s.next != nil {
s.next[name] = instance
}
s.mu.Unlock()
return instance
}
// commit makes the instances of this scrape the base of the next one.
func (s *instanceScrape) commit() {
s.mu.Lock()
next := s.next
s.next = nil
s.mu.Unlock()
if next == nil {
return
}
s.cache.mu.Lock()
s.cache.entries = next
s.cache.mu.Unlock()
}
@@ -74,3 +74,38 @@ func TestParseGPUCounterInstanceString(t *testing.T) {
})
}
}
func TestInstanceCache(t *testing.T) {
t.Parallel()
var cache instanceCache
names := []string{
"pid_1234_luid_0x00000000_0x00005678_phys_0_eng_0_engtype_3D",
"pid_1234_luid_0x00000000_0x00005678_phys_0_eng_1_engtype_Compute_0",
"luid_0x00000000_0x00005678_phys_0",
}
for range 3 {
scrape := cache.begin()
for _, name := range names {
require.Equal(t, parseGPUCounterInstanceString(name), scrape.parse(name))
}
scrape.commit()
scrape.commit()
}
require.Len(t, cache.entries, len(names))
// Instances that a scrape doesn't see are dropped.
scrape := cache.begin()
scrape.parse(names[0])
scrape.commit()
require.Len(t, cache.entries, 1)
cache.reset()
require.Empty(t, cache.entries)
}
+14 -4
View File
@@ -27,6 +27,7 @@ import (
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/osversion"
"github.com/prometheus-community/windows_exporter/internal/utils/recovery"
@@ -110,8 +111,13 @@ type Collector struct {
miSession *mi.Session
collectorFns []func(ch chan<- prometheus.Metric) error
collectorFns []func(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error
closeFns []func()
// labels keeps the label pairs of the series of the last scrape. The
// counters change on every scrape, but their VM, switch and adapter
// labels stay the same.
labels labelcache.Cache
}
func New(config *Config) *Collector {
@@ -162,6 +168,7 @@ func (c *Collector) Close() error {
}
c.closeFns = nil
c.labels.Reset()
return nil
}
@@ -169,7 +176,7 @@ func (c *Collector) Close() error {
func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
c.miSession = miSession
c.logger = logger.With(slog.String("collector", Name))
c.collectorFns = make([]func(ch chan<- prometheus.Metric) error, 0, len(c.config.CollectorsEnabled))
c.collectorFns = make([]func(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error, 0, len(c.config.CollectorsEnabled))
c.closeFns = make([]func(), 0, len(c.config.CollectorsEnabled))
if len(c.config.CollectorsEnabled) == 0 {
@@ -178,7 +185,7 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
subCollectors := map[string]struct {
build func() error
collect func(ch chan<- prometheus.Metric) error
collect func(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error
close func()
minBuildNumber uint16
}{
@@ -325,11 +332,14 @@ func (c *Collector) Build(logger *slog.Logger, miSession *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, _ time.Duration) error {
scrape := c.labels.Begin()
defer scrape.Commit()
var g recovery.Group
for _, fn := range c.collectorFns {
g.Go(func() error {
return fn(ch)
return fn(ch, scrape)
})
}
+48 -47
View File
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -417,329 +418,329 @@ func (c *Collector) buildDataStore() error {
return nil
}
func (c *Collector) collectDataStore(ch chan<- prometheus.Metric) error {
func (c *Collector) collectDataStore(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorDataStore.Collect(&c.perfDataObjectDataStore)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V DataStore metrics: %w", err)
}
for _, data := range c.perfDataObjectDataStore {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreFragmentationRatio,
prometheus.GaugeValue,
data.DataStoreFragmentationRatio,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreSectorSize,
prometheus.GaugeValue,
data.DataStoreSectorSize,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreDataAlignment,
prometheus.GaugeValue,
data.DataStoreDataAlignment,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreCurrentReplayLogSize,
prometheus.GaugeValue,
data.DataStoreCurrentReplayLogSize,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreAvailableEntries,
prometheus.GaugeValue,
data.DataStoreAvailableEntries,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreEmptyEntries,
prometheus.GaugeValue,
data.DataStoreEmptyEntries,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreFreeBytes,
prometheus.GaugeValue,
data.DataStoreFreeBytes,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreDataEnd,
prometheus.GaugeValue,
data.DataStoreDataEnd,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreFileObjects,
prometheus.GaugeValue,
data.DataStoreFileObjects,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreObjectTables,
prometheus.GaugeValue,
data.DataStoreObjectTables,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreKeyTables,
prometheus.GaugeValue,
data.DataStoreKeyTables,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreFileDataSize,
prometheus.GaugeValue,
data.DataStoreFileDataSize,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreTableDataSize,
prometheus.GaugeValue,
data.DataStoreTableDataSize,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreNamesSize,
prometheus.GaugeValue,
data.DataStoreNamesSize,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreNumberOfKeys,
prometheus.GaugeValue,
data.DataStoreNumberOfKeys,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreReconnectLatencyMicro,
prometheus.GaugeValue,
data.DataStoreReconnectLatencyMicro,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreDisconnectCount,
prometheus.CounterValue,
data.DataStoreDisconnectCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreWriteToFileByteLatency,
prometheus.GaugeValue,
data.DataStoreWriteToFileByteLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreWriteToFileByteCount,
prometheus.CounterValue,
data.DataStoreWriteToFileByteCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreWriteToFileCount,
prometheus.CounterValue,
data.DataStoreWriteToFileCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreReadFromFileByteLatency,
prometheus.GaugeValue,
data.DataStoreReadFromFileByteLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreReadFromFileByteCount,
prometheus.CounterValue,
data.DataStoreReadFromFileByteCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreReadFromFileCount,
prometheus.CounterValue,
data.DataStoreReadFromFileCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreWriteToStorageByteLatency,
prometheus.GaugeValue,
data.DataStoreWriteToStorageByteLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreWriteToStorageByteCount,
prometheus.CounterValue,
data.DataStoreWriteToStorageByteCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreWriteToStorageCount,
prometheus.CounterValue,
data.DataStoreWriteToStorageCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreReadFromStorageByteLatency,
prometheus.GaugeValue,
data.DataStoreReadFromStorageByteLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreReadFromStorageByteCount,
prometheus.CounterValue,
data.DataStoreReadFromStorageByteCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreReadFromStorageCount,
prometheus.CounterValue,
data.DataStoreReadFromStorageCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreCommitByteLatency,
prometheus.GaugeValue,
data.DataStoreCommitByteLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreCommitByteCount,
prometheus.CounterValue,
data.DataStoreCommitByteCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreCommitCount,
prometheus.CounterValue,
data.DataStoreCommitCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreCacheUpdateOperationLatency,
prometheus.GaugeValue,
data.DataStoreCacheUpdateOperationLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreCacheUpdateOperationCount,
prometheus.CounterValue,
data.DataStoreCacheUpdateOperationCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreCommitOperationLatency,
prometheus.GaugeValue,
data.DataStoreCommitOperationLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreCommitOperationCount,
prometheus.CounterValue,
data.DataStoreCommitOperationCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreCompactOperationLatency,
prometheus.GaugeValue,
data.DataStoreCompactOperationLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreCompactOperationCount,
prometheus.CounterValue,
data.DataStoreCompactOperationCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreLoadFileOperationLatency,
prometheus.GaugeValue,
data.DataStoreLoadFileOperationLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreLoadFileOperationCount,
prometheus.CounterValue,
data.DataStoreLoadFileOperationCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreRemoveOperationLatency,
prometheus.GaugeValue,
data.DataStoreRemoveOperationLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreRemoveOperationCount,
prometheus.CounterValue,
data.DataStoreRemoveOperationCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreQuerySizeOperationLatency,
prometheus.GaugeValue,
data.DataStoreQuerySizeOperationLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreQuerySizeOperationCount,
prometheus.CounterValue,
data.DataStoreQuerySizeOperationCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreSetOperationLatencyMicro,
prometheus.GaugeValue,
data.DataStoreSetOperationLatencyMicro,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.dataStoreSetOperationCount,
prometheus.CounterValue,
data.DataStoreSetOperationCount,
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/osversion"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -85,14 +86,14 @@ func (c *Collector) buildDynamicMemoryBalancer() error {
return nil
}
func (c *Collector) collectDynamicMemoryBalancer(ch chan<- prometheus.Metric) error {
func (c *Collector) collectDynamicMemoryBalancer(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorDynamicMemoryBalancer.Collect(&c.perfDataObjectDynamicMemoryBalancer)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Dynamic Memory Balancer metrics: %w", err)
}
for _, data := range c.perfDataObjectDynamicMemoryBalancer {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmDynamicMemoryBalancerAvailableMemory,
prometheus.GaugeValue,
utils.MBToBytes(data.VmDynamicMemoryBalancerAvailableMemory),
@@ -100,7 +101,7 @@ func (c *Collector) collectDynamicMemoryBalancer(ch chan<- prometheus.Metric) er
)
if osversion.Build() >= osversion.LTSC2019 {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmDynamicMemoryBalancerAvailableMemoryForBalancing,
prometheus.GaugeValue,
utils.MBToBytes(data.VmDynamicMemoryBalancerAvailableMemoryForBalancing),
@@ -108,14 +109,14 @@ func (c *Collector) collectDynamicMemoryBalancer(ch chan<- prometheus.Metric) er
)
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmDynamicMemoryBalancerAveragePressure,
prometheus.GaugeValue,
utils.PercentageToRatio(data.VmDynamicMemoryBalancerAveragePressure),
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmDynamicMemoryBalancerSystemCurrentPressure,
prometheus.GaugeValue,
utils.PercentageToRatio(data.VmDynamicMemoryBalancerSystemCurrentPressure),
@@ -21,6 +21,7 @@ import (
"fmt"
"strings"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/osversion"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -133,7 +134,7 @@ func (c *Collector) buildDynamicMemoryVM() error {
return nil
}
func (c *Collector) collectDynamicMemoryVM(ch chan<- prometheus.Metric) error {
func (c *Collector) collectDynamicMemoryVM(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorDynamicMemoryVM.Collect(&c.perfDataObjectDynamicMemoryVM)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Dynamic Memory VM metrics: %w", err)
@@ -142,14 +143,14 @@ func (c *Collector) collectDynamicMemoryVM(ch chan<- prometheus.Metric) error {
for _, data := range c.perfDataObjectDynamicMemoryVM {
vmName := dynamicMemoryVMName(data.Name)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmMemoryAddedMemory,
prometheus.CounterValue,
utils.MBToBytes(data.VmMemoryAddedMemory),
vmName,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmMemoryCurrentPressure,
prometheus.GaugeValue,
utils.PercentageToRatio(data.VmMemoryCurrentPressure),
@@ -157,7 +158,7 @@ func (c *Collector) collectDynamicMemoryVM(ch chan<- prometheus.Metric) error {
)
if osversion.Build() >= osversion.LTSC2022 {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmMemoryGuestAvailableMemory,
prometheus.GaugeValue,
utils.MBToBytes(data.VmMemoryGuestAvailableMemory),
@@ -165,49 +166,49 @@ func (c *Collector) collectDynamicMemoryVM(ch chan<- prometheus.Metric) error {
)
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmMemoryGuestVisiblePhysicalMemory,
prometheus.GaugeValue,
utils.MBToBytes(data.VmMemoryGuestVisiblePhysicalMemory),
vmName,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmMemoryMaximumPressure,
prometheus.GaugeValue,
utils.PercentageToRatio(data.VmMemoryMaximumPressure),
vmName,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmMemoryMemoryAddOperations,
prometheus.CounterValue,
data.VmMemoryMemoryAddOperations,
vmName,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmMemoryMemoryRemoveOperations,
prometheus.CounterValue,
data.VmMemoryMemoryRemoveOperations,
vmName,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmMemoryMinimumPressure,
prometheus.GaugeValue,
utils.PercentageToRatio(data.VmMemoryMinimumPressure),
vmName,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmMemoryPhysicalMemory,
prometheus.GaugeValue,
utils.MBToBytes(data.VmMemoryPhysicalMemory),
vmName,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmMemoryRemovedMemory,
prometheus.CounterValue,
utils.MBToBytes(data.VmMemoryRemovedMemory),
+5 -4
View File
@@ -24,6 +24,7 @@ import (
"log/slog"
"github.com/prometheus-community/windows_exporter/internal/headers/hcs"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -105,7 +106,7 @@ func (c *Collector) buildHost() error {
return nil
}
func (c *Collector) collectHost(ch chan<- prometheus.Metric) error {
func (c *Collector) collectHost(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorLogicalProcessor.Collect(&c.perfDataObjectLogicalProcessor)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Hypervisor Logical Processor metrics: %w", err)
@@ -125,7 +126,7 @@ func (c *Collector) collectHost(ch chan<- prometheus.Metric) error {
processorCount := float64(vm.ProcessorCount)
totalVirtualCoreCount += processorCount
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.vmProcessorCount,
prometheus.GaugeValue,
processorCount,
@@ -134,13 +135,13 @@ func (c *Collector) collectHost(ch chan<- prometheus.Metric) error {
}
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hostLogicalProcessorCount,
prometheus.GaugeValue,
logicalCoreCount,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.totalVMProcessorCount,
prometheus.GaugeValue,
totalVirtualCoreCount,
@@ -21,6 +21,7 @@ import (
"fmt"
"strings"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -80,7 +81,7 @@ func (c *Collector) buildHypervisorLogicalProcessor() error {
return nil
}
func (c *Collector) collectHypervisorLogicalProcessor(ch chan<- prometheus.Metric) error {
func (c *Collector) collectHypervisorLogicalProcessor(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorHypervisorLogicalProcessor.Collect(&c.perfDataObjectHypervisorLogicalProcessor)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Hypervisor Logical Processor metrics: %w", err)
@@ -95,35 +96,35 @@ func (c *Collector) collectHypervisorLogicalProcessor(ch chan<- prometheus.Metri
coreID := parts[2]
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorLogicalProcessorTimeTotal,
prometheus.CounterValue,
data.HypervisorLogicalProcessorGuestRunTimePercent,
coreID, "guest",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorLogicalProcessorTimeTotal,
prometheus.CounterValue,
data.HypervisorLogicalProcessorHypervisorRunTimePercent,
coreID, "hypervisor",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorLogicalProcessorTimeTotal,
prometheus.CounterValue,
data.HypervisorLogicalProcessorIdleRunTimePercent,
coreID, "idle",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorLogicalProcessorTotalRunTimeTotal,
prometheus.CounterValue,
data.HypervisorLogicalProcessorTotalRunTimePercent,
coreID,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorLogicalProcessorContextSwitches,
prometheus.CounterValue,
data.HypervisorLogicalProcessorContextSwitches,
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
pdhtypes "github.com/prometheus-community/windows_exporter/internal/pdh/types"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -220,133 +221,133 @@ func (c *Collector) buildHypervisorRootPartitionDescriptors() {
)
}
func (c *Collector) collectHypervisorRootPartition(ch chan<- prometheus.Metric) error {
func (c *Collector) collectHypervisorRootPartition(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorHypervisorRootPartition.Collect(&c.perfDataObjectHypervisorRootPartition)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Hypervisor Root Partition metrics: %w", err)
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionAddressSpaces,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionAddressSpaces,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionAttachedDevices,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionAttachedDevices,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionDepositedPages,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionDepositedPages,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionDeviceDMAErrors,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionDeviceDMAErrors,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionDeviceInterruptErrors,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionDeviceInterruptErrors,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionDeviceInterruptMappings,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionDeviceInterruptMappings,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionDeviceInterruptThrottleEvents,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionDeviceInterruptThrottleEvents,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionGPAPages,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionGPAPages,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionGPASpaceModifications,
prometheus.CounterValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionGPASpaceModifications,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionIOTLBFlushCost,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionIOTLBFlushCost,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionIOTLBFlushes,
prometheus.CounterValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionIOTLBFlushes,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionRecommendedVirtualTLBSize,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionRecommendedVirtualTLBSize,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionSkippedTimerTicks,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionSkippedTimerTicks,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartition1GDevicePages,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition1GDevicePages,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartition1GGPAPages,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition1GGPAPages,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartition2MDevicePages,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition2MDevicePages,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartition2MGPAPages,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition2MGPAPages,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartition4KDevicePages,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition4KDevicePages,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartition4KGPAPages,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition4KGPAPages,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionVirtualTLBFlushEntries,
prometheus.CounterValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionVirtualTLBFlushEntries,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootPartitionVirtualTLBPages,
prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionVirtualTLBPages,
@@ -21,6 +21,7 @@ import (
"fmt"
"strings"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -82,7 +83,7 @@ func (c *Collector) buildHypervisorRootVirtualProcessor() error {
return nil
}
func (c *Collector) collectHypervisorRootVirtualProcessor(ch chan<- prometheus.Metric) error {
func (c *Collector) collectHypervisorRootVirtualProcessor(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorHypervisorRootVirtualProcessor.Collect(&c.perfDataObjectHypervisorRootVirtualProcessor)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Hypervisor Root Virtual Processor metrics: %w", err)
@@ -97,35 +98,35 @@ func (c *Collector) collectHypervisorRootVirtualProcessor(ch chan<- prometheus.M
coreID := parts[2]
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootVirtualProcessorTimeTotal,
prometheus.CounterValue,
data.HypervisorRootVirtualProcessorGuestRunTimePercent,
coreID, "guest_run",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootVirtualProcessorTimeTotal,
prometheus.CounterValue,
data.HypervisorRootVirtualProcessorHypervisorRunTimePercent,
coreID, "hypervisor",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootVirtualProcessorTimeTotal,
prometheus.CounterValue,
data.HypervisorRootVirtualProcessorRemoteRunTimePercent,
coreID, "remote",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootVirtualProcessorTotalRunTimeTotal,
prometheus.CounterValue,
data.HypervisorRootVirtualProcessorTotalRunTimePercent,
coreID,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorRootVirtualProcessorCPUWaitTimePerDispatch,
prometheus.CounterValue,
data.HypervisorRootVirtualProcessorCPUWaitTimePerDispatch,
@@ -21,6 +21,7 @@ import (
"fmt"
"strings"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -97,7 +98,7 @@ func (c *Collector) buildHypervisorVirtualProcessor() error {
return nil
}
func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metric) error {
func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorHypervisorVirtualProcessor.Collect(&c.perfDataObjectHypervisorVirtualProcessor)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Hypervisor Virtual Processor metrics: %w", err)
@@ -118,63 +119,63 @@ func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metri
vmName := parts[0]
coreID := coreParts[2]
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorVirtualProcessorTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorHypervisorRunTimePercent,
vmName, coreID, "hypervisor",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorVirtualProcessorTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorGuestRunTimePercent,
vmName, coreID, "guest",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorVirtualProcessorTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorRemoteRunTimePercent,
vmName, coreID, "remote",
)
// Same metric with new name for better clarity, old one is kept for backward compatibility
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorVirtualProcessorModeTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorHypervisorRunTimePercent,
vmName, coreID, "hypervisor",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorVirtualProcessorModeTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorGuestRunTimePercent,
vmName, coreID, "guest",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorVirtualProcessorModeTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorRemoteRunTimePercent,
vmName, coreID, "remote",
)
// end same metric
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorVirtualProcessorTotalRunTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorTotalRunTimePercent,
vmName, coreID,
)
// Same metric with new name for better clarity, old one is kept for backward compatibility
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorVirtualProcessorRunTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorTotalRunTimePercent,
vmName, coreID,
)
// end same metric
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.hypervisorVirtualProcessorContextSwitches,
prometheus.CounterValue,
data.HypervisorVirtualProcessorCPUWaitTimePerDispatch,
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -97,49 +98,49 @@ func (c *Collector) buildLegacyNetworkAdapter() error {
return nil
}
func (c *Collector) collectLegacyNetworkAdapter(ch chan<- prometheus.Metric) error {
func (c *Collector) collectLegacyNetworkAdapter(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorLegacyNetworkAdapter.Collect(&c.perfDataObjectLegacyNetworkAdapter)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Legacy Network Adapter metrics: %w", err)
}
for _, data := range c.perfDataObjectLegacyNetworkAdapter {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.legacyNetworkAdapterBytesDropped,
prometheus.CounterValue,
data.LegacyNetworkAdapterBytesDropped,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.legacyNetworkAdapterBytesReceived,
prometheus.CounterValue,
data.LegacyNetworkAdapterBytesReceived,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.legacyNetworkAdapterBytesSent,
prometheus.CounterValue,
data.LegacyNetworkAdapterBytesSent,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.legacyNetworkAdapterFramesReceived,
prometheus.CounterValue,
data.LegacyNetworkAdapterFramesReceived,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.legacyNetworkAdapterFramesDropped,
prometheus.CounterValue,
data.LegacyNetworkAdapterFramesDropped,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.legacyNetworkAdapterFramesSent,
prometheus.CounterValue,
data.LegacyNetworkAdapterFramesSent,
+17 -16
View File
@@ -24,6 +24,7 @@ import (
"strings"
"time"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -177,14 +178,14 @@ func (c *Collector) buildReplicaVM() error {
return nil
}
func (c *Collector) collectReplicaVM(ch chan<- prometheus.Metric) error {
func (c *Collector) collectReplicaVM(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
return errors.Join(
c.collectReplicaVMPerfData(ch),
c.collectReplicaVMRelationships(ch),
c.collectReplicaVMPerfData(ch, scrape),
c.collectReplicaVMRelationships(ch, scrape),
)
}
func (c *Collector) collectReplicaVMPerfData(ch chan<- prometheus.Metric) error {
func (c *Collector) collectReplicaVMPerfData(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
if c.perfDataCollectorReplicaVM == nil {
return nil
}
@@ -198,63 +199,63 @@ func (c *Collector) collectReplicaVMPerfData(ch chan<- prometheus.Metric) error
}
for _, data := range c.perfDataObjectReplicaVM {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMAverageReplicationLatency,
prometheus.GaugeValue,
data.AverageReplicationLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMAverageReplicationSize,
prometheus.GaugeValue,
data.AverageReplicationSize,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMCompressionEfficiency,
prometheus.GaugeValue,
data.CompressionEfficiency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMLastReplicationSize,
prometheus.GaugeValue,
data.LastReplicationSize,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMNetworkReceivedBytes,
prometheus.CounterValue,
data.NetworkBytesRecv,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMNetworkSentBytes,
prometheus.CounterValue,
data.NetworkBytesSent,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMReplicationCount,
prometheus.CounterValue,
data.ReplicationCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMReplicationLatency,
prometheus.GaugeValue,
data.ReplicationLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMResynchronizedBytes,
prometheus.CounterValue,
data.ResynchronizedBytes,
@@ -265,7 +266,7 @@ func (c *Collector) collectReplicaVMPerfData(ch chan<- prometheus.Metric) error
return nil
}
func (c *Collector) collectReplicaVMRelationships(ch chan<- prometheus.Metric) error {
func (c *Collector) collectReplicaVMRelationships(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
var dst []msvmReplicationRelationship
if err := c.miSession.Query(&dst, mi.NamespaceRootVirtualizationV2, c.miQueryReplicaVM, replicaVMQueryTimeout); err != nil {
@@ -275,7 +276,7 @@ func (c *Collector) collectReplicaVMRelationships(ch chan<- prometheus.Metric) e
for _, relationship := range dst {
relationshipType := replicationRelationshipType(relationship.InstanceID)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMHealth,
prometheus.GaugeValue,
float64(relationship.ReplicationHealth),
@@ -283,7 +284,7 @@ func (c *Collector) collectReplicaVMRelationships(ch chan<- prometheus.Metric) e
relationshipType,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.replicaVMState,
prometheus.GaugeValue,
float64(relationship.ReplicationState),
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -59,20 +60,20 @@ func (c *Collector) buildVirtualMachineHealthSummary() error {
return nil
}
func (c *Collector) collectVirtualMachineHealthSummary(ch chan<- prometheus.Metric) error {
func (c *Collector) collectVirtualMachineHealthSummary(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorVirtualMachineHealthSummary.Collect(&c.perfDataObjectVirtualMachineHealthSummary)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual Machine Health Summary metrics: %w", err)
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.health,
prometheus.GaugeValue,
c.perfDataObjectVirtualMachineHealthSummary[0].HealthCritical,
"critical",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.health,
prometheus.GaugeValue,
c.perfDataObjectVirtualMachineHealthSummary[0].HealthOk,
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -73,28 +74,28 @@ func (c *Collector) buildVirtualMachineVidPartition() error {
return nil
}
func (c *Collector) collectVirtualMachineVidPartition(ch chan<- prometheus.Metric) error {
func (c *Collector) collectVirtualMachineVidPartition(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorVirtualMachineVidPartition.Collect(&c.perfDataObjectVirtualMachineVidPartition)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V VM Vid Partition metrics: %w", err)
}
for _, data := range c.perfDataObjectVirtualMachineVidPartition {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.physicalPagesAllocated,
prometheus.GaugeValue,
data.PhysicalPagesAllocated,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.preferredNUMANodeIndex,
prometheus.GaugeValue,
data.PreferredNUMANodeIndex,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.remotePhysicalPages,
prometheus.GaugeValue,
data.RemotePhysicalPages,
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -97,49 +98,49 @@ func (c *Collector) buildVirtualNetworkAdapter() error {
return nil
}
func (c *Collector) collectVirtualNetworkAdapter(ch chan<- prometheus.Metric) error {
func (c *Collector) collectVirtualNetworkAdapter(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorVirtualNetworkAdapter.Collect(&c.perfDataObjectVirtualNetworkAdapter)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual Network Adapter metrics: %w", err)
}
for _, data := range c.perfDataObjectVirtualNetworkAdapter {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterBytesReceived,
prometheus.CounterValue,
data.VirtualNetworkAdapterBytesReceived,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterBytesSent,
prometheus.CounterValue,
data.VirtualNetworkAdapterBytesSent,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDroppedPacketsIncoming,
prometheus.CounterValue,
data.VirtualNetworkAdapterDroppedPacketsIncoming,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDroppedPacketsOutgoing,
prometheus.CounterValue,
data.VirtualNetworkAdapterDroppedPacketsOutgoing,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterPacketsReceived,
prometheus.CounterValue,
data.VirtualNetworkAdapterPacketsReceived,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterPacketsSent,
prometheus.CounterValue,
data.VirtualNetworkAdapterPacketsSent,
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -182,357 +183,357 @@ func (c *Collector) buildVirtualNetworkAdapterDropReasons() error {
return nil
}
func (c *Collector) collectVirtualNetworkAdapterDropReasons(ch chan<- prometheus.Metric) error {
func (c *Collector) collectVirtualNetworkAdapterDropReasons(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorVirtualNetworkAdapterDropReasons.Collect(&c.perfDataObjectVirtualNetworkAdapterDropReasons)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual Network Adapter Drop Reasons metrics: %w", err)
}
for _, data := range c.perfDataObjectVirtualNetworkAdapterDropReasons {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingNativeFwdingReq,
data.Name, "NativeFwdingReq", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingNativeFwdingReq,
data.Name, "NativeFwdingReq", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingMTUMismatch,
data.Name, "MTUMismatch", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingMTUMismatch,
data.Name, "MTUMismatch", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingInvalidConfig,
data.Name, "InvalidConfig", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingInvalidConfig,
data.Name, "InvalidConfig", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingRequiredExtensionMissing,
data.Name, "RequiredExtensionMissing", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingRequiredExtensionMissing,
data.Name, "RequiredExtensionMissing", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingVirtualSubnetId,
data.Name, "VirtualSubnetId", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingVirtualSubnetId,
data.Name, "VirtualSubnetId", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingBridgeReserved,
data.Name, "BridgeReserved", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingBridgeReserved,
data.Name, "BridgeReserved", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingRouterGuard,
data.Name, "RouterGuard", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingRouterGuard,
data.Name, "RouterGuard", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingDhcpGuard,
data.Name, "DhcpGuard", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingDhcpGuard,
data.Name, "DhcpGuard", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingMacSpoofing,
data.Name, "MacSpoofing", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingMacSpoofing,
data.Name, "MacSpoofing", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingIpsec,
data.Name, "Ipsec", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingIpsec,
data.Name, "Ipsec", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingQos,
data.Name, "Qos", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingQos,
data.Name, "Qos", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingFailedPvlanSetting,
data.Name, "FailedPvlanSetting", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingFailedPvlanSetting,
data.Name, "FailedPvlanSetting", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingFailedSecurityPolicy,
data.Name, "FailedSecurityPolicy", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingFailedSecurityPolicy,
data.Name, "FailedSecurityPolicy", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingUnauthorizedMAC,
data.Name, "UnauthorizedMAC", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingUnauthorizedMAC,
data.Name, "UnauthorizedMAC", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingUnauthorizedVLAN,
data.Name, "UnauthorizedVLAN", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingUnauthorizedVLAN,
data.Name, "UnauthorizedVLAN", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingFilteredVLAN,
data.Name, "FilteredVLAN", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingFilteredVLAN,
data.Name, "FilteredVLAN", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingFiltered,
data.Name, "Filtered", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingFiltered,
data.Name, "Filtered", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingBusy,
data.Name, "Busy", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingBusy,
data.Name, "Busy", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingNotAccepted,
data.Name, "NotAccepted", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingNotAccepted,
data.Name, "NotAccepted", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingDisconnected,
data.Name, "Disconnected", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingDisconnected,
data.Name, "Disconnected", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingNotReady,
data.Name, "NotReady", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingNotReady,
data.Name, "NotReady", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingResources,
data.Name, "Resources", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingResources,
data.Name, "Resources", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingInvalidPacket,
data.Name, "InvalidPacket", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingInvalidPacket,
data.Name, "InvalidPacket", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingInvalidData,
data.Name, "InvalidData", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingInvalidData,
data.Name, "InvalidData", "incoming",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingUnknown,
data.Name, "Unknown", "outgoing",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingUnknown,
+19 -18
View File
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -185,126 +186,126 @@ func (c *Collector) buildVirtualSMB() error {
return nil
}
func (c *Collector) collectVirtualSMB(ch chan<- prometheus.Metric) error {
func (c *Collector) collectVirtualSMB(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorVirtualSMB.Collect(&c.perfDataObjectVirtualSMB)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual SMB metrics: %w", err)
}
for _, data := range c.perfDataObjectVirtualSMB {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBDirectMappedSections,
prometheus.GaugeValue,
data.VirtualSMBDirectMappedSections,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBDirectMappedPages,
prometheus.GaugeValue,
data.VirtualSMBDirectMappedPages,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBWriteBytesRDMA,
prometheus.CounterValue,
data.VirtualSMBWriteBytesRDMA,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBWriteBytes,
prometheus.CounterValue,
data.VirtualSMBWriteBytes,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBReadBytesRDMA,
prometheus.CounterValue,
data.VirtualSMBReadBytesRDMA,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBReadBytes,
prometheus.CounterValue,
data.VirtualSMBReadBytes,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBFlushRequests,
prometheus.CounterValue,
data.VirtualSMBFlushRequests,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBWriteRequestsRDMA,
prometheus.CounterValue,
data.VirtualSMBWriteRequestsRDMA,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBWriteRequests,
prometheus.CounterValue,
data.VirtualSMBWriteRequests,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBReadRequestsRDMA,
prometheus.CounterValue,
data.VirtualSMBReadRequestsRDMA,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBReadRequests,
prometheus.CounterValue,
data.VirtualSMBReadRequests,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBCurrentPendingRequests,
prometheus.GaugeValue,
data.VirtualSMBCurrentPendingRequests,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBCurrentOpenFileCount,
prometheus.GaugeValue,
data.VirtualSMBCurrentOpenFileCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBTreeConnectCount,
prometheus.GaugeValue,
data.VirtualSMBTreeConnectCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBRequests,
prometheus.CounterValue,
data.VirtualSMBRequests,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBSentBytes,
prometheus.CounterValue,
data.VirtualSMBSentBytes,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSMBReceivedBytes,
prometheus.CounterValue,
data.VirtualSMBReceivedBytes,
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -165,91 +166,91 @@ func (c *Collector) buildVirtualStorageDevice() error {
return nil
}
func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric) error {
func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorVirtualStorageDevice.Collect(&c.perfDataObjectVirtualStorageDevice)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual Storage Device metrics: %w", err)
}
for _, data := range c.perfDataObjectVirtualStorageDevice {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceErrorCount,
prometheus.CounterValue,
data.VirtualStorageDeviceErrorCount,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceQueueLength,
prometheus.GaugeValue,
data.VirtualStorageDeviceQueueLength,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceReadBytes,
prometheus.CounterValue,
data.VirtualStorageDeviceReadBytes,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceReadOperations,
prometheus.CounterValue,
data.VirtualStorageDeviceReadOperations,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceWriteBytes,
prometheus.CounterValue,
data.VirtualStorageDeviceWriteBytes,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceWriteOperations,
prometheus.CounterValue,
data.VirtualStorageDeviceWriteOperations,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceLatency,
prometheus.GaugeValue,
data.VirtualStorageDeviceLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceThroughput,
prometheus.CounterValue,
data.VirtualStorageDeviceThroughput,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceNormalizedThroughput,
prometheus.GaugeValue,
data.VirtualStorageDeviceNormalizedThroughput,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceLowerQueueLength,
prometheus.GaugeValue,
data.VirtualStorageDeviceLowerQueueLength,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceLowerLatency,
prometheus.GaugeValue,
data.VirtualStorageDeviceLowerLatency,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceIOQuotaReplenishmentRate,
prometheus.GaugeValue,
data.VirtualStorageDeviceIOQuotaReplenishmentRate,
@@ -258,14 +259,14 @@ func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric) err
// The raw value of a PERF_AVERAGE_TIMER counter is the sum of all IO latencies in
// 100ns ticks; the operation count it is averaged over is Throughput.
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceIOLatency,
prometheus.CounterValue,
data.VirtualStorageDeviceLatency*pdh.TicksToSecondScaleFactor,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualStorageDeviceLowerIOLatency,
prometheus.CounterValue,
data.VirtualStorageDeviceLowerLatency*pdh.TicksToSecondScaleFactor,
@@ -20,6 +20,7 @@ package hyperv
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -217,154 +218,154 @@ func (c *Collector) buildVirtualSwitch() error {
return nil
}
func (c *Collector) collectVirtualSwitch(ch chan<- prometheus.Metric) error {
func (c *Collector) collectVirtualSwitch(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
err := c.perfDataCollectorVirtualSwitch.Collect(&c.perfDataObjectVirtualSwitch)
if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual Switch metrics: %w", err)
}
for _, data := range c.perfDataObjectVirtualSwitch {
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchBroadcastPacketsReceived,
prometheus.CounterValue,
data.VirtualSwitchBroadcastPacketsReceived,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchBroadcastPacketsSent,
prometheus.CounterValue,
data.VirtualSwitchBroadcastPacketsSent,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchBytes,
prometheus.CounterValue,
data.VirtualSwitchBytes,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchBytesReceived,
prometheus.CounterValue,
data.VirtualSwitchBytesReceived,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchBytesSent,
prometheus.CounterValue,
data.VirtualSwitchBytesSent,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchDirectedPacketsReceived,
prometheus.CounterValue,
data.VirtualSwitchDirectedPacketsReceived,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchDirectedPacketsSent,
prometheus.CounterValue,
data.VirtualSwitchDirectedPacketsSent,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchDroppedPacketsIncoming,
prometheus.CounterValue,
data.VirtualSwitchDroppedPacketsIncoming,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchDroppedPacketsOutgoing,
prometheus.CounterValue,
data.VirtualSwitchDroppedPacketsOutgoing,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchExtensionsDroppedPacketsIncoming,
prometheus.CounterValue,
data.VirtualSwitchExtensionsDroppedPacketsIncoming,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchExtensionsDroppedPacketsOutgoing,
prometheus.CounterValue,
data.VirtualSwitchExtensionsDroppedPacketsOutgoing,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchLearnedMacAddresses,
prometheus.CounterValue,
data.VirtualSwitchLearnedMacAddresses,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchMulticastPacketsReceived,
prometheus.CounterValue,
data.VirtualSwitchMulticastPacketsReceived,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchMulticastPacketsSent,
prometheus.CounterValue,
data.VirtualSwitchMulticastPacketsSent,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchNumberOfSendChannelMoves,
prometheus.CounterValue,
data.VirtualSwitchNumberOfSendChannelMoves,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchNumberOfVMQMoves,
prometheus.CounterValue,
data.VirtualSwitchNumberOfVMQMoves,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchPacketsFlooded,
prometheus.CounterValue,
data.VirtualSwitchPacketsFlooded,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchPackets,
prometheus.CounterValue,
data.VirtualSwitchPackets,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchPacketsReceived,
prometheus.CounterValue,
data.VirtualSwitchPacketsReceived,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchPacketsSent,
prometheus.CounterValue,
data.VirtualSwitchPacketsSent,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualSwitchPurgedMacAddresses,
prometheus.CounterValue,
data.VirtualSwitchPurgedMacAddresses,
@@ -24,6 +24,7 @@ import (
"time"
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -79,7 +80,7 @@ func (c *Collector) buildWMIHealth() error {
// collectWMIHealth reports 1 if a minimal query against the Hyper-V WMI
// namespace succeeds and 0 otherwise.
func (c *Collector) collectWMIHealth(ch chan<- prometheus.Metric) error {
func (c *Collector) collectWMIHealth(ch chan<- prometheus.Metric, scrape *labelcache.Scrape) error {
var dst []msvmComputerSystem
healthValue := 1.0
@@ -90,7 +91,7 @@ func (c *Collector) collectWMIHealth(ch chan<- prometheus.Metric) error {
healthValue = 0.0
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.wmiHealth,
prometheus.GaugeValue,
healthValue,
@@ -32,7 +32,7 @@ func TestRootPartitionInterruptMappings(t *testing.T) {
c.buildHypervisorRootPartitionDescriptors()
c.perfDataCollectorHypervisorRootPartition = interruptMappingFixture{}
metrics := make(chan prometheus.Metric, 100)
require.NoError(t, c.collectHypervisorRootPartition(metrics))
require.NoError(t, c.collectHypervisorRootPartition(metrics, nil))
close(metrics)
found := false
@@ -28,6 +28,7 @@ import (
"unsafe"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/utils/recovery"
@@ -73,6 +74,10 @@ const (
// A Collector collects .NET Framework performance counters.
type Collector struct {
// labels keeps the label pairs of the series of the last scrape. The
// counters change on every scrape, but their process labels stay the
// same while the process runs.
labels labelcache.Cache
config Config
logger *slog.Logger
perfFrequency float64
@@ -86,7 +91,7 @@ type Collector struct {
perfClrRemoting perfCollector[perfDataClrRemoting]
perfClrSecurity perfCollector[perfDataClrSecurity]
collectorFns []func(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error
collectorFns []func(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, maxScrapeDuration time.Duration) error
// clrexceptions
numberOfExceptionsThrown *prometheus.Desc
@@ -203,6 +208,7 @@ func (c *Collector) Close() error {
c.closeFns = nil
c.collectorFns = nil
c.labels.Reset()
return nil
}
@@ -224,11 +230,11 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.perfFrequency = float64(frequency)
}
c.collectorFns = make([]func(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error, 0, len(c.config.CollectorsEnabled))
c.collectorFns = make([]func(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, maxScrapeDuration time.Duration) error, 0, len(c.config.CollectorsEnabled))
subCollectors := map[string]struct {
build func() error
collect func(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error
collect func(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, maxScrapeDuration time.Duration) error
close func()
}{
collectorClrExceptions: {
@@ -334,11 +340,14 @@ 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, maxScrapeDuration time.Duration) error {
scrape := c.labels.Begin()
defer scrape.Commit()
var g recovery.Group
for _, fn := range c.collectorFns {
g.Go(func() error {
return fn(ch, maxScrapeDuration)
return fn(ch, scrape, maxScrapeDuration)
})
}
@@ -21,6 +21,7 @@ import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -70,7 +71,7 @@ type perfDataClrExceptions struct {
ThrowToCatchDepthPersec float64 `perfdata:"Throw To Catch Depth / sec"`
}
func (c *Collector) collectClrExceptions(ch chan<- prometheus.Metric, _ time.Duration) error {
func (c *Collector) collectClrExceptions(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, _ time.Duration) error {
var dst []perfDataClrExceptions
if err := c.perfClrExceptions.Collect(&dst); err != nil {
return fmt.Errorf("failed to collect .NET CLR Exceptions: %w", err)
@@ -81,28 +82,28 @@ func (c *Collector) collectClrExceptions(ch chan<- prometheus.Metric, _ time.Dur
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfExceptionsThrown,
prometheus.CounterValue,
float64(process.NumberofExcepsThrown),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfFilters,
prometheus.CounterValue,
float64(process.NumberofFiltersPersec),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfFinally,
prometheus.CounterValue,
float64(process.NumberofFinallysPersec),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.throwToCatchDepth,
prometheus.CounterValue,
float64(process.ThrowToCatchDepthPersec),
@@ -21,6 +21,7 @@ import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -63,7 +64,7 @@ type perfDataClrInterop struct {
Numberofmarshalling float64 `perfdata:"# of marshalling"`
}
func (c *Collector) collectClrInterop(ch chan<- prometheus.Metric, _ time.Duration) error {
func (c *Collector) collectClrInterop(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, _ time.Duration) error {
var dst []perfDataClrInterop
if err := c.perfClrInterop.Collect(&dst); err != nil {
return fmt.Errorf("failed to collect .NET CLR Interop: %w", err)
@@ -74,21 +75,21 @@ func (c *Collector) collectClrInterop(ch chan<- prometheus.Metric, _ time.Durati
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfCCWs,
prometheus.CounterValue,
float64(process.NumberofCCWs),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfMarshalling,
prometheus.CounterValue,
float64(process.Numberofmarshalling),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfStubs,
prometheus.CounterValue,
float64(process.NumberofStubs),
@@ -21,6 +21,7 @@ import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -70,7 +71,7 @@ type perfDataClrJIT struct {
TotalNumberofILBytesJitted float64 `perfdata:"Total # of IL Bytes Jitted"`
}
func (c *Collector) collectClrJIT(ch chan<- prometheus.Metric, _ time.Duration) error {
func (c *Collector) collectClrJIT(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, _ time.Duration) error {
var dst []perfDataClrJIT
if err := c.perfClrJIT.Collect(&dst); err != nil {
return fmt.Errorf("failed to collect .NET CLR Jit: %w", err)
@@ -81,28 +82,28 @@ func (c *Collector) collectClrJIT(ch chan<- prometheus.Metric, _ time.Duration)
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfMethodsJitted,
prometheus.CounterValue,
float64(process.NumberofMethodsJitted),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.timeInJit,
prometheus.GaugeValue,
float64(process.PercentTimeinJit)/c.perfFrequency,
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.standardJitFailures,
prometheus.GaugeValue,
float64(process.StandardJitFailures),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.totalNumberOfILBytesJitted,
prometheus.CounterValue,
float64(process.TotalNumberofILBytesJitted),
@@ -21,6 +21,7 @@ import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -105,7 +106,7 @@ type perfDataClrLoading struct {
Totalappdomainsunloaded float64 `perfdata:"Total appdomains unloaded"`
}
func (c *Collector) collectClrLoading(ch chan<- prometheus.Metric, _ time.Duration) error {
func (c *Collector) collectClrLoading(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, _ time.Duration) error {
var dst []perfDataClrLoading
if err := c.perfClrLoading.Collect(&dst); err != nil {
return fmt.Errorf("failed to collect .NET CLR Loading: %w", err)
@@ -116,63 +117,63 @@ func (c *Collector) collectClrLoading(ch chan<- prometheus.Metric, _ time.Durati
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.bytesInLoaderHeap,
prometheus.GaugeValue,
float64(process.BytesinLoaderHeap),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.currentAppDomains,
prometheus.GaugeValue,
float64(process.Currentappdomains),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.currentAssemblies,
prometheus.GaugeValue,
float64(process.CurrentAssemblies),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.currentClassesLoaded,
prometheus.GaugeValue,
float64(process.CurrentClassesLoaded),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.totalAppDomains,
prometheus.CounterValue,
float64(process.TotalAppdomains),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.totalAppDomainsUnloaded,
prometheus.CounterValue,
float64(process.Totalappdomainsunloaded),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.totalAssemblies,
prometheus.CounterValue,
float64(process.TotalAssemblies),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.totalClassesLoaded,
prometheus.CounterValue,
float64(process.TotalClassesLoaded),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.totalNumberOfLoadFailures,
prometheus.CounterValue,
float64(process.TotalNumberofLoadFailures),
@@ -21,6 +21,7 @@ import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -91,7 +92,7 @@ type perfDataClrLocksAndThreads struct {
TotalNumberofContentions float64 `perfdata:"Total # of Contentions"`
}
func (c *Collector) collectClrLocksAndThreads(ch chan<- prometheus.Metric, _ time.Duration) error {
func (c *Collector) collectClrLocksAndThreads(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, _ time.Duration) error {
var dst []perfDataClrLocksAndThreads
if err := c.perfClrLocksAndThreads.Collect(&dst); err != nil {
return fmt.Errorf("failed to collect .NET CLR LocksAndThreads: %w", err)
@@ -102,49 +103,49 @@ func (c *Collector) collectClrLocksAndThreads(ch chan<- prometheus.Metric, _ tim
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.currentQueueLength,
prometheus.GaugeValue,
float64(process.CurrentQueueLength),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfCurrentLogicalThreads,
prometheus.GaugeValue,
float64(process.NumberofcurrentlogicalThreads),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfCurrentPhysicalThreads,
prometheus.GaugeValue,
float64(process.NumberofcurrentphysicalThreads),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfCurrentRecognizedThreads,
prometheus.GaugeValue,
float64(process.Numberofcurrentrecognizedthreads),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfTotalRecognizedThreads,
prometheus.CounterValue,
float64(process.Numberoftotalrecognizedthreads),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.queueLengthPeak,
prometheus.CounterValue,
float64(process.QueueLengthPeak),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.totalNumberOfContentions,
prometheus.CounterValue,
float64(process.TotalNumberofContentions),
@@ -22,6 +22,7 @@ import (
"strconv"
"time"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -135,7 +136,7 @@ type perfDataClrMemory struct {
ProcessID float64 `perfdata:"Process ID"`
}
func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duration) error {
func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, _ time.Duration) error {
var dst []perfDataClrMemory
if err := c.perfClrMemory.Collect(&dst); err != nil {
return fmt.Errorf("failed to collect .NET CLR Memory: %w", err)
@@ -146,7 +147,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.allocatedBytes,
prometheus.CounterValue,
float64(process.AllocatedBytesPersec),
@@ -154,7 +155,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
strconv.FormatUint(uint64(process.ProcessID), 10),
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.finalizationSurvivors,
prometheus.GaugeValue,
float64(process.FinalizationSurvivors),
@@ -162,7 +163,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
strconv.FormatUint(uint64(process.ProcessID), 10),
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.heapSize,
prometheus.GaugeValue,
float64(process.Gen0heapsize),
@@ -171,7 +172,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
"Gen0",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.promotedBytes,
prometheus.GaugeValue,
float64(process.Gen0PromotedBytesPerSec),
@@ -180,7 +181,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
"Gen0",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.heapSize,
prometheus.GaugeValue,
float64(process.Gen1heapsize),
@@ -189,7 +190,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
"Gen1",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.promotedBytes,
prometheus.GaugeValue,
float64(process.Gen1PromotedBytesPerSec),
@@ -198,7 +199,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
"Gen1",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.heapSize,
prometheus.GaugeValue,
float64(process.Gen2heapsize),
@@ -207,7 +208,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
"Gen2",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.heapSize,
prometheus.GaugeValue,
float64(process.LargeObjectHeapsize),
@@ -216,7 +217,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
"LOH",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberGCHandles,
prometheus.GaugeValue,
float64(process.NumberGCHandles),
@@ -224,7 +225,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
strconv.FormatUint(uint64(process.ProcessID), 10),
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberCollections,
prometheus.CounterValue,
float64(process.NumberGen0Collections),
@@ -233,7 +234,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
"Gen0",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberCollections,
prometheus.CounterValue,
float64(process.NumberGen1Collections),
@@ -242,7 +243,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
"Gen1",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberCollections,
prometheus.CounterValue,
float64(process.NumberGen2Collections),
@@ -251,7 +252,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
"Gen2",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberInducedGC,
prometheus.CounterValue,
float64(process.NumberInducedGC),
@@ -259,7 +260,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
strconv.FormatUint(uint64(process.ProcessID), 10),
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfPinnedObjects,
prometheus.GaugeValue,
float64(process.NumberofPinnedObjects),
@@ -267,7 +268,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
strconv.FormatUint(uint64(process.ProcessID), 10),
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberOfSinkBlocksInUse,
prometheus.GaugeValue,
float64(process.NumberofSinkBlocksinuse),
@@ -275,7 +276,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
strconv.FormatUint(uint64(process.ProcessID), 10),
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberTotalCommittedBytes,
prometheus.GaugeValue,
float64(process.NumberTotalcommittedBytes),
@@ -283,7 +284,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
strconv.FormatUint(uint64(process.ProcessID), 10),
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberTotalReservedBytes,
prometheus.GaugeValue,
float64(process.NumberTotalreservedBytes),
@@ -295,7 +296,7 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, _ time.Duratio
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.timeInGC,
prometheus.GaugeValue,
100*process.PercentTimeinGC/process.PercentTimeinGC_base,
@@ -21,6 +21,7 @@ import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -84,7 +85,7 @@ type perfDataClrRemoting struct {
TotalRemoteCalls float64 `perfdata:"Total Remote Calls"`
}
func (c *Collector) collectClrRemoting(ch chan<- prometheus.Metric, _ time.Duration) error {
func (c *Collector) collectClrRemoting(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, _ time.Duration) error {
var dst []perfDataClrRemoting
if err := c.perfClrRemoting.Collect(&dst); err != nil {
return fmt.Errorf("failed to collect .NET CLR Remoting: %w", err)
@@ -95,42 +96,42 @@ func (c *Collector) collectClrRemoting(ch chan<- prometheus.Metric, _ time.Durat
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.channels,
prometheus.CounterValue,
float64(process.Channels),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.contextBoundClassesLoaded,
prometheus.GaugeValue,
float64(process.ContextBoundClassesLoaded),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.contextBoundObjects,
prometheus.CounterValue,
float64(process.ContextBoundObjectsAllocPersec),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.contextProxies,
prometheus.CounterValue,
float64(process.ContextProxies),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.contexts,
prometheus.GaugeValue,
float64(process.Contexts),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.totalRemoteCalls,
prometheus.CounterValue,
float64(process.TotalRemoteCalls),
@@ -21,6 +21,7 @@ import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
@@ -70,7 +71,7 @@ type perfDataClrSecurity struct {
TotalRuntimeChecks float64 `perfdata:"Total Runtime Checks"`
}
func (c *Collector) collectClrSecurity(ch chan<- prometheus.Metric, _ time.Duration) error {
func (c *Collector) collectClrSecurity(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, _ time.Duration) error {
var dst []perfDataClrSecurity
if err := c.perfClrSecurity.Collect(&dst); err != nil {
return fmt.Errorf("failed to collect .NET CLR Security: %w", err)
@@ -81,28 +82,28 @@ func (c *Collector) collectClrSecurity(ch chan<- prometheus.Metric, _ time.Durat
continue
}
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.numberLinkTimeChecks,
prometheus.CounterValue,
float64(process.NumberLinkTimeChecks),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.timeInRTChecks,
prometheus.GaugeValue,
float64(process.PercentTimeinRTchecks)/c.perfFrequency,
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.stackWalkDepth,
prometheus.GaugeValue,
float64(process.StackWalkDepth),
process.Name,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.totalRuntimeChecks,
prometheus.CounterValue,
float64(process.TotalRuntimeChecks),
@@ -23,6 +23,7 @@ import (
"testing"
"time"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
@@ -57,14 +58,27 @@ type expectedMetric struct {
area string
}
func assertFixtureMetrics(t *testing.T, collect func(chan<- prometheus.Metric, time.Duration) error, expected []expectedMetric, withPID bool) {
func assertFixtureMetrics(t *testing.T, collect func(chan<- prometheus.Metric, *labelcache.Scrape, time.Duration) error, expected []expectedMetric, withPID bool) {
t.Helper()
// A first scrape fills the label cache, so the checked scrape publishes
// series with reused label pairs.
var cache labelcache.Cache
prime := cache.Begin()
primeCh := make(chan prometheus.Metric, 1024)
require.NoError(t, collect(primeCh, prime, time.Second))
prime.Commit()
registry := prometheus.NewRegistry()
var collectErr error
registry.MustRegister(fixturePromCollector{collect: func(ch chan<- prometheus.Metric) { collectErr = collect(ch, time.Second) }})
registry.MustRegister(fixturePromCollector{collect: func(ch chan<- prometheus.Metric) {
scrape := cache.Begin()
collectErr = collect(ch, scrape, time.Second)
scrape.Commit()
}})
families, err := registry.Gather()
require.NoError(t, err)
require.NoError(t, collectErr)
@@ -382,7 +396,7 @@ func TestGCZeroBaseDoesNotPublishInvalidRatio(t *testing.T) {
c.describeClrMemory()
c.perfClrMemory = &fixturePerfCollector[perfDataClrMemory]{rows: []perfDataClrMemory{{Name: "worker", ProcessID: 123, AllocatedBytesPersec: 99}}}
registry := prometheus.NewRegistry()
registry.MustRegister(fixturePromCollector{collect: func(ch chan<- prometheus.Metric) { require.NoError(t, c.collectClrMemory(ch, time.Second)) }})
registry.MustRegister(fixturePromCollector{collect: func(ch chan<- prometheus.Metric) { require.NoError(t, c.collectClrMemory(ch, nil, time.Second)) }})
families, err := registry.Gather()
require.NoError(t, err)
@@ -416,7 +430,7 @@ func TestNoDataIsReturned(t *testing.T) {
c.describeClrExceptions()
c.perfClrExceptions = unavailablePerfCollector[perfDataClrExceptions]{}
ch := make(chan prometheus.Metric, 16)
require.ErrorIs(t, c.collectClrExceptions(ch, time.Second), pdh.ErrNoData)
require.ErrorIs(t, c.collectClrExceptions(ch, nil, time.Second), pdh.ErrNoData)
require.Empty(t, ch)
}
@@ -450,7 +464,7 @@ func BenchmarkClrMemoryMetricPublication(b *testing.B) {
b.ResetTimer()
for b.Loop() {
if err := c.collectClrMemory(ch, time.Second); err != nil {
if err := c.collectClrMemory(ch, nil, time.Second); err != nil {
b.Fatal(err)
}
@@ -467,7 +481,7 @@ func TestCollectRetainsSuccessfulChildMetrics(t *testing.T) {
c.perfClrExceptions = &fixturePerfCollector[perfDataClrExceptions]{rows: []perfDataClrExceptions{{Name: "worker", NumberofExcepsThrown: 37}}}
failure := errors.New("provider failed")
c.perfClrInterop = &fixturePerfCollector[perfDataClrInterop]{err: failure}
c.collectorFns = []func(chan<- prometheus.Metric, time.Duration) error{c.collectClrExceptions, c.collectClrInterop}
c.collectorFns = []func(chan<- prometheus.Metric, *labelcache.Scrape, time.Duration) error{c.collectClrExceptions, c.collectClrInterop}
registry := prometheus.NewRegistry()
var collectErr error
+33 -24
View File
@@ -29,6 +29,7 @@ import (
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
@@ -74,6 +75,10 @@ type Collector struct {
snapshot snapshotBuffer
processes []processSnapshot
// labels keeps the label pairs of the series of the last scrape. Process
// values change on every scrape, but their labels stay the same while
// the process runs.
labels labelcache.Cache
// infoCache holds the windows_process_info values of the processes of the last scrape, keyed by PID.
infoCache map[uint32]processInfo
@@ -176,6 +181,7 @@ func (c *Collector) Close() error {
c.snapshot = snapshotBuffer{}
c.processes = nil
c.infoCache = nil
c.labels.Reset()
// The session belongs to the caller of Build.
c.miSession = nil
@@ -374,13 +380,16 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric, maxScrapeDuration time.
infos := c.resolveProcessInfo(processes)
scrape := c.labels.Begin()
defer scrape.Commit()
for i, process := range processes {
name := process.name
if appPoolName := appPools[process.pid]; appPoolName != "" {
name = name + "_" + appPoolName
}
c.collectProcess(ch, name, process, &infos[i])
c.collectProcess(ch, scrape, name, process, &infos[i])
}
return err
@@ -463,10 +472,10 @@ func resolveAppPools(
return appPools, nil
}
func (c *Collector) collectProcess(ch chan<- prometheus.Metric, name string, process *processSnapshot, info *processInfo) {
func (c *Collector) collectProcess(ch chan<- prometheus.Metric, scrape *labelcache.Scrape, name string, process *processSnapshot, info *processInfo) {
pid := strconv.FormatUint(uint64(process.pid), 10)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.info,
prometheus.GaugeValue,
1.0,
@@ -474,147 +483,147 @@ func (c *Collector) collectProcess(ch chan<- prometheus.Metric, name string, pro
)
// Perflib reports whole seconds for the Elapsed Time counter of the Process counter set.
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.startTime,
prometheus.GaugeValue,
float64((process.createTime-windowsEpoch)/ticksPerSecond),
name, pid,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.handleCount,
prometheus.GaugeValue,
float64(process.handleCount),
name, pid,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.cpuTimeTotal,
prometheus.CounterValue,
float64(process.kernelTime)*secondsPerTick,
name, pid, "privileged",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.cpuTimeTotal,
prometheus.CounterValue,
float64(process.userTime)*secondsPerTick,
name, pid, "user",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
float64(process.otherTransferCount),
name, pid, "other",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
float64(process.otherOperationCount),
name, pid, "other",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
float64(process.readTransferCount),
name, pid, "read",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
float64(process.readOperationCount),
name, pid, "read",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
float64(process.writeTransferCount),
name, pid, "write",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
float64(process.writeOperationCount),
name, pid, "write",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.pageFaultsTotal,
prometheus.CounterValue,
float64(process.pageFaultCount),
name, pid,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.pageFileBytes,
prometheus.GaugeValue,
float64(process.pageFileUsage),
name, pid,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.poolBytes,
prometheus.GaugeValue,
float64(process.nonPagedPoolUsage),
name, pid, "nonpaged",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.poolBytes,
prometheus.GaugeValue,
float64(process.pagedPoolUsage),
name, pid, "paged",
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.priorityBase,
prometheus.GaugeValue,
float64(process.basePriority),
name, pid,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.privateBytes,
prometheus.GaugeValue,
float64(process.privatePageCount),
name, pid,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.threadCount,
prometheus.GaugeValue,
float64(process.threadCount),
name, pid,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.virtualBytes,
prometheus.GaugeValue,
float64(process.virtualSize),
name, pid,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.workingSetPrivate,
prometheus.GaugeValue,
float64(process.workingSetPrivate),
name, pid,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.workingSetPeak,
prometheus.GaugeValue,
float64(process.workingSetPeak),
name, pid,
)
ch <- prometheus.MustNewConstMetric(
ch <- scrape.MustNewConstMetric(
c.workingSet,
prometheus.GaugeValue,
float64(process.workingSetSize),
+212
View File
@@ -0,0 +1,212 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package labelcache reuses the label pairs of const metrics between scrapes.
//
// prometheus.NewConstMetric builds and sorts the label pairs of a series on
// every call. For series whose value changes on every scrape, such as process
// counters, internal/metriccache can't reuse the metric, but the labels stay
// the same as long as the series exists. A Scrape hands out metrics that share
// the label pairs built for the same series in the previous scrape. Series that
// aren't reported in a scrape are dropped when it commits.
package labelcache
import (
"fmt"
"sync"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
)
// maxLabels is the largest number of label values a cached series can have.
// Metrics with more labels are created without the cache.
const maxLabels = 6
// key identifies a series. It is a fixed-size array, so building and looking up
// a key doesn't allocate.
type key struct {
desc *prometheus.Desc
n int
values [maxLabels]string
}
// Cache holds the label pairs of the last committed scrape. The zero value is
// ready to use.
type Cache struct {
mu sync.Mutex
entries map[key][]*dto.LabelPair
// resets counts Reset calls, so that a scrape begun before a Reset doesn't
// commit afterwards.
resets uint64
// active counts the scrapes between Begin and Commit. spare is a replaced
// generation that no scrape reads anymore; the next scrape reuses it
// instead of allocating a new map.
active int
spare map[key][]*dto.LabelPair
}
// Scrape creates the metrics of one scrape.
type Scrape struct {
cache *Cache
resets uint64
// prev is the last committed generation. It is never modified, so it is
// read without holding mu.
prev map[key][]*dto.LabelPair
mu sync.Mutex
// next collects the label pairs of this scrape. Commit hands it to the
// cache and sets it to nil.
next map[key][]*dto.LabelPair
}
// Begin starts a scrape. Call Commit when it is done.
func (c *Cache) Begin() *Scrape {
c.mu.Lock()
prev, resets, next := c.entries, c.resets, c.spare
c.spare = nil
c.active++
c.mu.Unlock()
if next == nil {
next = make(map[key][]*dto.LabelPair, len(prev))
}
return &Scrape{
cache: c,
resets: resets,
prev: prev,
next: next,
}
}
// Reset drops all cached label pairs, for example when the collector closes.
func (c *Cache) Reset() {
c.mu.Lock()
c.entries = nil
c.spare = nil
c.resets++
c.mu.Unlock()
}
// Commit makes the series of this scrape the base of the next one. Series of
// the previous scrape that this scrape didn't report are dropped.
func (s *Scrape) Commit() {
if s == nil {
return
}
s.mu.Lock()
next := s.next
s.next = nil
s.mu.Unlock()
if next == nil {
return
}
s.cache.mu.Lock()
defer s.cache.mu.Unlock()
s.cache.active--
if s.cache.resets != s.resets {
return
}
replaced := s.cache.entries
s.cache.entries = next
// Other scrapes may still read the replaced generation.
if s.cache.active == 0 && replaced != nil {
clear(replaced)
s.cache.spare = replaced
}
}
// MustNewConstMetric is prometheus.MustNewConstMetric, but it reuses the label
// pairs of the series from the previous scrape. A nil Scrape creates the metric
// without the cache.
//
//nolint:ireturn // Const metrics have no exported type.
func (s *Scrape) MustNewConstMetric(desc *prometheus.Desc, valueType prometheus.ValueType, value float64, labelValues ...string) prometheus.Metric {
if s == nil || len(labelValues) > maxLabels {
return prometheus.MustNewConstMetric(desc, valueType, value, append([]string(nil), labelValues...)...)
}
k := key{desc: desc, n: len(labelValues)}
copy(k.values[:], labelValues)
labels, ok := s.prev[k]
s.mu.Lock()
if !ok {
labels, ok = s.next[k]
}
if ok && s.next != nil {
s.next[k] = labels
}
s.mu.Unlock()
if ok {
return &constMetric{desc: desc, valueType: valueType, value: value, labels: labels}
}
// A new series: prometheus validates the label values and builds the
// pairs, which the following scrapes share.
metric := prometheus.MustNewConstMetric(desc, valueType, value, append([]string(nil), labelValues...)...)
var out dto.Metric
if err := metric.Write(&out); err == nil {
s.mu.Lock()
if s.next != nil {
s.next[k] = out.GetLabel()
}
s.mu.Unlock()
}
return metric
}
// constMetric is a const metric with shared label pairs. Label pairs are
// immutable once written, like those of prometheus.NewConstMetric.
type constMetric struct {
desc *prometheus.Desc
labels []*dto.LabelPair
value float64
valueType prometheus.ValueType
}
func (m *constMetric) Desc() *prometheus.Desc {
return m.desc
}
func (m *constMetric) Write(out *dto.Metric) error {
out.Label = m.labels
switch m.valueType {
case prometheus.CounterValue:
out.Counter = &dto.Counter{Value: &m.value}
case prometheus.GaugeValue:
out.Gauge = &dto.Gauge{Value: &m.value}
case prometheus.UntypedValue:
out.Untyped = &dto.Untyped{Value: &m.value}
default:
return fmt.Errorf("encountered unknown type %v", m.valueType)
}
return nil
}
+214
View File
@@ -0,0 +1,214 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package labelcache_test
import (
"strconv"
"sync"
"testing"
"github.com/prometheus-community/windows_exporter/internal/labelcache"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
)
//nolint:gochecknoglobals
var (
counterDesc = prometheus.NewDesc("test_cpu_seconds_total", "test", []string{"process", "process_id", "mode"}, prometheus.Labels{"const": "x"})
gaugeDesc = prometheus.NewDesc("test_handles", "test", []string{"process", "process_id"}, nil)
untypedDesc = prometheus.NewDesc("test_untyped", "test", nil, nil)
wideDesc = prometheus.NewDesc("test_info", "test", []string{"a", "b", "c", "d", "e", "f", "g"}, nil)
)
func write(t *testing.T, metric prometheus.Metric) *dto.Metric {
t.Helper()
var out dto.Metric
require.NoError(t, metric.Write(&out))
return &out
}
// Cached metrics must write exactly what prometheus.MustNewConstMetric writes,
// in the first scrape (new series) and the following ones (shared labels).
func TestMustNewConstMetric(t *testing.T) {
t.Parallel()
var cache labelcache.Cache
cases := []struct {
desc *prometheus.Desc
valueType prometheus.ValueType
values []string
}{
{counterDesc, prometheus.CounterValue, []string{"svchost", "1234", "user"}},
{counterDesc, prometheus.CounterValue, []string{"svchost", "1234", "privileged"}},
{gaugeDesc, prometheus.GaugeValue, []string{"svchost", "1234"}},
{untypedDesc, prometheus.UntypedValue, nil},
{wideDesc, prometheus.GaugeValue, []string{"1", "2", "3", "4", "5", "6", "7"}},
}
for scrapeNumber := range 3 {
scrape := cache.Begin()
for i, tc := range cases {
value := float64(scrapeNumber*10 + i)
got := scrape.MustNewConstMetric(tc.desc, tc.valueType, value, tc.values...)
want := prometheus.MustNewConstMetric(tc.desc, tc.valueType, value, tc.values...)
require.Equal(t, want.Desc(), got.Desc())
require.True(t, proto.Equal(write(t, want), write(t, got)), "scrape %d, case %d:\nwant %v\ngot %v", scrapeNumber, i, write(t, want), write(t, got))
}
scrape.Commit()
}
}
// From the second scrape on, a series reuses the label pairs of the previous
// one; series that a scrape didn't report get new pairs.
func TestLabelReuse(t *testing.T) {
t.Parallel()
var cache labelcache.Cache
labelsOf := func(scrape *labelcache.Scrape, pid string) []*dto.LabelPair {
return write(t, scrape.MustNewConstMetric(gaugeDesc, prometheus.GaugeValue, 1, "p", pid)).GetLabel()
}
scrape := cache.Begin()
first := labelsOf(scrape, "1")
labelsOf(scrape, "2")
scrape.Commit()
scrape = cache.Begin()
require.Same(t, first[0], labelsOf(scrape, "1")[0], "label pairs reused")
scrape.Commit()
// Process 2 wasn't reported in the second scrape, so its pairs were dropped.
scrape = cache.Begin()
second := labelsOf(scrape, "2")
require.Equal(t, "2", second[1].GetValue())
scrape.Commit()
scrape = cache.Begin()
require.Same(t, second[0], labelsOf(scrape, "2")[0])
scrape.Commit()
cache.Reset()
scrape = cache.Begin()
require.NotSame(t, second[0], labelsOf(scrape, "2")[0], "reset drops the cache")
scrape.Commit()
}
// A scrape begun before Reset must not restore its generation afterwards.
func TestResetDuringScrape(t *testing.T) {
t.Parallel()
var cache labelcache.Cache
scrape := cache.Begin()
pairs := write(t, scrape.MustNewConstMetric(gaugeDesc, prometheus.GaugeValue, 1, "p", "1")).GetLabel()
cache.Reset()
scrape.Commit()
scrape = cache.Begin()
require.NotSame(t, pairs[0], write(t, scrape.MustNewConstMetric(gaugeDesc, prometheus.GaugeValue, 1, "p", "1")).GetLabel()[0])
scrape.Commit()
scrape.Commit()
}
func TestInvalidLabelValues(t *testing.T) {
t.Parallel()
var cache labelcache.Cache
scrape := cache.Begin()
require.Panics(t, func() { scrape.MustNewConstMetric(gaugeDesc, prometheus.GaugeValue, 1, "only one") })
require.Panics(t, func() { scrape.MustNewConstMetric(gaugeDesc, prometheus.GaugeValue, 1, "p", "\xff") })
}
func TestConcurrentScrapes(t *testing.T) {
t.Parallel()
var (
cache labelcache.Cache
wg sync.WaitGroup
)
for range 8 {
wg.Go(func() {
for range 20 {
scrape := cache.Begin()
var inner sync.WaitGroup
for p := range 4 {
inner.Go(func() {
for pid := range 50 {
m := scrape.MustNewConstMetric(counterDesc, prometheus.CounterValue, 1, "p"+strconv.Itoa(p), strconv.Itoa(pid), "user")
if err := m.Write(&dto.Metric{}); err != nil {
t.Error(err)
}
}
})
}
inner.Wait()
scrape.Commit()
}
})
}
wg.Wait()
}
func BenchmarkMustNewConstMetric(b *testing.B) {
pids := make([]string, 500)
for i := range pids {
pids[i] = strconv.Itoa(1000 + i)
}
b.Run("prometheus", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
for _, pid := range pids {
_ = prometheus.MustNewConstMetric(counterDesc, prometheus.CounterValue, 1, "svchost", pid, "user")
}
}
})
b.Run("labelcache", func(b *testing.B) {
var cache labelcache.Cache
b.ReportAllocs()
for b.Loop() {
scrape := cache.Begin()
for _, pid := range pids {
_ = scrape.MustNewConstMetric(counterDesc, prometheus.CounterValue, 1, "svchost", pid, "user")
}
scrape.Commit()
}
})
}