Merge pull request #461 from martinlindhe/specific-perflib-objects

Only query the perflib objects we need
This commit is contained in:
Calle Pettersson
2020-03-01 12:55:03 +01:00
committed by GitHub
33 changed files with 97 additions and 57 deletions

View File

@@ -11,7 +11,7 @@ import (
) )
func init() { func init() {
Factories["ad"] = NewADCollector registerCollector("ad", NewADCollector)
} }
// A ADCollector is a Prometheus collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics // A ADCollector is a Prometheus collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics

View File

@@ -7,7 +7,7 @@ import (
) )
func init() { func init() {
Factories["adfs"] = newADFSCollector registerCollector("adfs", newADFSCollector)
} }
type adfsCollector struct { type adfsCollector struct {

View File

@@ -2,6 +2,7 @@ package collector
import ( import (
"strconv" "strconv"
"strings"
"github.com/leoluk/perflib_exporter/perflib" "github.com/leoluk/perflib_exporter/perflib"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
@@ -47,8 +48,41 @@ func getWindowsVersion() float64 {
return currentv_flt return currentv_flt
} }
// Factories ... type collectorBuilder func() (Collector, error)
var Factories = make(map[string]func() (Collector, error))
var (
builders = make(map[string]collectorBuilder)
perfCounterDependencies = make(map[string]string)
)
func registerCollector(name string, builder collectorBuilder, perfCounterNames ...string) {
builders[name] = builder
perfIndicies := make([]string, 0, len(perfCounterNames))
for _, cn := range perfCounterNames {
perfIndicies = append(perfIndicies, MapCounterToIndex(cn))
}
perfCounterDependencies[name] = strings.Join(perfIndicies, " ")
}
func Available() []string {
cs := make([]string, 0, len(builders))
for c := range builders {
cs = append(cs, c)
}
return cs
}
func Build(collector string) (Collector, error) {
return builders[collector]()
}
func getPerfQuery(collectors []string) string {
parts := make([]string, 0, len(collectors))
for _, c := range collectors {
if p := perfCounterDependencies[c]; p != "" {
parts = append(parts, p)
}
}
return strings.Join(parts, " ")
}
// Collector is the interface a collector has to implement. // Collector is the interface a collector has to implement.
type Collector interface { type Collector interface {
@@ -61,8 +95,9 @@ type ScrapeContext struct {
} }
// PrepareScrapeContext creates a ScrapeContext to be used during a single scrape // PrepareScrapeContext creates a ScrapeContext to be used during a single scrape
func PrepareScrapeContext() (*ScrapeContext, error) { func PrepareScrapeContext(collectors []string) (*ScrapeContext, error) {
objs, err := getPerflibSnapshot() q := getPerfQuery(collectors) // TODO: Memoize
objs, err := getPerflibSnapshot(q)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -9,7 +9,7 @@ import (
) )
func init() { func init() {
Factories["container"] = NewContainerMetricsCollector registerCollector("container", NewContainerMetricsCollector)
} }
// A ContainerMetricsCollector is a Prometheus collector for containers metrics // A ContainerMetricsCollector is a Prometheus collector for containers metrics

View File

@@ -9,7 +9,14 @@ import (
) )
func init() { func init() {
Factories["cpu"] = newCPUCollector var deps string
// See below for 6.05 magic value
if getWindowsVersion() > 6.05 {
deps = "Processor Information"
} else {
deps = "Processor"
}
registerCollector("cpu", newCPUCollector, deps)
} }
type cpuCollectorBasic struct { type cpuCollectorBasic struct {
@@ -38,7 +45,7 @@ func newCPUCollector() (Collector, error) {
version := getWindowsVersion() version := getWindowsVersion()
// For Windows 2008 (version 6.0) or earlier we only have the "Processor" // For Windows 2008 (version 6.0) or earlier we only have the "Processor"
// class. As of Windows 2008 R2 (version 6.1) the more detailed // class. As of Windows 2008 R2 (version 6.1) the more detailed
// "ProcessorInformation" set is available (although some of the counters // "Processor Information" set is available (although some of the counters
// are added in later versions, so we aren't guaranteed to get all of // are added in later versions, so we aren't guaranteed to get all of
// them). // them).
// Value 6.05 was selected to split between Windows versions. // Value 6.05 was selected to split between Windows versions.

View File

@@ -11,7 +11,7 @@ import (
) )
func init() { func init() {
Factories["cs"] = NewCSCollector registerCollector("cs", NewCSCollector)
} }
// A CSCollector is a Prometheus collector for WMI metrics // A CSCollector is a Prometheus collector for WMI metrics

View File

@@ -11,7 +11,7 @@ import (
) )
func init() { func init() {
Factories["dns"] = NewDNSCollector registerCollector("dns", NewDNSCollector)
} }
// A DNSCollector is a Prometheus collector for WMI Win32_PerfRawData_DNS_DNS metrics // A DNSCollector is a Prometheus collector for WMI Win32_PerfRawData_DNS_DNS metrics

View File

@@ -11,7 +11,7 @@ import (
) )
func init() { func init() {
Factories["hyperv"] = NewHyperVCollector registerCollector("hyperv", NewHyperVCollector)
} }
// HyperVCollector is a Prometheus collector for hyper-v // HyperVCollector is a Prometheus collector for hyper-v

View File

@@ -16,7 +16,7 @@ import (
) )
func init() { func init() {
Factories["iis"] = NewIISCollector registerCollector("iis", NewIISCollector)
} }
type simple_version struct { type simple_version struct {

View File

@@ -12,7 +12,7 @@ import (
) )
func init() { func init() {
Factories["logical_disk"] = NewLogicalDiskCollector registerCollector("logical_disk", NewLogicalDiskCollector, "LogicalDisk")
} }
var ( var (

View File

@@ -11,7 +11,7 @@ import (
) )
func init() { func init() {
Factories["logon"] = NewLogonCollector registerCollector("logon", NewLogonCollector)
} }
// A LogonCollector is a Prometheus collector for WMI metrics // A LogonCollector is a Prometheus collector for WMI metrics

View File

@@ -11,7 +11,7 @@ import (
) )
func init() { func init() {
Factories["memory"] = NewMemoryCollector registerCollector("memory", NewMemoryCollector, "Memory")
} }
// A MemoryCollector is a Prometheus collector for perflib Memory metrics // A MemoryCollector is a Prometheus collector for perflib Memory metrics

View File

@@ -12,7 +12,7 @@ import (
) )
func init() { func init() {
Factories["msmq"] = NewMSMQCollector registerCollector("msmq", NewMSMQCollector)
} }
var ( var (

View File

@@ -127,7 +127,7 @@ func mssqlExpandEnabledCollectors(enabled string) []string {
} }
func init() { func init() {
Factories["mssql"] = NewMSSQLCollector registerCollector("mssql", NewMSSQLCollector)
} }
// A MSSQLCollector is a Prometheus collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics // A MSSQLCollector is a Prometheus collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics

View File

@@ -12,7 +12,7 @@ import (
) )
func init() { func init() {
Factories["net"] = NewNetworkCollector registerCollector("net", NewNetworkCollector, "Network Interface")
} }
var ( var (

View File

@@ -9,7 +9,7 @@ import (
) )
func init() { func init() {
Factories["netframework_clrexceptions"] = NewNETFramework_NETCLRExceptionsCollector registerCollector("netframework_clrexceptions", NewNETFramework_NETCLRExceptionsCollector)
} }
// A NETFramework_NETCLRExceptionsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics // A NETFramework_NETCLRExceptionsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics

View File

@@ -9,7 +9,7 @@ import (
) )
func init() { func init() {
Factories["netframework_clrinterop"] = NewNETFramework_NETCLRInteropCollector registerCollector("netframework_clrinterop", NewNETFramework_NETCLRInteropCollector)
} }
// A NETFramework_NETCLRInteropCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics // A NETFramework_NETCLRInteropCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics

View File

@@ -9,7 +9,7 @@ import (
) )
func init() { func init() {
Factories["netframework_clrjit"] = NewNETFramework_NETCLRJitCollector registerCollector("netframework_clrjit", NewNETFramework_NETCLRJitCollector)
} }
// A NETFramework_NETCLRJitCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics // A NETFramework_NETCLRJitCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics

View File

@@ -9,7 +9,7 @@ import (
) )
func init() { func init() {
Factories["netframework_clrloading"] = NewNETFramework_NETCLRLoadingCollector registerCollector("netframework_clrloading", NewNETFramework_NETCLRLoadingCollector)
} }
// A NETFramework_NETCLRLoadingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics // A NETFramework_NETCLRLoadingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics

View File

@@ -9,7 +9,7 @@ import (
) )
func init() { func init() {
Factories["netframework_clrlocksandthreads"] = NewNETFramework_NETCLRLocksAndThreadsCollector registerCollector("netframework_clrlocksandthreads", NewNETFramework_NETCLRLocksAndThreadsCollector)
} }
// A NETFramework_NETCLRLocksAndThreadsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics // A NETFramework_NETCLRLocksAndThreadsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics

