Initial cpu collector implementation

This commit is contained in:
Calle Pettersson 2016-09-17 17:11:35 +02:00
parent c98a0c16b2
commit 92b762f6a1
4 changed files with 215 additions and 5 deletions

211
collector/cpu.go Normal file
View File

@ -0,0 +1,211 @@
// returns data points from Win32_PerfRawData_PerfOS_Processor
// https://msdn.microsoft.com/en-us/library/aa394317(v=vs.90).aspx - Win32_PerfRawData_PerfOS_Processor class
package collector
import (
"log"
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
Factories["cpu"] = NewCPUCollector
}
// A CPUCollector is a Prometheus collector for WMI Win32_PerfRawData_PerfOS_Processor metrics
type CPUCollector struct {
CStateSecondsTotal *prometheus.Desc
TimeTotal *prometheus.Desc
InterruptsTotal *prometheus.Desc
DPCsTotal *prometheus.Desc
}
func NewCPUCollector() (Collector, error) {
const subsystem = "cpu"
return &CPUCollector{
CStateSecondsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cstate_seconds_total"),
"Time spent in low-power idle state",
[]string{"core", "state"},
nil,
),
TimeTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "time_total"),
"Time that processor spent in different modes (idle, user, system, ...)",
[]string{"core", "mode"},
nil,
),
InterruptsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "interrupts_total"),
"Total number of received and serviced hardware interrupts",
[]string{"core"},
nil,
),
DPCsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "dpcs_total"),
"Total number of received and serviced deferred procedure calls (DPCs)",
[]string{"core"},
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *CPUCollector) Collect(ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Println("[ERROR] failed collecting os metrics:", desc, err)
return err
}
return nil
}
type Win32_PerfRawData_PerfOS_Processor struct {
Name string
C1TransitionsPersec uint64
C2TransitionsPersec uint64
C3TransitionsPersec uint64
DPCRate uint32
DPCsQueuedPersec uint32
InterruptsPersec uint32
PercentC1Time uint64
PercentC2Time uint64
PercentC3Time uint64
PercentDPCTime uint64
PercentIdleTime uint64
PercentInterruptTime uint64
PercentPrivilegedTime uint64
PercentProcessorTime uint64
PercentUserTime uint64
}
/* NOTE: This is an alternative class, but it is not as widely available. Decide which to use
type Win32_PerfRawData_Counters_ProcessorInformation struct {
Name string
AverageIdleTime uint64
C1TransitionsPersec uint64
C2TransitionsPersec uint64
C3TransitionsPersec uint64
ClockInterruptsPersec uint64
DPCRate uint64
DPCsQueuedPersec uint64
IdleBreakEventsPersec uint64
InterruptsPersec uint64
ParkingStatus uint64
PercentC1Time uint64
PercentC2Time uint64
PercentC3Time uint64
PercentDPCTime uint64
PercentIdleTime uint64
PercentInterruptTime uint64
PercentofMaximumFrequency uint64
PercentPerformanceLimit uint64
PercentPriorityTime uint64
PercentPrivilegedTime uint64
PercentPrivilegedUtility uint64
PercentProcessorPerformance uint64
PercentProcessorTime uint64
PercentProcessorUtility uint64
PercentUserTime uint64
PerformanceLimitFlags uint64
ProcessorFrequency uint64
ProcessorStateFlags uint64
}*/
func (c *CPUCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_PerfOS_Processor
q := wmi.CreateQuery(&dst, "")
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
for _, data := range dst {
if strings.Contains(data.Name, "_Total") {
continue
}
core := data.Name
// These are only available from Win32_PerfRawData_Counters_ProcessorInformation, which is only available from Win2008R2+
/*ch <- prometheus.MustNewConstMetric(
c.ProcessorFrequency,
prometheus.GaugeValue,
float64(data.ProcessorFrequency),
socket, core,
)
ch <- prometheus.MustNewConstMetric(
c.MaximumFrequency,
prometheus.GaugeValue,
float64(data.PercentofMaximumFrequency)/100*float64(data.ProcessorFrequency),
socket, core,
)*/
ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal,
prometheus.GaugeValue,
float64(data.PercentC1Time)*ticksToSecondsScaleFactor,
core, "c1",
)
ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal,
prometheus.GaugeValue,
float64(data.PercentC2Time)*ticksToSecondsScaleFactor,
core, "c2",
)
ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal,
prometheus.GaugeValue,
float64(data.PercentC3Time)*ticksToSecondsScaleFactor,
core, "c3",
)
ch <- prometheus.MustNewConstMetric(
c.TimeTotal,
prometheus.GaugeValue,
float64(data.PercentIdleTime)*ticksToSecondsScaleFactor,
core, "idle",
)
ch <- prometheus.MustNewConstMetric(
c.TimeTotal,
prometheus.GaugeValue,
float64(data.PercentInterruptTime)*ticksToSecondsScaleFactor,
core, "interrupt",
)
ch <- prometheus.MustNewConstMetric(
c.TimeTotal,
prometheus.GaugeValue,
float64(data.PercentDPCTime)*ticksToSecondsScaleFactor,
core, "dpc",
)
ch <- prometheus.MustNewConstMetric(
c.TimeTotal,
prometheus.GaugeValue,
float64(data.PercentPrivilegedTime)*ticksToSecondsScaleFactor,
core, "privileged",
)
ch <- prometheus.MustNewConstMetric(
c.TimeTotal,
prometheus.GaugeValue,
float64(data.PercentUserTime)*ticksToSecondsScaleFactor,
core, "user",
)
ch <- prometheus.MustNewConstMetric(
c.InterruptsTotal,
prometheus.CounterValue,
float64(data.InterruptsPersec),
core,
)
ch <- prometheus.MustNewConstMetric(
c.DPCsTotal,
prometheus.CounterValue,
float64(data.DPCsQueuedPersec),
core,
)
}
return nil, nil
}

View File

@ -18,10 +18,6 @@ func init() {
Factories["logical_disk"] = NewLogicalDiskCollector
}
const (
ticksToSecondsScaleFactor = 1 / 1e7
)
var (
volumeWhitelist = flag.String("collector.logical_disk.volume-whitelist", ".+", "Regexp of volumes to whitelist. Volume name must both match whitelist and not match blacklist to be included.")
volumeBlacklist = flag.String("collector.logical_disk.volume-blacklist", "", "Regexp of volumes to blacklist. Volume name must both match whitelist and not match blacklist to be included.")

View File

@ -5,6 +5,9 @@ import "github.com/prometheus/client_golang/prometheus"
// ...
const (
Namespace = "wmi"
// Conversion factors
ticksToSecondsScaleFactor = 1 / 1e7
)
// Factories ...

View File

@ -24,7 +24,7 @@ type WmiCollector struct {
}
const (
defaultCollectors = "logical_disk,os"
defaultCollectors = "cpu,logical_disk,os"
serviceName = "wmi_exporter"
)