diff --git a/collector/collector.go b/collector/collector.go index 3f0ab4c3..b5b3a236 100644 --- a/collector/collector.go +++ b/collector/collector.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/leoluk/perflib_exporter/perflib" "github.com/prometheus-community/windows_exporter/log" "github.com/prometheus/client_golang/prometheus" @@ -51,6 +52,8 @@ func getWindowsVersion() float64 { } type collectorBuilder func() (Collector, error) +type flagsBuilder func(*kingpin.Application) +type perfCounterNamesBuilder func() []string var ( builders = make(map[string]collectorBuilder) diff --git a/collector/dfsr.go b/collector/dfsr.go index 0874ec69..22def85b 100644 --- a/collector/dfsr.go +++ b/collector/dfsr.go @@ -9,7 +9,11 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -var dfsrEnabledCollectors = kingpin.Flag("collectors.dfsr.sources-enabled", "Comma-seperated list of DFSR Perflib sources to use.").Default("connection,folder,volume").String() +const ( + FlagDfsrEnabledCollectors = "collectors.dfsr.sources-enabled" +) + +var dfsrEnabledCollectors *string // DFSRCollector contains the metric and state data of the DFSR collectors. type DFSRCollector struct { @@ -82,6 +86,11 @@ func dfsrGetPerfObjectName(collector string) string { return (prefix + suffix) } +// newDFSRCollectorFlags is registered +func newDFSRCollectorFlags(app *kingpin.Application) { + dfsrEnabledCollectors = app.Flag(FlagDfsrEnabledCollectors, "Comma-seperated list of DFSR Perflib sources to use.").Default("connection,folder,volume").String() +} + // newDFSRCollector is registered func newDFSRCollector() (Collector, error) { log.Info("dfsr collector is in an experimental state! Metrics for this collector have not been tested.") diff --git a/collector/exchange.go b/collector/exchange.go index 1a6b1320..90d2f870 100644 --- a/collector/exchange.go +++ b/collector/exchange.go @@ -13,6 +13,11 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +const ( + FlagExchangeListAllCollectors = "collectors.exchange.list" + FlagExchangeCollectorsEnabled = "collectors.exchange.enabled" +) + type exchangeCollector struct { LDAPReadTime *prometheus.Desc LDAPSearchTime *prometheus.Desc @@ -69,16 +74,23 @@ var ( "RpcClientAccess", } - argExchangeListAllCollectors = kingpin.Flag( - "collectors.exchange.list", + argExchangeListAllCollectors *bool + + argExchangeCollectorsEnabled *string +) + +// newExchangeCollectorFlags ... +func newExchangeCollectorFlags(app *kingpin.Application) { + argExchangeListAllCollectors = app.Flag( + FlagExchangeListAllCollectors, "List the collectors along with their perflib object name/ids", ).Bool() - argExchangeCollectorsEnabled = kingpin.Flag( - "collectors.exchange.enabled", + argExchangeCollectorsEnabled = app.Flag( + FlagExchangeCollectorsEnabled, "Comma-separated list of collectors to use. Defaults to all, if not specified.", ).Default("").String() -) +} // newExchangeCollector returns a new Collector func newExchangeCollector() (Collector, error) { diff --git a/collector/iis.go b/collector/iis.go index fc691da0..8532c272 100644 --- a/collector/iis.go +++ b/collector/iis.go @@ -13,11 +13,18 @@ import ( "golang.org/x/sys/windows/registry" ) +const ( + FlagISSSiteBlacklist = "collector.iis.site-blacklist" + FlagISSSiteWhitelist = "collector.iis.site-whitelist" + FlagISSAppBlacklist = "collector.iis.app-blacklist" + FlagISSAppWhitelist = "collector.iis.app-whitelist" +) + var ( - siteWhitelist = kingpin.Flag("collector.iis.site-whitelist", "Regexp of sites to whitelist. Site name must both match whitelist and not match blacklist to be included.").Default(".+").String() - siteBlacklist = kingpin.Flag("collector.iis.site-blacklist", "Regexp of sites to blacklist. Site name must both match whitelist and not match blacklist to be included.").String() - appWhitelist = kingpin.Flag("collector.iis.app-whitelist", "Regexp of apps to whitelist. App name must both match whitelist and not match blacklist to be included.").Default(".+").String() - appBlacklist = kingpin.Flag("collector.iis.app-blacklist", "Regexp of apps to blacklist. App name must both match whitelist and not match blacklist to be included.").String() + siteWhitelist *string + siteBlacklist *string + appWhitelist *string + appBlacklist *string ) type simple_version struct { @@ -191,6 +198,13 @@ type IISCollector struct { iis_version simple_version } +func newIISCollectorFlags(app *kingpin.Application) { + siteWhitelist = kingpin.Flag(FlagISSSiteWhitelist, "Regexp of sites to whitelist. Site name must both match whitelist and not match blacklist to be included.").Default(".+").String() + siteBlacklist = kingpin.Flag(FlagISSSiteBlacklist, "Regexp of sites to blacklist. Site name must both match whitelist and not match blacklist to be included.").String() + appWhitelist = kingpin.Flag(FlagISSAppWhitelist, "Regexp of apps to whitelist. App name must both match whitelist and not match blacklist to be included.").Default(".+").String() + appBlacklist = kingpin.Flag(FlagISSAppBlacklist, "Regexp of apps to blacklist. App name must both match whitelist and not match blacklist to be included.").String() +} + func newIISCollector() (Collector, error) { const subsystem = "iis" diff --git a/collector/init.go b/collector/init.go index 932c0d08..63e8e9ea 100644 --- a/collector/init.go +++ b/collector/init.go @@ -1,23 +1,18 @@ package collector +import "github.com/alecthomas/kingpin/v2" + // collectorInit represents the required initialisation config for a collector. type collectorInit struct { // Name of collector to be initialised name string // Builder function for the collector + flags flagsBuilder + // Builder function for the collector builder collectorBuilder // Perflib counter names for the collector. // These will be included in the Perflib scrape scope by the exporter. - perfCounterNames []string -} - -func getCPUCollectorDeps() string { - // See below for 6.05 magic value - if getWindowsVersion() > 6.05 { - return "Processor Information" - } - return "Processor" - + perfCounterFunc perfCounterNamesBuilder } func getDFSRCollectorDeps() []string { @@ -32,278 +27,381 @@ func getDFSRCollectorDeps() []string { var collectors = []collectorInit{ { - name: "ad", - builder: newADCollector, - perfCounterNames: nil, + name: "ad", + flags: nil, + builder: newADCollector, + perfCounterFunc: nil, }, { - name: "adcs", - builder: adcsCollectorMethod, - perfCounterNames: []string{"Certification Authority"}, + name: "adcs", + flags: nil, + builder: adcsCollectorMethod, + perfCounterFunc: func() []string { + return []string{"Certification Authority"} + }, }, { - name: "adfs", - builder: newADFSCollector, - perfCounterNames: []string{"AD FS"}, + name: "adfs", + flags: nil, + builder: newADFSCollector, + perfCounterFunc: func() []string { + return []string{"AD FS"} + }, }, { - name: "cache", - builder: newCacheCollector, - perfCounterNames: []string{"Cache"}, + name: "cache", + flags: nil, + builder: newCacheCollector, + perfCounterFunc: func() []string { + return []string{"Cache"} + }, }, { - name: "container", - builder: newContainerMetricsCollector, - perfCounterNames: nil, + name: "container", + flags: nil, + builder: newContainerMetricsCollector, + perfCounterFunc: nil, }, { - name: "cpu", - builder: newCPUCollector, - perfCounterNames: []string{getCPUCollectorDeps()}, + name: "cpu", + flags: nil, + builder: newCPUCollector, + perfCounterFunc: func() []string { + if getWindowsVersion() > 6.05 { + return []string{"Processor Information"} + } + return []string{"Processor"} + }, }, { - name: "cpu_info", - builder: newCpuInfoCollector, - perfCounterNames: nil, + name: "cpu_info", + flags: nil, + builder: newCpuInfoCollector, + perfCounterFunc: nil, }, { - name: "cs", - builder: newCSCollector, - perfCounterNames: nil, + name: "cs", + flags: nil, + builder: newCSCollector, + perfCounterFunc: nil, }, { - name: "dfsr", - builder: newDFSRCollector, - perfCounterNames: getDFSRCollectorDeps(), + name: "dfsr", + flags: newDFSRCollectorFlags, + builder: newDFSRCollector, + perfCounterFunc: getDFSRCollectorDeps, }, { - name: "dhcp", - builder: newDhcpCollector, - perfCounterNames: nil, + name: "dhcp", + flags: nil, + builder: newDhcpCollector, + perfCounterFunc: nil, }, { - name: "diskdrive", - builder: newDiskDriveInfoCollector, - perfCounterNames: nil, + name: "diskdrive", + flags: nil, + builder: newDiskDriveInfoCollector, + perfCounterFunc: nil, }, { - name: "dns", - builder: newDNSCollector, - perfCounterNames: nil, + name: "dns", + flags: nil, + builder: newDNSCollector, + perfCounterFunc: nil, }, { name: "exchange", + flags: newExchangeCollectorFlags, builder: newExchangeCollector, - perfCounterNames: []string{ - "MSExchange ADAccess Processes", - "MSExchangeTransport Queues", - "MSExchange HttpProxy", - "MSExchange ActiveSync", - "MSExchange Availability Service", - "MSExchange OWA", - "MSExchangeAutodiscover", - "MSExchange WorkloadManagement Workloads", - "MSExchange RpcClientAccess", + perfCounterFunc: func() []string { + return []string{ + "MSExchange ADAccess Processes", + "MSExchangeTransport Queues", + "MSExchange HttpProxy", + "MSExchange ActiveSync", + "MSExchange Availability Service", + "MSExchange OWA", + "MSExchangeAutodiscover", + "MSExchange WorkloadManagement Workloads", + "MSExchange RpcClientAccess", + } }, }, { - name: "fsrmquota", - builder: newFSRMQuotaCollector, - perfCounterNames: nil, + name: "fsrmquota", + flags: nil, + builder: newFSRMQuotaCollector, + perfCounterFunc: nil, }, { - name: "hyperv", - builder: newHyperVCollector, - perfCounterNames: nil, + name: "hyperv", + flags: nil, + builder: newHyperVCollector, + perfCounterFunc: nil, }, { name: "iis", + flags: newIISCollectorFlags, builder: newIISCollector, - perfCounterNames: []string{"Web Service", - "APP_POOL_WAS", - "Web Service Cache", - "W3SVC_W3WP", + perfCounterFunc: func() []string { + return []string{ + "Web Service", + "APP_POOL_WAS", + "Web Service Cache", + "W3SVC_W3WP", + } }, }, { - name: "logical_disk", - builder: newLogicalDiskCollector, - perfCounterNames: []string{"LogicalDisk"}, + name: "logical_disk", + flags: newLogicalDiskCollectorFlags, + builder: newLogicalDiskCollector, + perfCounterFunc: func() []string { + return []string{"LogicalDisk"} + }, }, { - name: "logon", - builder: newLogonCollector, - perfCounterNames: nil, + name: "logon", + flags: nil, + builder: newLogonCollector, + perfCounterFunc: nil, }, { - name: "memory", - builder: newMemoryCollector, - perfCounterNames: []string{"Memory"}, + name: "memory", + flags: nil, + builder: newMemoryCollector, + perfCounterFunc: func() []string { + return []string{"Memory"} + }, }, { - name: "mscluster_cluster", - builder: newMSCluster_ClusterCollector, - perfCounterNames: nil, + name: "mscluster_cluster", + flags: nil, + builder: newMSCluster_ClusterCollector, + perfCounterFunc: nil, }, { - name: "mscluster_network", - builder: newMSCluster_NetworkCollector, - perfCounterNames: nil, + name: "mscluster_network", + flags: nil, + builder: newMSCluster_NetworkCollector, + perfCounterFunc: nil, }, { - name: "mscluster_node", - builder: newMSCluster_NodeCollector, - perfCounterNames: nil, + name: "mscluster_node", + flags: nil, + builder: newMSCluster_NodeCollector, + perfCounterFunc: nil, }, { - name: "mscluster_resource", - builder: newMSCluster_ResourceCollector, - perfCounterNames: nil, + name: "mscluster_resource", + flags: nil, + builder: newMSCluster_ResourceCollector, + perfCounterFunc: nil, }, { - name: "mscluster_resourcegroup", - builder: newMSCluster_ResourceGroupCollector, - perfCounterNames: nil, + name: "mscluster_resourcegroup", + flags: nil, + builder: newMSCluster_ResourceGroupCollector, + perfCounterFunc: nil, }, { - name: "msmq", - builder: newMSMQCollector, - perfCounterNames: nil, + name: "msmq", + flags: newMSMQCollectorFlags, + builder: newMSMQCollector, + perfCounterFunc: nil, }, { - name: "mssql", - builder: newMSSQLCollector, - perfCounterNames: nil, + name: "mssql", + flags: newMSSQLCollectorFlags, + builder: newMSSQLCollector, + perfCounterFunc: nil, }, { - name: "net", - builder: newNetworkCollector, - perfCounterNames: []string{"Network Interface"}, + name: "net", + flags: newNetworkCollectorFlags, + builder: newNetworkCollector, + perfCounterFunc: func() []string { + return []string{"Network Interface"} + }, }, { - name: "netframework_clrexceptions", - builder: newNETFramework_NETCLRExceptionsCollector, - perfCounterNames: nil, + name: "netframework_clrexceptions", + flags: nil, + builder: newNETFramework_NETCLRExceptionsCollector, + perfCounterFunc: nil, }, { - name: "netframework_clrinterop", - builder: newNETFramework_NETCLRInteropCollector, - perfCounterNames: nil, + name: "netframework_clrinterop", + flags: nil, + builder: newNETFramework_NETCLRInteropCollector, + perfCounterFunc: nil, }, { - name: "netframework_clrjit", - builder: newNETFramework_NETCLRJitCollector, - perfCounterNames: nil, + name: "netframework_clrjit", + flags: nil, + builder: newNETFramework_NETCLRJitCollector, + perfCounterFunc: nil, }, { - name: "netframework_clrloading", - builder: newNETFramework_NETCLRLoadingCollector, - perfCounterNames: nil, + name: "netframework_clrloading", + flags: nil, + builder: newNETFramework_NETCLRLoadingCollector, + perfCounterFunc: nil, }, { - name: "netframework_clrlocksandthreads", - builder: newNETFramework_NETCLRLocksAndThreadsCollector, - perfCounterNames: nil, + name: "netframework_clrlocksandthreads", + flags: nil, + builder: newNETFramework_NETCLRLocksAndThreadsCollector, + perfCounterFunc: nil, }, { - name: "netframework_clrmemory", - builder: newNETFramework_NETCLRMemoryCollector, - perfCounterNames: nil, + name: "netframework_clrmemory", + flags: nil, + builder: newNETFramework_NETCLRMemoryCollector, + perfCounterFunc: nil, }, { - name: "netframework_clrremoting", - builder: newNETFramework_NETCLRRemotingCollector, - perfCounterNames: nil, + name: "netframework_clrremoting", + flags: nil, + builder: newNETFramework_NETCLRRemotingCollector, + perfCounterFunc: nil, }, { - name: "netframework_clrsecurity", - builder: newNETFramework_NETCLRSecurityCollector, - perfCounterNames: nil, + name: "netframework_clrsecurity", + flags: nil, + builder: newNETFramework_NETCLRSecurityCollector, + perfCounterFunc: nil, }, { - name: "os", - builder: newOSCollector, - perfCounterNames: []string{"Paging File"}, + name: "os", + flags: nil, + builder: newOSCollector, + perfCounterFunc: func() []string { + return []string{"Paging File"} + }, }, { - name: "process", - builder: newProcessCollector, - perfCounterNames: []string{"Process"}, + name: "process", + flags: newProcessCollectorFlags, + builder: newProcessCollector, + perfCounterFunc: func() []string { + return []string{"Process"} + }, }, { - name: "remote_fx", - builder: newRemoteFx, - perfCounterNames: []string{"RemoteFX Network"}, + name: "remote_fx", + flags: nil, + builder: newRemoteFx, + perfCounterFunc: func() []string { + return []string{"RemoteFX Network"} + }, }, { - name: "scheduled_task", - builder: newScheduledTask, - perfCounterNames: nil, + name: "scheduled_task", + flags: newScheduledTaskFlags, + builder: newScheduledTask, + perfCounterFunc: nil, }, { - name: "service", - builder: newserviceCollector, - perfCounterNames: nil, + name: "service", + flags: newServiceCollectorFlags, + builder: newserviceCollector, + perfCounterFunc: nil, }, { - name: "smtp", - builder: newSMTPCollector, - perfCounterNames: []string{"SMTP Server"}, + name: "smtp", + flags: newSMTPCollectorFlags, + builder: newSMTPCollector, + perfCounterFunc: func() []string { + return []string{"SMTP Server"} + }, }, { - name: "system", - builder: newSystemCollector, - perfCounterNames: []string{"System"}, + name: "system", + flags: nil, + builder: newSystemCollector, + perfCounterFunc: func() []string { + return []string{"System"} + }, }, { - name: "teradici_pcoip", - builder: newTeradiciPcoipCollector, - perfCounterNames: nil, + name: "teradici_pcoip", + flags: nil, + builder: newTeradiciPcoipCollector, + perfCounterFunc: nil, }, { - name: "tcp", - builder: newTCPCollector, - perfCounterNames: []string{"TCPv4"}, + name: "tcp", + flags: nil, + builder: newTCPCollector, + perfCounterFunc: func() []string { + return []string{"TCPv4"} + }, }, { name: "terminal_services", + flags: nil, builder: newTerminalServicesCollector, - perfCounterNames: []string{ - "Terminal Services", - "Terminal Services Session", - "Remote Desktop Connection Broker Counterset", + perfCounterFunc: func() []string { + return []string{ + "Terminal Services", + "Terminal Services Session", + "Remote Desktop Connection Broker Counterset", + } }, }, { - name: "textfile", - builder: newTextFileCollector, - perfCounterNames: nil, + name: "textfile", + flags: newTextFileCollectorFlags, + builder: newTextFileCollector, + perfCounterFunc: nil, }, { - name: "thermalzone", - builder: newThermalZoneCollector, - perfCounterNames: nil, + name: "thermalzone", + flags: nil, + builder: newThermalZoneCollector, + perfCounterFunc: nil, }, { - name: "time", - builder: newTimeCollector, - perfCounterNames: []string{"Windows Time Service"}, + name: "time", + flags: nil, + builder: newTimeCollector, + perfCounterFunc: func() []string { + return []string{"Windows Time Service"} + }, }, { - name: "vmware", - builder: newVmwareCollector, - perfCounterNames: nil, + name: "vmware", + flags: nil, + builder: newVmwareCollector, + perfCounterFunc: nil, }, { - name: "vmware_blast", - builder: newVmwareBlastCollector, - perfCounterNames: nil, + name: "vmware_blast", + flags: nil, + builder: newVmwareBlastCollector, + perfCounterFunc: nil, }, } -// To be called by the exporter for collector initialisation -func RegisterCollectors() { +// RegisterCollectorsFlags To be called by the exporter for collector initialisation before running app.Parse +func RegisterCollectorsFlags(app *kingpin.Application) { for _, v := range collectors { - registerCollector(v.name, v.builder, v.perfCounterNames...) + if v.flags != nil { + v.flags(app) + } + } +} + +// RegisterCollectors To be called by the exporter for collector initialisation +func RegisterCollectors() { + for _, v := range collectors { + var perfCounterNames []string + + if v.perfCounterFunc != nil { + perfCounterNames = v.perfCounterFunc() + } + + registerCollector(v.name, v.builder, perfCounterNames...) } } diff --git a/collector/logical_disk.go b/collector/logical_disk.go index 7ecdd06b..342afc65 100644 --- a/collector/logical_disk.go +++ b/collector/logical_disk.go @@ -12,15 +12,14 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +const ( + FlagLogicalDiskVolumeBlacklist = "collector.logical_disk.volume-blacklist" + FlagLogicalDiskVolumeWhitelist = "collector.logical_disk.volume-whitelist" +) + var ( - volumeWhitelist = kingpin.Flag( - "collector.logical_disk.volume-whitelist", - "Regexp of volumes to whitelist. Volume name must both match whitelist and not match blacklist to be included.", - ).Default(".+").String() - volumeBlacklist = kingpin.Flag( - "collector.logical_disk.volume-blacklist", - "Regexp of volumes to blacklist. Volume name must both match whitelist and not match blacklist to be included.", - ).Default("").String() + volumeWhitelist *string + volumeBlacklist *string ) // A LogicalDiskCollector is a Prometheus collector for perflib logicalDisk metrics @@ -46,6 +45,18 @@ type LogicalDiskCollector struct { volumeBlacklistPattern *regexp.Regexp } +// newLogicalDiskCollectorFlags ... +func newLogicalDiskCollectorFlags(app *kingpin.Application) { + volumeWhitelist = app.Flag( + FlagLogicalDiskVolumeWhitelist, + "Regexp of volumes to whitelist. Volume name must both match whitelist and not match blacklist to be included.", + ).Default(".+").String() + volumeBlacklist = app.Flag( + FlagLogicalDiskVolumeBlacklist, + "Regexp of volumes to blacklist. Volume name must both match whitelist and not match blacklist to be included.", + ).Default("").String() +} + // newLogicalDiskCollector ... func newLogicalDiskCollector() (Collector, error) { const subsystem = "logical_disk" diff --git a/collector/msmq.go b/collector/msmq.go index fdbc9799..aca01a1a 100644 --- a/collector/msmq.go +++ b/collector/msmq.go @@ -12,8 +12,12 @@ import ( "github.com/yusufpapurcu/wmi" ) +const ( + FlagMsmqWhereClause = "collector.msmq.msmq-where" +) + var ( - msmqWhereClause = kingpin.Flag("collector.msmq.msmq-where", "WQL 'where' clause to use in WMI metrics query. Limits the response to the msmqs you specify and reduces the size of the response.").String() + msmqWhereClause *string ) // A Win32_PerfRawData_MSMQ_MSMQQueueCollector is a Prometheus collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics @@ -26,6 +30,11 @@ type Win32_PerfRawData_MSMQ_MSMQQueueCollector struct { queryWhereClause string } +// newMSMQCollectorFlags .. +func newMSMQCollectorFlags(app *kingpin.Application) { + msmqWhereClause = app.Flag(FlagMsmqWhereClause, "WQL 'where' clause to use in WMI metrics query. Limits the response to the msmqs you specify and reduces the size of the response.").String() +} + // NewWin32_PerfRawData_MSMQ_MSMQQueueCollector ... func newMSMQCollector() (Collector, error) { const subsystem = "msmq" diff --git a/collector/mssql.go b/collector/mssql.go index e86721ea..2a7de75c 100644 --- a/collector/mssql.go +++ b/collector/mssql.go @@ -17,16 +17,15 @@ import ( "golang.org/x/sys/windows/registry" ) -var ( - mssqlEnabledCollectors = kingpin.Flag( - "collectors.mssql.classes-enabled", - "Comma-separated list of mssql WMI classes to use."). - Default(mssqlAvailableClassCollectors()).String() +const ( + FlagMssqlEnabledCollectors = "collectors.mssql.classes-enabled" + FlagMssqlPrintCollectors = "collectors.mssql.class-print" +) - mssqlPrintCollectors = kingpin.Flag( - "collectors.mssql.class-print", - "If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.", - ).Bool() +var ( + mssqlEnabledCollectors *string + + mssqlPrintCollectors *bool ) type mssqlInstancesType map[string]string @@ -401,6 +400,19 @@ type MSSQLCollector struct { mssqlChildCollectorFailure int } +// newMSSQLCollectorFlags ... +func newMSSQLCollectorFlags(app *kingpin.Application) { + mssqlEnabledCollectors = app.Flag( + FlagMssqlEnabledCollectors, + "Comma-separated list of mssql WMI classes to use."). + Default(mssqlAvailableClassCollectors()).String() + + mssqlPrintCollectors = app.Flag( + FlagMssqlPrintCollectors, + "If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.", + ).Bool() +} + // newMSSQLCollector ... func newMSSQLCollector() (Collector, error) { diff --git a/collector/net.go b/collector/net.go index 6c3e65d9..b1652aed 100644 --- a/collector/net.go +++ b/collector/net.go @@ -12,15 +12,14 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +const ( + FlagNicBlacklist = "collector.net.nic-blacklist" + FlagNicWhitelist = "collector.net.nic-whitelist" +) + var ( - nicWhitelist = kingpin.Flag( - "collector.net.nic-whitelist", - "Regexp of NIC:s to whitelist. NIC name must both match whitelist and not match blacklist to be included.", - ).Default(".+").String() - nicBlacklist = kingpin.Flag( - "collector.net.nic-blacklist", - "Regexp of NIC:s to blacklist. NIC name must both match whitelist and not match blacklist to be included.", - ).Default("").String() + nicWhitelist *string + nicBlacklist *string nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]") ) @@ -44,6 +43,18 @@ type NetworkCollector struct { nicBlacklistPattern *regexp.Regexp } +// newNetworkCollectorFlags ... +func newNetworkCollectorFlags(app *kingpin.Application) { + nicWhitelist = app.Flag( + FlagNicWhitelist, + "Regexp of NIC:s to whitelist. NIC name must both match whitelist and not match blacklist to be included.", + ).Default(".+").String() + nicBlacklist = app.Flag( + FlagNicBlacklist, + "Regexp of NIC:s to blacklist. NIC name must both match whitelist and not match blacklist to be included.", + ).Default("").String() +} + // newNetworkCollector ... func newNetworkCollector() (Collector, error) { const subsystem = "net" diff --git a/collector/process.go b/collector/process.go index 5854accf..76d7f950 100644 --- a/collector/process.go +++ b/collector/process.go @@ -15,15 +15,14 @@ import ( "github.com/yusufpapurcu/wmi" ) +const ( + FlagProcessBlacklist = "collector.process.blacklist" + FlagProcessWhitelist = "collector.process.whitelist" +) + var ( - processWhitelist = kingpin.Flag( - "collector.process.whitelist", - "Regexp of processes to include. Process name must both match whitelist and not match blacklist to be included.", - ).Default(".*").String() - processBlacklist = kingpin.Flag( - "collector.process.blacklist", - "Regexp of processes to exclude. Process name must both match whitelist and not match blacklist to be included.", - ).Default("").String() + processWhitelist *string + processBlacklist *string ) type processCollector struct { @@ -47,6 +46,18 @@ type processCollector struct { processBlacklistPattern *regexp.Regexp } +// newProcessCollectorFlags ... +func newProcessCollectorFlags(app *kingpin.Application) { + processWhitelist = app.Flag( + FlagProcessWhitelist, + "Regexp of processes to include. Process name must both match whitelist and not match blacklist to be included.", + ).Default(".*").String() + processBlacklist = app.Flag( + FlagProcessBlacklist, + "Regexp of processes to exclude. Process name must both match whitelist and not match blacklist to be included.", + ).Default("").String() +} + // NewProcessCollector ... func newProcessCollector() (Collector, error) { const subsystem = "process" diff --git a/collector/scheduled_task.go b/collector/scheduled_task.go index a26bac85..4dd8d13a 100644 --- a/collector/scheduled_task.go +++ b/collector/scheduled_task.go @@ -16,15 +16,14 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +const ( + FlagScheduledTaskBlacklist = "collector.scheduled_task.blacklist" + FlagScheduledTaskWhitelist = "collector.scheduled_task.whitelist" +) + var ( - taskWhitelist = kingpin.Flag( - "collector.scheduled_task.whitelist", - "Regexp of tasks to whitelist. Task path must both match whitelist and not match blacklist to be included.", - ).Default(".+").String() - taskBlacklist = kingpin.Flag( - "collector.scheduled_task.blacklist", - "Regexp of tasks to blacklist. Task path must both match whitelist and not match blacklist to be included.", - ).String() + taskWhitelist *string + taskBlacklist *string ) type ScheduledTaskCollector struct { @@ -63,6 +62,18 @@ type ScheduledTask struct { type ScheduledTasks []ScheduledTask +// newScheduledTask ... +func newScheduledTaskFlags(app *kingpin.Application) { + taskWhitelist = app.Flag( + FlagScheduledTaskWhitelist, + "Regexp of tasks to whitelist. Task path must both match whitelist and not match blacklist to be included.", + ).Default(".+").String() + taskBlacklist = app.Flag( + FlagScheduledTaskBlacklist, + "Regexp of tasks to blacklist. Task path must both match whitelist and not match blacklist to be included.", + ).String() +} + // newScheduledTask ... func newScheduledTask() (Collector, error) { const subsystem = "scheduled_task" diff --git a/collector/service.go b/collector/service.go index fc54bf9c..2a023229 100644 --- a/collector/service.go +++ b/collector/service.go @@ -16,15 +16,14 @@ import ( "golang.org/x/sys/windows/svc/mgr" ) +const ( + FlagServiceWhereClause = "collector.service.services-where" + FlagServiceUseAPI = "collector.service.use-api" +) + var ( - serviceWhereClause = kingpin.Flag( - "collector.service.services-where", - "WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.", - ).Default("").String() - useAPI = kingpin.Flag( - "collector.service.use-api", - "Use API calls to collect service data instead of WMI. Flag 'collector.service.services-where' won't be effective.", - ).Default("false").Bool() + serviceWhereClause *string + useAPI *bool ) // A serviceCollector is a Prometheus collector for WMI Win32_Service metrics @@ -37,6 +36,18 @@ type serviceCollector struct { queryWhereClause string } +// newServiceCollectorFlags ... +func newServiceCollectorFlags(app *kingpin.Application) { + serviceWhereClause = app.Flag( + FlagServiceWhereClause, + "WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.", + ).Default("").String() + useAPI = app.Flag( + FlagServiceUseAPI, + "Use API calls to collect service data instead of WMI. Flag 'collector.service.services-where' won't be effective.", + ).Default("false").Bool() +} + // newserviceCollector ... func newserviceCollector() (Collector, error) { const subsystem = "service" diff --git a/collector/smtp.go b/collector/smtp.go index 1dc5b5c8..d4d9f796 100644 --- a/collector/smtp.go +++ b/collector/smtp.go @@ -11,9 +11,14 @@ import ( "regexp" ) +const ( + FlagSmtpServerBlacklist = "collector.smtp.server-blacklist" + FlagSmtpServerWhitelist = "collector.smtp.server-whitelist" +) + var ( - serverWhitelist = kingpin.Flag("collector.smtp.server-whitelist", "Regexp of virtual servers to whitelist. Server name must both match whitelist and not match blacklist to be included.").Default(".+").String() - serverBlacklist = kingpin.Flag("collector.smtp.server-blacklist", "Regexp of virtual servers to blacklist. Server name must both match whitelist and not match blacklist to be included.").String() + serverWhitelist *string + serverBlacklist *string ) type SMTPCollector struct { @@ -64,6 +69,11 @@ type SMTPCollector struct { serverBlacklistPattern *regexp.Regexp } +func newSMTPCollectorFlags(app *kingpin.Application) { + serverWhitelist = app.Flag(FlagSmtpServerWhitelist, "Regexp of virtual servers to whitelist. Server name must both match whitelist and not match blacklist to be included.").Default(".+").String() + serverBlacklist = app.Flag(FlagSmtpServerBlacklist, "Regexp of virtual servers to blacklist. Server name must both match whitelist and not match blacklist to be included.").String() +} + func newSMTPCollector() (Collector, error) { log.Info("smtp collector is in an experimental state! Metrics for this collector have not been tested.") const subsystem = "smtp" diff --git a/collector/textfile.go b/collector/textfile.go index 75f78067..fb47644a 100644 --- a/collector/textfile.go +++ b/collector/textfile.go @@ -35,11 +35,12 @@ import ( "github.com/prometheus/common/expfmt" ) +const ( + FlagTextFileDirectory = "collector.textfile.directory" +) + var ( - textFileDirectory = kingpin.Flag( - "collector.textfile.directory", - "Directory to read text files with metrics from.", - ).Default(getDefaultPath()).String() + textFileDirectory *string mtimeDesc = prometheus.NewDesc( prometheus.BuildFQName(Namespace, "textfile", "mtime_seconds"), @@ -55,6 +56,14 @@ type textFileCollector struct { mtime *float64 } +// newTextFileCollectorFlags ... +func newTextFileCollectorFlags(app *kingpin.Application) { + textFileDirectory = app.Flag( + FlagTextFileDirectory, + "Directory to read text files with metrics from.", + ).Default(getDefaultPath()).String() +} + // newTextFileCollector returns a new Collector exposing metrics read from files // in the given textfile directory. func newTextFileCollector() (Collector, error) { diff --git a/exporter.go b/exporter.go index bd029074..49cacd54 100644 --- a/exporter.go +++ b/exporter.go @@ -259,51 +259,55 @@ func initWbem() { } func main() { + app := kingpin.New("windows_exporter", "A metrics collector for Windows.") var ( - configFile = kingpin.Flag( + configFile = app.Flag( "config.file", "YAML configuration file to use. Values set in this file will be overridden by CLI flags.", ).String() - webConfig = webflag.AddFlags(kingpin.CommandLine, ":9182") - metricsPath = kingpin.Flag( + webConfig = webflag.AddFlags(app, ":9182") + metricsPath = app.Flag( "telemetry.path", "URL path for surfacing collected metrics.", ).Default("/metrics").String() - disableExporterMetrics = kingpin.Flag( + disableExporterMetrics = app.Flag( "web.disable-exporter-metrics", "Exclude metrics about the exporter itself (promhttp_*, process_*, go_*).", ).Bool() - maxRequests = kingpin.Flag( + maxRequests = app.Flag( "telemetry.max-requests", "Maximum number of concurrent requests. 0 to disable.", ).Default("5").Int() - enabledCollectors = kingpin.Flag( + enabledCollectors = app.Flag( "collectors.enabled", "Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default."). Default(defaultCollectors).String() - printCollectors = kingpin.Flag( + printCollectors = app.Flag( "collectors.print", "If true, print available collectors and exit.", ).Bool() - timeoutMargin = kingpin.Flag( + timeoutMargin = app.Flag( "scrape.timeout-margin", "Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads.", ).Default("0.5").Float64() ) - log.AddFlags(kingpin.CommandLine) - kingpin.Version(version.Print("windows_exporter")) - kingpin.HelpFlag.Short('h') + log.AddFlags(app) + app.Version(version.Print("windows_exporter")) + app.HelpFlag.Short('h') + + // Initialize collectors before loading and parsing CLI arguments + collector.RegisterCollectorsFlags(app) // Load values from configuration file(s). Executable flags must first be parsed, in order // to load the specified file(s). - kingpin.Parse() + kingpin.MustParse(app.Parse(os.Args[1:])) log.Debug("Logging has Started") if *configFile != "" { resolver, err := config.NewResolver(*configFile) if err != nil { log.Fatalf("could not load config file: %v\n", err) } - err = resolver.Bind(kingpin.CommandLine, os.Args[1:]) + err = resolver.Bind(app, os.Args[1:]) if err != nil { log.Fatalf("%v\n", err) } @@ -314,7 +318,7 @@ func main() { *webConfig.WebListenAddresses = (*webConfig.WebListenAddresses)[1:] // Parse flags once more to include those discovered in configuration file(s). - kingpin.Parse() + kingpin.MustParse(app.Parse(os.Args[1:])) } if *printCollectors {