View File

@@ -9,7 +9,7 @@ import (
) )
func init() { func init() {
Factories["netframework_clrmemory"] = NewNETFramework_NETCLRMemoryCollector registerCollector("netframework_clrmemory", NewNETFramework_NETCLRMemoryCollector)
} }
// A NETFramework_NETCLRMemoryCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics // A NETFramework_NETCLRMemoryCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics

View File

@@ -9,7 +9,7 @@ import (
) )
func init() { func init() {
Factories["netframework_clrremoting"] = NewNETFramework_NETCLRRemotingCollector registerCollector("netframework_clrremoting", NewNETFramework_NETCLRRemotingCollector)
} }
// A NETFramework_NETCLRRemotingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics // A NETFramework_NETCLRRemotingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics

View File

@@ -9,7 +9,7 @@ import (
) )
func init() { func init() {
Factories["netframework_clrsecurity"] = NewNETFramework_NETCLRSecurityCollector registerCollector("netframework_clrsecurity", NewNETFramework_NETCLRSecurityCollector)
} }
// A NETFramework_NETCLRSecurityCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics // A NETFramework_NETCLRSecurityCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics

View File

@@ -12,7 +12,7 @@ import (
) )
func init() { func init() {
Factories["os"] = NewOSCollector registerCollector("os", NewOSCollector)
} }
// A OSCollector is a Prometheus collector for WMI metrics // A OSCollector is a Prometheus collector for WMI metrics

