mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-26 14:46:35 +00:00
cpu: Fetch performance counter via PDH.dll via feature toggle. (off by default) (#1627)
This commit is contained in:
@@ -217,6 +217,10 @@ func run() int {
|
|||||||
|
|
||||||
logger.Info("Enabled collectors: " + strings.Join(enabledCollectorList, ", "))
|
logger.Info("Enabled collectors: " + strings.Join(enabledCollectorList, ", "))
|
||||||
|
|
||||||
|
if utils.PDHEnabled() {
|
||||||
|
logger.Info("Using performance data helper from PHD.dll for performance counter collection. This is in experimental state.")
|
||||||
|
}
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.Handle("GET /health", httphandler.NewHealthHandler())
|
mux.Handle("GET /health", httphandler.NewHealthHandler())
|
||||||
mux.Handle("GET /version", httphandler.NewVersionHandler())
|
mux.Handle("GET /version", httphandler.NewVersionHandler())
|
||||||
|
|||||||
28
pkg/collector/cpu/const.go
Normal file
28
pkg/collector/cpu/const.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package cpu
|
||||||
|
|
||||||
|
// Processor performance counters.
|
||||||
|
const (
|
||||||
|
C1TimeSeconds = "% C1 Time"
|
||||||
|
C2TimeSeconds = "% C2 Time"
|
||||||
|
C3TimeSeconds = "% C3 Time"
|
||||||
|
C1TransitionsTotal = "C1 Transitions/sec"
|
||||||
|
C2TransitionsTotal = "C2 Transitions/sec"
|
||||||
|
C3TransitionsTotal = "C3 Transitions/sec"
|
||||||
|
ClockInterruptsTotal = "Clock Interrupts/sec"
|
||||||
|
DPCsQueuedTotal = "DPCs Queued/sec"
|
||||||
|
DPCTimeSeconds = "% DPC Time"
|
||||||
|
IdleBreakEventsTotal = "Idle Break Events/sec"
|
||||||
|
IdleTimeSeconds = "% Idle Time"
|
||||||
|
InterruptsTotal = "Interrupts/sec"
|
||||||
|
InterruptTimeSeconds = "% Interrupt Time"
|
||||||
|
ParkingStatus = "Parking Status"
|
||||||
|
PerformanceLimitPercent = "% Performance Limit"
|
||||||
|
PriorityTimeSeconds = "% Priority Time"
|
||||||
|
PrivilegedTimeSeconds = "% Privileged Time"
|
||||||
|
PrivilegedUtilitySeconds = "% Privileged Utility"
|
||||||
|
ProcessorFrequencyMHz = "Processor Frequency"
|
||||||
|
ProcessorPerformance = "% Processor Performance"
|
||||||
|
ProcessorTimeSeconds = "% Processor Time"
|
||||||
|
ProcessorUtilityRate = "% Processor Utility"
|
||||||
|
UserTimeSeconds = "% User Time"
|
||||||
|
)
|
||||||
@@ -3,12 +3,15 @@
|
|||||||
package cpu
|
package cpu
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/pkg/perfdata"
|
||||||
"github.com/prometheus-community/windows_exporter/pkg/perflib"
|
"github.com/prometheus-community/windows_exporter/pkg/perflib"
|
||||||
"github.com/prometheus-community/windows_exporter/pkg/types"
|
"github.com/prometheus-community/windows_exporter/pkg/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/pkg/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
"github.com/yusufpapurcu/wmi"
|
||||||
)
|
)
|
||||||
@@ -22,6 +25,8 @@ var ConfigDefaults = Config{}
|
|||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
|
|
||||||
|
perfDataCollector *perfdata.Collector
|
||||||
|
|
||||||
logicalProcessors *prometheus.Desc
|
logicalProcessors *prometheus.Desc
|
||||||
cStateSecondsTotal *prometheus.Desc
|
cStateSecondsTotal *prometheus.Desc
|
||||||
timeTotal *prometheus.Desc
|
timeTotal *prometheus.Desc
|
||||||
@@ -59,6 +64,10 @@ func (c *Collector) GetName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
|
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
|
||||||
|
if utils.PDHEnabled() {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
return []string{"Processor Information"}, nil
|
return []string{"Processor Information"}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +76,41 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||||
|
if utils.PDHEnabled() {
|
||||||
|
counters := []string{
|
||||||
|
C1TimeSeconds,
|
||||||
|
C2TimeSeconds,
|
||||||
|
C3TimeSeconds,
|
||||||
|
C1TransitionsTotal,
|
||||||
|
C2TransitionsTotal,
|
||||||
|
C3TransitionsTotal,
|
||||||
|
ClockInterruptsTotal,
|
||||||
|
DPCsQueuedTotal,
|
||||||
|
DPCTimeSeconds,
|
||||||
|
IdleBreakEventsTotal,
|
||||||
|
IdleTimeSeconds,
|
||||||
|
InterruptsTotal,
|
||||||
|
InterruptTimeSeconds,
|
||||||
|
ParkingStatus,
|
||||||
|
PerformanceLimitPercent,
|
||||||
|
PriorityTimeSeconds,
|
||||||
|
PrivilegedTimeSeconds,
|
||||||
|
PrivilegedUtilitySeconds,
|
||||||
|
ProcessorFrequencyMHz,
|
||||||
|
ProcessorPerformance,
|
||||||
|
ProcessorTimeSeconds,
|
||||||
|
ProcessorUtilityRate,
|
||||||
|
UserTimeSeconds,
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
c.perfDataCollector, err = perfdata.NewCollector("Processor Information", []string{"*"}, counters)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create Processor Information collector: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.logicalProcessors = prometheus.NewDesc(
|
c.logicalProcessors = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "logical_processor"),
|
prometheus.BuildFQName(types.Namespace, Name, "logical_processor"),
|
||||||
"Total number of logical processors",
|
"Total number of logical processors",
|
||||||
@@ -184,7 +228,11 @@ func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
|||||||
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||||
logger = logger.With(slog.String("collector", Name))
|
logger = logger.With(slog.String("collector", Name))
|
||||||
|
|
||||||
return c.CollectFull(ctx, logger, ch)
|
if utils.PDHEnabled() {
|
||||||
|
return c.collectPDH(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.collectFull(ctx, logger, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
type perflibProcessorInformation struct {
|
type perflibProcessorInformation struct {
|
||||||
@@ -216,8 +264,7 @@ type perflibProcessorInformation struct {
|
|||||||
UserTimeSeconds float64 `perflib:"% User Time"`
|
UserTimeSeconds float64 `perflib:"% User Time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) CollectFull(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectFull(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||||
logger = logger.With(slog.String("collector", Name))
|
|
||||||
data := make([]perflibProcessorInformation, 0)
|
data := make([]perflibProcessorInformation, 0)
|
||||||
|
|
||||||
err := perflib.UnmarshalObject(ctx.PerfObjects["Processor Information"], &data, logger)
|
err := perflib.UnmarshalObject(ctx.PerfObjects["Processor Information"], &data, logger)
|
||||||
@@ -364,3 +411,143 @@ func (c *Collector) CollectFull(ctx *types.ScrapeContext, logger *slog.Logger, c
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Collector) collectPDH(ch chan<- prometheus.Metric) error {
|
||||||
|
data, err := c.perfDataCollector.Collect()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to collect Processor Information metrics: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var coreCount float64
|
||||||
|
|
||||||
|
for core, coreData := range data {
|
||||||
|
coreCount++
|
||||||
|
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.cStateSecondsTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[C1TimeSeconds].FirstValue,
|
||||||
|
core, "c1",
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.cStateSecondsTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[C2TimeSeconds].FirstValue,
|
||||||
|
core, "c2",
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.cStateSecondsTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[C3TimeSeconds].FirstValue,
|
||||||
|
core, "c3",
|
||||||
|
)
|
||||||
|
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.timeTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[IdleTimeSeconds].FirstValue,
|
||||||
|
core, "idle",
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.timeTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[InterruptTimeSeconds].FirstValue,
|
||||||
|
core, "interrupt",
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.timeTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[DPCTimeSeconds].FirstValue,
|
||||||
|
core, "dpc",
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.timeTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[PrivilegedTimeSeconds].FirstValue,
|
||||||
|
core, "privileged",
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.timeTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[UserTimeSeconds].FirstValue,
|
||||||
|
core, "user",
|
||||||
|
)
|
||||||
|
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.interruptsTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[InterruptsTotal].FirstValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.dpcsTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[DPCsQueuedTotal].FirstValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.clockInterruptsTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[ClockInterruptsTotal].FirstValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.idleBreakEventsTotal,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[IdleBreakEventsTotal].FirstValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.parkingStatus,
|
||||||
|
prometheus.GaugeValue,
|
||||||
|
coreData[ParkingStatus].FirstValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.processorFrequencyMHz,
|
||||||
|
prometheus.GaugeValue,
|
||||||
|
coreData[ProcessorFrequencyMHz].FirstValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.processorPerformance,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[ProcessorPerformance].FirstValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.processorMPerf,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[ProcessorPerformance].SecondValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.processorRTC,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[ProcessorUtilityRate].SecondValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.processorUtility,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[ProcessorUtilityRate].FirstValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.processorPrivilegedUtility,
|
||||||
|
prometheus.CounterValue,
|
||||||
|
coreData[PrivilegedUtilitySeconds].FirstValue,
|
||||||
|
core,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.logicalProcessors,
|
||||||
|
prometheus.GaugeValue,
|
||||||
|
coreCount,
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/prometheus-community/windows_exporter/pkg/types"
|
"github.com/prometheus-community/windows_exporter/pkg/types"
|
||||||
@@ -26,3 +27,11 @@ func ExpandEnabledCollectors(enabled string) []string {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PDHEnabled() bool {
|
||||||
|
if v, ok := os.LookupEnv("WINDOWS_EXPORTER_PERF_COUNTERS_ENGINE"); ok && v == "pdh" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user