From 667d06116d30cfb66d03aa518bb889b2ff5c5bea Mon Sep 17 00:00:00 2001 From: Calle Pettersson Date: Wed, 6 Jun 2018 10:31:50 +0200 Subject: [PATCH 1/2] Refactor wmi query generator to use wildcard selector --- collector/ad.go | 2 +- collector/cpu.go | 2 +- collector/cs.go | 2 +- collector/dns.go | 2 +- collector/hyperv.go | 20 ++-- collector/iis.go | 10 +- collector/logical_disk.go | 2 +- collector/msmq.go | 8 +- collector/net.go | 2 +- collector/netframework_clrexceptions.go | 2 +- collector/netframework_clrinterop.go | 2 +- collector/netframework_clrjit.go | 2 +- collector/netframework_clrloading.go | 2 +- collector/netframework_clrlocksandthreads.go | 2 +- collector/netframework_clrmemory.go | 2 +- collector/netframework_clrremoting.go | 2 +- collector/netframework_clrsecurity.go | 2 +- collector/os.go | 2 +- collector/process.go | 11 +- collector/service.go | 11 +- collector/system.go | 2 +- collector/tcp.go | 2 +- collector/vmware.go | 4 +- collector/wmi.go | 68 +++++++---- collector/wmi_test.go | 115 +++++++++++++++++++ exporter.go | 3 +- tools/collector-generator/collector.template | 2 +- 27 files changed, 208 insertions(+), 78 deletions(-) create mode 100644 collector/wmi_test.go diff --git a/collector/ad.go b/collector/ad.go index 4fa0e505..33224942 100644 --- a/collector/ad.go +++ b/collector/ad.go @@ -612,7 +612,7 @@ type Win32_PerfRawData_DirectoryServices_DirectoryServices struct { func (c *ADCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_DirectoryServices_DirectoryServices - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/cpu.go b/collector/cpu.go index f4e2878e..f89b953d 100644 --- a/collector/cpu.go +++ b/collector/cpu.go @@ -117,7 +117,7 @@ type Win32_PerfRawData_Counters_ProcessorInformation struct { func (c *CPUCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_PerfOS_Processor - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/cs.go b/collector/cs.go index c78bb9d8..18d8a9f6 100644 --- a/collector/cs.go +++ b/collector/cs.go @@ -56,7 +56,7 @@ type Win32_ComputerSystem struct { func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_ComputerSystem - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } diff --git a/collector/dns.go b/collector/dns.go index 676817b2..cbb13078 100644 --- a/collector/dns.go +++ b/collector/dns.go @@ -233,7 +233,7 @@ type Win32_PerfRawData_DNS_DNS struct { func (c *DNSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_DNS_DNS - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/hyperv.go b/collector/hyperv.go index 1be5a8f6..2662e421 100644 --- a/collector/hyperv.go +++ b/collector/hyperv.go @@ -657,7 +657,7 @@ type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary func (c *HyperVCollector) collectVmHealth(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } @@ -689,7 +689,7 @@ type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct { func (c *HyperVCollector) collectVmVid(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } @@ -752,7 +752,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct { func (c *HyperVCollector) collectVmHv(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } @@ -889,7 +889,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisor struct { func (c *HyperVCollector) collectVmProcessor(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisor - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } @@ -923,7 +923,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct { func (c *HyperVCollector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } @@ -983,7 +983,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct { func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } @@ -1060,7 +1060,7 @@ type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct { func (c *HyperVCollector) collectVmSwitch(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } @@ -1218,7 +1218,7 @@ type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct { func (c *HyperVCollector) collectVmEthernet(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } @@ -1287,7 +1287,7 @@ type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct { func (c *HyperVCollector) collectVmStorage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } @@ -1355,7 +1355,7 @@ type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct { func (c *HyperVCollector) collectVmNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } diff --git a/collector/iis.go b/collector/iis.go index 0dc4b5d8..5139f14e 100644 --- a/collector/iis.go +++ b/collector/iis.go @@ -995,7 +995,7 @@ var workerProcessNameExtractor = regexp.MustCompile(`^(\d+)_(.+)$`) func (c *IISCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_W3SVC_WebService - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1248,7 +1248,7 @@ func (c *IISCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, e } var dst2 []Win32_PerfRawData_APPPOOLCountersProvider_APPPOOLWAS - q2 := wmi.CreateQuery(&dst2, "") + q2 := queryAll(&dst2) if err := wmi.Query(q2, &dst2); err != nil { return nil, err } @@ -1365,7 +1365,7 @@ func (c *IISCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, e } var dst_worker []Win32_PerfRawData_W3SVCW3WPCounterProvider_W3SVCW3WP - q = wmi.CreateQuery(&dst_worker, "") + q = queryAll(&dst_worker) if err := wmi.Query(q, &dst_worker); err != nil { return nil, err } @@ -1647,7 +1647,7 @@ func (c *IISCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, e if iis_version.major >= 8 { var dst_worker_iis8 []Win32_PerfRawData_W3SVCW3WPCounterProvider_W3SVCW3WP_IIS8 - q = createQuery(&dst_worker_iis8, "Win32_PerfRawData_W3SVCW3WPCounterProvider_W3SVCW3WP", "") + q = queryAllForClass(&dst_worker_iis8, "Win32_PerfRawData_W3SVCW3WPCounterProvider_W3SVCW3WP") if err := wmi.Query(q, &dst_worker_iis8); err != nil { return nil, err } @@ -1730,7 +1730,7 @@ func (c *IISCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, e } var dst_cache []Win32_PerfRawData_W3SVC_WebServiceCache - q = wmi.CreateQuery(&dst_cache, "") + q = queryAll(&dst_cache) if err := wmi.Query(q, &dst_cache); err != nil { return nil, err } diff --git a/collector/logical_disk.go b/collector/logical_disk.go index 4bc49428..f685c6c5 100644 --- a/collector/logical_disk.go +++ b/collector/logical_disk.go @@ -161,7 +161,7 @@ type Win32_PerfRawData_PerfDisk_LogicalDisk struct { func (c *LogicalDiskCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_PerfDisk_LogicalDisk - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/msmq.go b/collector/msmq.go index b9b4b145..03985144 100644 --- a/collector/msmq.go +++ b/collector/msmq.go @@ -3,7 +3,6 @@ package collector import ( - "bytes" "strings" "github.com/StackExchange/wmi" @@ -34,10 +33,7 @@ type Win32_PerfRawData_MSMQ_MSMQQueueCollector struct { func NewMSMQCollector() (Collector, error) { const subsystem = "msmq" - var wc bytes.Buffer if *msmqWhereClause != "" { - wc.WriteString("WHERE ") - wc.WriteString(*msmqWhereClause) log.Warn("No where-clause specified for msmq collector. This will generate a very large number of metrics!") } @@ -66,7 +62,7 @@ func NewMSMQCollector() (Collector, error) { []string{"name"}, nil, ), - queryWhereClause: wc.String(), + queryWhereClause: *msmqWhereClause, }, nil } @@ -91,7 +87,7 @@ type Win32_PerfRawData_MSMQ_MSMQQueue struct { func (c *Win32_PerfRawData_MSMQ_MSMQQueueCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_MSMQ_MSMQQueue - q := wmi.CreateQuery(&dst, c.queryWhereClause) + q := queryAllWhere(&dst, c.queryWhereClause) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/net.go b/collector/net.go index 98fb2827..e159ce66 100644 --- a/collector/net.go +++ b/collector/net.go @@ -169,7 +169,7 @@ type Win32_PerfRawData_Tcpip_NetworkInterface struct { func (c *NetworkCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_Tcpip_NetworkInterface - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/netframework_clrexceptions.go b/collector/netframework_clrexceptions.go index 637d2501..90f26ee3 100644 --- a/collector/netframework_clrexceptions.go +++ b/collector/netframework_clrexceptions.go @@ -73,7 +73,7 @@ type Win32_PerfRawData_NETFramework_NETCLRExceptions struct { func (c *NETFramework_NETCLRExceptionsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/netframework_clrinterop.go b/collector/netframework_clrinterop.go index b22f9e99..ad79e32f 100644 --- a/collector/netframework_clrinterop.go +++ b/collector/netframework_clrinterop.go @@ -66,7 +66,7 @@ type Win32_PerfRawData_NETFramework_NETCLRInterop struct { func (c *NETFramework_NETCLRInteropCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NETFramework_NETCLRInterop - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/netframework_clrjit.go b/collector/netframework_clrjit.go index 19bb61c6..8c6e54da 100644 --- a/collector/netframework_clrjit.go +++ b/collector/netframework_clrjit.go @@ -75,7 +75,7 @@ type Win32_PerfRawData_NETFramework_NETCLRJit struct { func (c *NETFramework_NETCLRJitCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NETFramework_NETCLRJit - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/netframework_clrloading.go b/collector/netframework_clrloading.go index caba7e1e..61cd50e1 100644 --- a/collector/netframework_clrloading.go +++ b/collector/netframework_clrloading.go @@ -119,7 +119,7 @@ type Win32_PerfRawData_NETFramework_NETCLRLoading struct { func (c *NETFramework_NETCLRLoadingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NETFramework_NETCLRLoading - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/netframework_clrlocksandthreads.go b/collector/netframework_clrlocksandthreads.go index f78430ce..7d9bee99 100644 --- a/collector/netframework_clrlocksandthreads.go +++ b/collector/netframework_clrlocksandthreads.go @@ -99,7 +99,7 @@ type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct { func (c *NETFramework_NETCLRLocksAndThreadsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/netframework_clrmemory.go b/collector/netframework_clrmemory.go index 52c913bb..a7a6d483 100644 --- a/collector/netframework_clrmemory.go +++ b/collector/netframework_clrmemory.go @@ -151,7 +151,7 @@ type Win32_PerfRawData_NETFramework_NETCLRMemory struct { func (c *NETFramework_NETCLRMemoryCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NETFramework_NETCLRMemory - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/netframework_clrremoting.go b/collector/netframework_clrremoting.go index b4c6b5fc..58acf37e 100644 --- a/collector/netframework_clrremoting.go +++ b/collector/netframework_clrremoting.go @@ -89,7 +89,7 @@ type Win32_PerfRawData_NETFramework_NETCLRRemoting struct { func (c *NETFramework_NETCLRRemotingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/netframework_clrsecurity.go b/collector/netframework_clrsecurity.go index 457a04b3..2dfdf588 100644 --- a/collector/netframework_clrsecurity.go +++ b/collector/netframework_clrsecurity.go @@ -74,7 +74,7 @@ type Win32_PerfRawData_NETFramework_NETCLRSecurity struct { func (c *NETFramework_NETCLRSecurityCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/os.go b/collector/os.go index 244eeee9..b476c4d6 100644 --- a/collector/os.go +++ b/collector/os.go @@ -137,7 +137,7 @@ type Win32_OperatingSystem struct { func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_OperatingSystem - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } diff --git a/collector/process.go b/collector/process.go index 9b45200d..f3bc2b04 100644 --- a/collector/process.go +++ b/collector/process.go @@ -3,7 +3,6 @@ package collector import ( - "bytes" "strconv" "strings" @@ -47,11 +46,7 @@ type ProcessCollector struct { func NewProcessCollector() (Collector, error) { const subsystem = "process" - var wc bytes.Buffer - if *processWhereClause != "" { - wc.WriteString("WHERE ") - wc.WriteString(*processWhereClause) - } else { + if *processWhereClause == "" { log.Warn("No where-clause specified for process collector. This will generate a very large number of metrics!") } @@ -134,7 +129,7 @@ func NewProcessCollector() (Collector, error) { []string{"process", "process_id", "creating_process_id"}, nil, ), - queryWhereClause: wc.String(), + queryWhereClause: *processWhereClause, }, nil } @@ -184,7 +179,7 @@ type Win32_PerfRawData_PerfProc_Process struct { func (c *ProcessCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_PerfProc_Process - q := wmi.CreateQuery(&dst, c.queryWhereClause) + q := queryAllWhere(&dst, c.queryWhereClause) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/service.go b/collector/service.go index cb692d7a..50bcc3ea 100644 --- a/collector/service.go +++ b/collector/service.go @@ -3,7 +3,6 @@ package collector import ( - "bytes" "strings" "github.com/StackExchange/wmi" @@ -36,11 +35,7 @@ type serviceCollector struct { func NewserviceCollector() (Collector, error) { const subsystem = "service" - var wc bytes.Buffer - if *serviceWhereClause != "" { - wc.WriteString("WHERE ") - wc.WriteString(*serviceWhereClause) - } else { + if *serviceWhereClause == "" { log.Warn("No where-clause specified for service collector. This will generate a very large number of metrics!") } @@ -63,7 +58,7 @@ func NewserviceCollector() (Collector, error) { []string{"name", "status"}, nil, ), - queryWhereClause: wc.String(), + queryWhereClause: *serviceWhereClause, }, nil } @@ -120,7 +115,7 @@ var ( func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_Service - q := wmi.CreateQuery(&dst, c.queryWhereClause) + q := queryAllWhere(&dst, c.queryWhereClause) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/system.go b/collector/system.go index 051da15b..58b3f292 100644 --- a/collector/system.go +++ b/collector/system.go @@ -90,7 +90,7 @@ type Win32_PerfRawData_PerfOS_System struct { func (c *SystemCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_PerfOS_System - if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil { + if err := wmi.Query(queryAll(&dst), &dst); err != nil { return nil, err } diff --git a/collector/tcp.go b/collector/tcp.go index 15a9f621..6dafd767 100644 --- a/collector/tcp.go +++ b/collector/tcp.go @@ -114,7 +114,7 @@ type Win32_PerfRawData_Tcpip_TCPv4 struct { func (c *TCPCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_Tcpip_TCPv4 - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/vmware.go b/collector/vmware.go index 568106c1..094e117d 100644 --- a/collector/vmware.go +++ b/collector/vmware.go @@ -197,7 +197,7 @@ type Win32_PerfRawData_vmGuestLib_VCPU struct { func (c *VmwareCollector) collectMem(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_vmGuestLib_VMem - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -283,7 +283,7 @@ func mbToBytes(mb uint64) float64 { func (c *VmwareCollector) collectCpu(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_vmGuestLib_VCPU - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/wmi.go b/collector/wmi.go index 47dbe59b..b4a99ba8 100644 --- a/collector/wmi.go +++ b/collector/wmi.go @@ -3,9 +3,9 @@ package collector import ( "bytes" "reflect" - "strings" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" ) // ... @@ -25,29 +25,57 @@ type Collector interface { Collect(ch chan<- prometheus.Metric) (err error) } -// This is adapted from StackExchange/wmi/wmi.go, and lets us change the class -// name being queried for: -// CreateQuery returns a WQL query string that queries all columns of src. where -// is an optional string that is appended to the query, to be used with WHERE -// clauses. In such a case, the "WHERE" string should appear at the beginning. -func createQuery(src interface{}, class, where string) string { - var b bytes.Buffer - b.WriteString("SELECT ") +func className(src interface{}) string { s := reflect.Indirect(reflect.ValueOf(src)) t := s.Type() if s.Kind() == reflect.Slice { t = t.Elem() } - if t.Kind() != reflect.Struct { - return "" - } - var fields []string - for i := 0; i < t.NumField(); i++ { - fields = append(fields, t.Field(i).Name) - } - b.WriteString(strings.Join(fields, ", ")) - b.WriteString(" FROM ") - b.WriteString(class) - b.WriteString(" " + where) + return t.Name() +} + +func queryAll(src interface{}) string { + var b bytes.Buffer + b.WriteString("SELECT * FROM ") + b.WriteString(className(src)) + + log.Debugf("Generated WMI query %s", b.String()) + return b.String() +} + +func queryAllForClass(src interface{}, class string) string { + var b bytes.Buffer + b.WriteString("SELECT * FROM ") + b.WriteString(class) + + log.Debugf("Generated WMI query %s", b.String()) + return b.String() +} + +func queryAllWhere(src interface{}, where string) string { + var b bytes.Buffer + b.WriteString("SELECT * FROM ") + b.WriteString(className(src)) + + if where != "" { + b.WriteString(" WHERE ") + b.WriteString(where) + } + + log.Debugf("Generated WMI query %s", b.String()) + return b.String() +} + +func queryAllForClassWhere(src interface{}, class string, where string) string { + var b bytes.Buffer + b.WriteString("SELECT * FROM ") + b.WriteString(class) + + if where != "" { + b.WriteString(" WHERE ") + b.WriteString(where) + } + + log.Debugf("Generated WMI query %s", b.String()) return b.String() } diff --git a/collector/wmi_test.go b/collector/wmi_test.go new file mode 100644 index 00000000..5303d086 --- /dev/null +++ b/collector/wmi_test.go @@ -0,0 +1,115 @@ +package collector + +import ( + "testing" +) + +type fakeWmiClass struct { + Name string + SomeProperty int +} + +var ( + mapQueryAll = func(src interface{}, class string, where string) string { + return queryAll(src) + } + mapQueryAllWhere = func(src interface{}, class string, where string) string { + return queryAllWhere(src, where) + } + mapQueryAllForClass = func(src interface{}, class string, where string) string { + return queryAllForClass(src, class) + } + mapQueryAllForClassWhere = func(src interface{}, class string, where string) string { + return queryAllForClassWhere(src, class, where) + } +) + +type queryFunc func(src interface{}, class string, where string) string + +func TestCreateQuery(t *testing.T) { + cases := []struct { + desc string + dst interface{} + class string + where string + queryFunc queryFunc + expected string + }{ + { + desc: "queryAll on single instance", + dst: fakeWmiClass{}, + queryFunc: mapQueryAll, + expected: "SELECT * FROM fakeWmiClass", + }, + { + desc: "queryAll on slice", + dst: []fakeWmiClass{}, + queryFunc: mapQueryAll, + expected: "SELECT * FROM fakeWmiClass", + }, + { + desc: "queryAllWhere on single instance", + dst: fakeWmiClass{}, + where: "foo = bar", + queryFunc: mapQueryAllWhere, + expected: "SELECT * FROM fakeWmiClass WHERE foo = bar", + }, + { + desc: "queryAllWhere on slice", + dst: []fakeWmiClass{}, + where: "foo = bar", + queryFunc: mapQueryAllWhere, + expected: "SELECT * FROM fakeWmiClass WHERE foo = bar", + }, + { + desc: "queryAllWhere on single instance with empty where", + dst: fakeWmiClass{}, + queryFunc: mapQueryAllWhere, + expected: "SELECT * FROM fakeWmiClass", + }, + { + desc: "queryAllForClass on single instance", + dst: fakeWmiClass{}, + class: "someClass", + queryFunc: mapQueryAllForClass, + expected: "SELECT * FROM someClass", + }, + { + desc: "queryAllForClass on slice", + dst: []fakeWmiClass{}, + class: "someClass", + queryFunc: mapQueryAllForClass, + expected: "SELECT * FROM someClass", + }, + { + desc: "queryAllForClassWhere on single instance", + dst: fakeWmiClass{}, + class: "someClass", + where: "foo = bar", + queryFunc: mapQueryAllForClassWhere, + expected: "SELECT * FROM someClass WHERE foo = bar", + }, + { + desc: "queryAllForClassWhere on slice", + dst: []fakeWmiClass{}, + class: "someClass", + where: "foo = bar", + queryFunc: mapQueryAllForClassWhere, + expected: "SELECT * FROM someClass WHERE foo = bar", + }, + { + desc: "queryAllForClassWhere on single instance with empty where", + dst: fakeWmiClass{}, + class: "someClass", + queryFunc: mapQueryAllForClassWhere, + expected: "SELECT * FROM someClass", + }, + } + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + if q := c.queryFunc(c.dst, c.class, c.where); q != c.expected { + t.Errorf("Case %q failed: Expected %q, got %q", c.desc, c.expected, q) + } + }) + } +} diff --git a/exporter.go b/exporter.go index 94586c9a..7ab98cd4 100644 --- a/exporter.go +++ b/exporter.go @@ -47,7 +47,7 @@ var ( // This can be removed when client_golang exposes this on Windows // (See https://github.com/prometheus/client_golang/issues/376) - startTime = float64(time.Now().Unix()) + startTime = float64(time.Now().Unix()) startTimeDesc = prometheus.NewDesc( "process_start_time_seconds", "Start time of the process since unix epoch in seconds.", @@ -169,6 +169,7 @@ func initWbem() { if err != nil { log.Fatal(err) } + wmi.DefaultClient.AllowMissingFields = true wmi.DefaultClient.SWbemServicesClient = s } diff --git a/tools/collector-generator/collector.template b/tools/collector-generator/collector.template index 186ebd3d..68c17cad 100644 --- a/tools/collector-generator/collector.template +++ b/tools/collector-generator/collector.template @@ -46,7 +46,7 @@ type {{ .Class }} struct { } func (c *{{ .CollectorName }}Collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []{{ .Class }} - q := wmi.CreateQuery(&dst, "") + q := queryAll(&dst) if err := wmi.Query(q, &dst); err != nil { return nil, err } From cd365c6a3b5b6818e00baa0395c96e25b8b4a03e Mon Sep 17 00:00:00 2001 From: Calle Pettersson Date: Wed, 6 Jun 2018 11:35:13 +0200 Subject: [PATCH 2/2] Harmonize query call layout --- collector/cs.go | 3 ++- collector/hyperv.go | 32 +++++++++++++++++++++----------- collector/os.go | 3 ++- collector/system.go | 3 ++- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/collector/cs.go b/collector/cs.go index 18d8a9f6..6f7aaed6 100644 --- a/collector/cs.go +++ b/collector/cs.go @@ -56,7 +56,8 @@ type Win32_ComputerSystem struct { func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_ComputerSystem - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/hyperv.go b/collector/hyperv.go index 2662e421..84b86b8b 100644 --- a/collector/hyperv.go +++ b/collector/hyperv.go @@ -95,7 +95,7 @@ type HyperVCollector struct { // Win32_PerfRawData_Counters_HyperVVirtualStorageDevice VMStorageErrorCount *prometheus.Desc - VMStorageQueueLength *prometheus.Desc + VMStorageQueueLength *prometheus.Desc VMStorageReadBytes *prometheus.Desc VMStorageReadOperations *prometheus.Desc VMStorageWriteBytes *prometheus.Desc @@ -657,7 +657,8 @@ type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary func (c *HyperVCollector) collectVmHealth(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -689,7 +690,8 @@ type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct { func (c *HyperVCollector) collectVmVid(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -752,7 +754,8 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct { func (c *HyperVCollector) collectVmHv(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -889,7 +892,8 @@ type Win32_PerfRawData_HvStats_HyperVHypervisor struct { func (c *HyperVCollector) collectVmProcessor(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisor - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -923,7 +927,8 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct { func (c *HyperVCollector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -983,7 +988,8 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct { func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1060,7 +1066,8 @@ type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct { func (c *HyperVCollector) collectVmSwitch(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1218,7 +1225,8 @@ type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct { func (c *HyperVCollector) collectVmEthernet(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1287,7 +1295,8 @@ type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct { func (c *HyperVCollector) collectVmStorage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1355,7 +1364,8 @@ type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct { func (c *HyperVCollector) collectVmNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/os.go b/collector/os.go index b476c4d6..7c890bd9 100644 --- a/collector/os.go +++ b/collector/os.go @@ -137,7 +137,8 @@ type Win32_OperatingSystem struct { func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_OperatingSystem - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/collector/system.go b/collector/system.go index 58b3f292..ddbe09cd 100644 --- a/collector/system.go +++ b/collector/system.go @@ -90,7 +90,8 @@ type Win32_PerfRawData_PerfOS_System struct { func (c *SystemCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_PerfOS_System - if err := wmi.Query(queryAll(&dst), &dst); err != nil { + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { return nil, err }