View File

@@ -3,14 +3,21 @@ package collector
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"strconv"
perflibCollector "github.com/leoluk/perflib_exporter/collector" perflibCollector "github.com/leoluk/perflib_exporter/collector"
"github.com/leoluk/perflib_exporter/perflib" "github.com/leoluk/perflib_exporter/perflib"
"github.com/prometheus/common/log" "github.com/prometheus/common/log"
) )
func getPerflibSnapshot() (map[string]*perflib.PerfObject, error) { var nametable = perflib.QueryNameTable("Counter 009") // Reads the names in English TODO: validate that the English names are always present
objects, err := perflib.QueryPerformanceData("Global")
func MapCounterToIndex(name string) string {
return strconv.Itoa(int(nametable.LookupIndex(name)))
}
func getPerflibSnapshot(objNames string) (map[string]*perflib.PerfObject, error) {
objects, err := perflib.QueryPerformanceData(objNames)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -13,7 +13,7 @@ import (
) )
func init() { func init() {
Factories["process"] = NewProcessCollector registerCollector("process", NewProcessCollector)
} }
var ( var (

View File

@@ -12,7 +12,7 @@ import (
) )
func init() { func init() {
Factories["service"] = NewserviceCollector registerCollector("service", NewserviceCollector)
} }
var ( var (

View File

@@ -8,7 +8,7 @@ import (
) )
func init() { func init() {
Factories["system"] = NewSystemCollector registerCollector("system", NewSystemCollector, "System")
} }
// A SystemCollector is a Prometheus collector for WMI metrics // A SystemCollector is a Prometheus collector for WMI metrics

View File

@@ -10,7 +10,7 @@ import (
) )
func init() { func init() {
Factories["tcp"] = NewTCPCollector registerCollector("tcp", NewTCPCollector)
} }
// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv4 metrics // A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv4 metrics

View File

@@ -54,7 +54,7 @@ type textFileCollector struct {
} }
func init() { func init() {
Factories["textfile"] = NewTextFileCollector registerCollector("textfile", NewTextFileCollector)
} }
// NewTextFileCollector returns a new Collector exposing metrics read from files // NewTextFileCollector returns a new Collector exposing metrics read from files

View File

@@ -7,7 +7,7 @@ import (
) )
func init() { func init() {
Factories["thermalzone"] = NewThermalZoneCollector registerCollector("thermalzone", NewThermalZoneCollector)
} }
// A thermalZoneCollector is a Prometheus collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics // A thermalZoneCollector is a Prometheus collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics

View File

@@ -11,7 +11,7 @@ import (
) )
func init() { func init() {
Factories["vmware"] = NewVmwareCollector registerCollector("vmware", NewVmwareCollector)
} }
// A VmwareCollector is a Prometheus collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics // A VmwareCollector is a Prometheus collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics

View File

@@ -97,7 +97,11 @@ func (coll WmiCollector) Collect(ch chan<- prometheus.Metric) {
) )
t := time.Now() t := time.Now()
scrapeContext, err := collector.PrepareScrapeContext() cs := make([]string, 0, len(coll.collectors))
for name := range coll.collectors {
cs = append(cs, name)
}
scrapeContext, err := collector.PrepareScrapeContext(cs)
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
snapshotDuration, snapshotDuration,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -188,17 +192,6 @@ func (coll WmiCollector) Collect(ch chan<- prometheus.Metric) {
l.Unlock() l.Unlock()
} }
func filterAvailableCollectors(collectors string) string {
var availableCollectors []string
for _, c := range strings.Split(collectors, ",") {
_, ok := collector.Factories[c]
if ok {
availableCollectors = append(availableCollectors, c)
}
}
return strings.Join(availableCollectors, ",")
}
func execute(name string, c collector.Collector, ctx *collector.ScrapeContext, ch chan<- prometheus.Metric) collectorOutcome { func execute(name string, c collector.Collector, ctx *collector.ScrapeContext, ch chan<- prometheus.Metric) collectorOutcome {
t := time.Now() t := time.Now()
err := c.Collect(ctx, ch) err := c.Collect(ctx, ch)
@@ -239,16 +232,13 @@ func loadCollectors(list string) (map[string]collector.Collector, error) {
enabled := expandEnabledCollectors(list) enabled := expandEnabledCollectors(list)
for _, name := range enabled { for _, name := range enabled {
fn, ok := collector.Factories[name] c, err := collector.Build(name)
if !ok {
return nil, fmt.Errorf("collector '%s' not available", name)
}
c, err := fn()
if err != nil { if err != nil {
return nil, err return nil, err
} }
collectors[name] = c collectors[name] = c
} }
return collectors, nil return collectors, nil
} }
@@ -278,7 +268,7 @@ func main() {
enabledCollectors = kingpin.Flag( enabledCollectors = kingpin.Flag(
"collectors.enabled", "collectors.enabled",
"Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default."). "Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default.").
Default(filterAvailableCollectors(defaultCollectors)).String() Default(defaultCollectors).String()
printCollectors = kingpin.Flag( printCollectors = kingpin.Flag(
"collectors.print", "collectors.print",
"If true, print available collectors and exit.", "If true, print available collectors and exit.",
@@ -295,8 +285,9 @@ func main() {
kingpin.Parse() kingpin.Parse()
if *printCollectors { if *printCollectors {
collectorNames := make(sort.StringSlice, 0, len(collector.Factories)) collectors := collector.Available()
for n := range collector.Factories { collectorNames := make(sort.StringSlice, 0, len(collectors))
for _, n := range collectors {
collectorNames = append(collectorNames, n) collectorNames = append(collectorNames, n)
} }
collectorNames.Sort() collectorNames.Sort()