From dd956c986be851df4f807b0feeb73219fa9d3d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sun, 11 Aug 2024 13:28:39 +0200 Subject: [PATCH] chore: Refactor Config Collector API (#1558) --- .github/workflows/release.yml | 2 +- exporter.go | 18 +- pkg/collector/ad/ad.go | 12 +- pkg/collector/adcs/adcs.go | 12 +- pkg/collector/adfs/adfs.go | 12 +- pkg/collector/cache/cache.go | 12 +- pkg/collector/container/container.go | 12 +- pkg/collector/cpu/cpu.go | 12 +- pkg/collector/cpu_info/cpu_info.go | 12 +- pkg/collector/cs/cs.go | 12 +- pkg/collector/dfsr/dfsr.go | 44 ++-- pkg/collector/dhcp/dhcp.go | 12 +- pkg/collector/diskdrive/diskdrive.go | 12 +- pkg/collector/dns/dns.go | 12 +- pkg/collector/exchange/exchange.go | 117 +++++---- pkg/collector/fsrmquota/fsrmquota.go | 12 +- pkg/collector/hyperv/hyperv.go | 12 +- pkg/collector/iis/iis.go | 228 +++++++++--------- pkg/collector/license/license.go | 12 +- pkg/collector/logical_disk/logical_disk.go | 80 +++--- pkg/collector/logon/logon.go | 12 +- pkg/collector/memory/memory.go | 12 +- .../mscluster_cluster/mscluster_cluster.go | 12 +- .../mscluster_network/mscluster_network.go | 12 +- .../mscluster_node/mscluster_node.go | 12 +- .../mscluster_resource/mscluster_resource.go | 12 +- .../mscluster_resourcegroup.go | 12 +- pkg/collector/msmq/msmq.go | 54 +++-- pkg/collector/mssql/mssql.go | 106 +++++--- pkg/collector/net/net.go | 82 ++++--- .../netframework_clrexceptions.go | 12 +- .../netframework_clrinterop.go | 12 +- .../netframework_clrjit.go | 12 +- .../netframework_clrloading.go | 12 +- .../netframework_clrlocksandthreads.go | 12 +- .../netframework_clrmemory.go | 12 +- .../netframework_clrremoting.go | 12 +- .../netframework_clrsecurity.go | 12 +- pkg/collector/nps/nps.go | 12 +- pkg/collector/os/os.go | 12 +- pkg/collector/physical_disk/physical_disk.go | 85 +++---- pkg/collector/printer/printer.go | 106 +++++--- pkg/collector/process/process.go | 146 +++++------ pkg/collector/remote_fx/remote_fx.go | 12 +- .../scheduled_task/scheduled_task.go | 90 +++---- pkg/collector/service/service.go | 2 +- pkg/collector/smb/smb.go | 79 +----- pkg/collector/smbclient/smbclient.go | 79 +----- pkg/collector/smtp/smtp.go | 82 ++++--- pkg/collector/system/system.go | 12 +- pkg/collector/tcp/tcp.go | 12 +- .../teradici_pcoip/teradici_pcoip.go | 12 +- .../terminal_services/terminal_services.go | 12 +- pkg/collector/textfile/textfile.go | 66 ++--- pkg/collector/textfile/textfile_test_test.go | 18 +- pkg/collector/thermalzone/thermalzone.go | 12 +- pkg/collector/time/time.go | 12 +- pkg/collector/vmware/vmware.go | 12 +- pkg/collector/vmware_blast/vmware_blast.go | 12 +- pkg/types/regexp.go | 8 + pkg/utils/utils.go | 4 + pkg/wmi/wmi.go | 1 + 62 files changed, 1186 insertions(+), 791 deletions(-) create mode 100644 pkg/types/regexp.go diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 65f9fced..9f07f01a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -77,7 +77,7 @@ jobs: run: | $ErrorActionPreference = "Stop" - $Version = git describe --tag + $Version = git describe --tags --always $Version = $Version -replace 'v', '' # '+' symbols are invalid characters in image tags $Version = $Version -replace '\+', '_' diff --git a/exporter.go b/exporter.go index 261e1f10..e4ffc247 100644 --- a/exporter.go +++ b/exporter.go @@ -38,9 +38,6 @@ import ( "golang.org/x/sys/windows" ) -// https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights -const PROCESS_ALL_ACCESS = windows.STANDARD_RIGHTS_REQUIRED | windows.SYNCHRONIZE | windows.SPECIFIC_RIGHTS_ALL - // Same struct prometheus uses for their /version endpoint. // Separate copy to avoid pulling all of prometheus as a dependency. type prometheusVersion struct { @@ -63,18 +60,23 @@ var priorityStringToInt = map[string]uint32{ } func setPriorityWindows(pid int, priority uint32) error { - handle, err := windows.OpenProcess(PROCESS_ALL_ACCESS, false, uint32(pid)) + // https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights + handle, err := windows.OpenProcess( + windows.STANDARD_RIGHTS_REQUIRED|windows.SYNCHRONIZE|windows.SPECIFIC_RIGHTS_ALL, + false, uint32(pid), + ) if err != nil { return err } - //nolint:errcheck - defer windows.CloseHandle(handle) // Technically this can fail, but we ignore it - err = windows.SetPriorityClass(handle, priority) - if err != nil { + if err = windows.SetPriorityClass(handle, priority); err != nil { return err } + if err = windows.CloseHandle(handle); err != nil { + return fmt.Errorf("failed to close handle: %w", err) + } + return nil } diff --git a/pkg/collector/ad/ad.go b/pkg/collector/ad/ad.go index 9088bc39..3e0de9f1 100644 --- a/pkg/collector/ad/ad.go +++ b/pkg/collector/ad/ad.go @@ -21,6 +21,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics. type Collector struct { + config Config logger log.Logger addressBookClientSessions *prometheus.Desc @@ -87,8 +88,15 @@ type Collector struct { tombstonesObjectsVisitedTotal *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/adcs/adcs.go b/pkg/collector/adcs/adcs.go index 080bd161..f91f86fc 100644 --- a/pkg/collector/adcs/adcs.go +++ b/pkg/collector/adcs/adcs.go @@ -22,6 +22,7 @@ type Config struct{} var ConfigDefaults = Config{} type Collector struct { + config Config logger log.Logger challengeResponseProcessingTime *prometheus.Desc @@ -39,8 +40,15 @@ type Collector struct { signedCertificateTimestampListsPerSecond *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/adfs/adfs.go b/pkg/collector/adfs/adfs.go index 8b850060..e50fbef7 100644 --- a/pkg/collector/adfs/adfs.go +++ b/pkg/collector/adfs/adfs.go @@ -19,6 +19,7 @@ type Config struct{} var ConfigDefaults = Config{} type Collector struct { + config Config logger log.Logger adLoginConnectionFailures *prometheus.Desc @@ -66,8 +67,15 @@ type Collector struct { wstrustTokenRequests *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/cache/cache.go b/pkg/collector/cache/cache.go index d8ab69da..5c1b9d25 100644 --- a/pkg/collector/cache/cache.go +++ b/pkg/collector/cache/cache.go @@ -20,6 +20,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for Perflib Cache metrics. type Collector struct { + config Config logger log.Logger asyncCopyReadsTotal *prometheus.Desc @@ -53,8 +54,15 @@ type Collector struct { syncPinReadsTotal *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/container/container.go b/pkg/collector/container/container.go index 0a0ace07..27f1c1c8 100644 --- a/pkg/collector/container/container.go +++ b/pkg/collector/container/container.go @@ -22,6 +22,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for containers metrics. type Collector struct { + config Config logger log.Logger // Presence @@ -56,8 +57,15 @@ type Collector struct { } // New constructs a new Collector. -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/cpu/cpu.go b/pkg/collector/cpu/cpu.go index bc8179a2..fa50d5c4 100644 --- a/pkg/collector/cpu/cpu.go +++ b/pkg/collector/cpu/cpu.go @@ -20,6 +20,7 @@ type Config struct{} var ConfigDefaults = Config{} type Collector struct { + config Config logger log.Logger cStateSecondsTotal *prometheus.Desc @@ -37,8 +38,15 @@ type Collector struct { processorPrivilegedUtility *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/cpu_info/cpu_info.go b/pkg/collector/cpu_info/cpu_info.go index ecfde90d..815f0e78 100644 --- a/pkg/collector/cpu_info/cpu_info.go +++ b/pkg/collector/cpu_info/cpu_info.go @@ -27,13 +27,21 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for a few WMI metrics in Win32_Processor. type Collector struct { + config Config logger log.Logger cpuInfo *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/cs/cs.go b/pkg/collector/cs/cs.go index efb188f0..fba90765 100644 --- a/pkg/collector/cs/cs.go +++ b/pkg/collector/cs/cs.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI metrics. type Collector struct { + config Config logger log.Logger physicalMemoryBytes *prometheus.Desc @@ -26,8 +27,15 @@ type Collector struct { hostname *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/dfsr/dfsr.go b/pkg/collector/dfsr/dfsr.go index 703f0f52..df7af73e 100644 --- a/pkg/collector/dfsr/dfsr.go +++ b/pkg/collector/dfsr/dfsr.go @@ -3,31 +3,32 @@ package dfsr import ( + "slices" + "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/types" - "github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus/client_golang/prometheus" ) const Name = "dfsr" type Config struct { - EnabledCollectors string `yaml:"enabled_collectors"` + CollectorsEnabled []string `yaml:"collectors_enabled"` } var ConfigDefaults = Config{ - EnabledCollectors: "connection,folder,volume", + CollectorsEnabled: []string{"connection", "folder", "volume"}, } // Collector contains the metric and state data of the DFSR collectors. type Collector struct { + config Config logger log.Logger - dfsrEnabledCollectors *string - // connection source connectionBandwidthSavingsUsingDFSReplicationTotal *prometheus.Desc connectionBytesReceivedTotal *prometheus.Desc @@ -102,21 +103,29 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - c := &Collector{ - dfsrEnabledCollectors: &config.EnabledCollectors, + if config.CollectorsEnabled == nil { + config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c } func NewWithFlags(app *kingpin.Application) *Collector { - return &Collector{ - dfsrEnabledCollectors: app. - Flag("collectors.dfsr.sources-enabled", "Comma-separated list of DFSR Perflib sources to use."). - Default(ConfigDefaults.EnabledCollectors). - String(), + c := &Collector{ + config: ConfigDefaults, } + c.config.CollectorsEnabled = make([]string, 0) + + app.Flag("collectors.dfsr.sources-enabled", "Comma-separated list of DFSR Perflib sources to use."). + Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringsVar(&c.config.CollectorsEnabled) + + return c } func (c *Collector) GetName() string { @@ -129,8 +138,9 @@ func (c *Collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter() ([]string, error) { // Perflib sources are dynamic, depending on the enabled child collectors - expandedChildCollectors := utils.ExpandEnabledChildCollectors(*c.dfsrEnabledCollectors) + expandedChildCollectors := slices.Compact(c.config.CollectorsEnabled) perflibDependencies := make([]string, 0, len(expandedChildCollectors)) + for _, source := range expandedChildCollectors { perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source)) } @@ -209,8 +219,8 @@ func (c *Collector) Build() error { nil, ) - c. // folder - folderBandwidthSavingsUsingDFSReplicationTotal = prometheus.NewDesc( + // folder + c.folderBandwidthSavingsUsingDFSReplicationTotal = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "folder_bandwidth_savings_using_dfs_replication_bytes_total"), "Total bytes of bandwidth saved using DFS Replication for this folder", []string{"name"}, @@ -435,7 +445,9 @@ func (c *Collector) Build() error { nil, ) - c.dfsrChildCollectors = c.getDFSRChildCollectors(utils.ExpandEnabledChildCollectors(*c.dfsrEnabledCollectors)) + // Perflib sources are dynamic, depending on the enabled child collectors + expandedChildCollectors := slices.Compact(c.config.CollectorsEnabled) + c.dfsrChildCollectors = c.getDFSRChildCollectors(expandedChildCollectors) return nil } diff --git a/pkg/collector/dhcp/dhcp.go b/pkg/collector/dhcp/dhcp.go index ee8cf3ba..d181ccb0 100644 --- a/pkg/collector/dhcp/dhcp.go +++ b/pkg/collector/dhcp/dhcp.go @@ -18,6 +18,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector perflib DHCP metrics. type Collector struct { + config Config logger log.Logger acksTotal *prometheus.Desc @@ -47,8 +48,15 @@ type Collector struct { requestsTotal *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/diskdrive/diskdrive.go b/pkg/collector/diskdrive/diskdrive.go index eb2724ac..bfc89b2a 100644 --- a/pkg/collector/diskdrive/diskdrive.go +++ b/pkg/collector/diskdrive/diskdrive.go @@ -25,6 +25,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive. type Collector struct { + config Config logger log.Logger availability *prometheus.Desc @@ -34,8 +35,15 @@ type Collector struct { status *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/dns/dns.go b/pkg/collector/dns/dns.go index 131a6a47..acd72a8c 100644 --- a/pkg/collector/dns/dns.go +++ b/pkg/collector/dns/dns.go @@ -21,6 +21,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics. type Collector struct { + config Config logger log.Logger dynamicUpdatesFailures *prometheus.Desc @@ -47,8 +48,15 @@ type Collector struct { zoneTransferSuccessSent *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/exchange/exchange.go b/pkg/collector/exchange/exchange.go index f92aa876..01330bad 100644 --- a/pkg/collector/exchange/exchange.go +++ b/pkg/collector/exchange/exchange.go @@ -13,26 +13,23 @@ import ( "github.com/go-kit/log/level" "github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/types" - "github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus/client_golang/prometheus" ) const Name = "exchange" type Config struct { - CollectorsEnabled string `yaml:"collectors_enabled"` + CollectorsEnabled []string `yaml:"collectors_enabled"` } var ConfigDefaults = Config{ - CollectorsEnabled: "", + CollectorsEnabled: []string{}, } type Collector struct { + config Config logger log.Logger - exchangeListAllCollectors *bool - exchangeCollectorsEnabled *string - activeMailboxDeliveryQueueLength *prometheus.Desc activeSyncRequestsPerSec *prometheus.Desc activeTasks *prometheus.Desc @@ -94,28 +91,68 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - exchangeListAllCollectors := false - c := &Collector{ - exchangeCollectorsEnabled: &config.CollectorsEnabled, - exchangeListAllCollectors: &exchangeListAllCollectors, + if config.CollectorsEnabled == nil { + config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c } func NewWithFlags(app *kingpin.Application) *Collector { - return &Collector{ - exchangeListAllCollectors: app.Flag( - "collectors.exchange.list", - "List the collectors along with their perflib object name/ids", - ).Bool(), - - exchangeCollectorsEnabled: app.Flag( - "collectors.exchange.enabled", - "Comma-separated list of collectors to use. Defaults to all, if not specified.", - ).Default(ConfigDefaults.CollectorsEnabled).String(), + c := &Collector{ + config: ConfigDefaults, } + c.config.CollectorsEnabled = make([]string, 0) + + var listAllCollectors bool + + app.Flag( + "collectors.exchange.list", + "List the collectors along with their perflib object name/ids", + ).BoolVar(&listAllCollectors) + + app.Flag( + "collectors.exchange.enabled", + "Comma-separated list of collectors to use. Defaults to all, if not specified.", + ).Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringsVar(&c.config.CollectorsEnabled) + + app.PreAction(func(*kingpin.ParseContext) error { + if listAllCollectors { + collectorDesc := map[string]string{ + "ADAccessProcesses": "[19108] MSExchange ADAccess Processes", + "TransportQueues": "[20524] MSExchangeTransport Queues", + "HttpProxy": "[36934] MSExchange HttpProxy", + "ActiveSync": "[25138] MSExchange ActiveSync", + "AvailabilityService": "[24914] MSExchange Availability Service", + "OutlookWebAccess": "[24618] MSExchange OWA", + "Autodiscover": "[29240] MSExchange Autodiscover", + "WorkloadManagement": "[19430] MSExchange WorkloadManagement Workloads", + "RpcClientAccess": "[29336] MSExchange RpcClientAccess", + "MapiHttpEmsmdb": "[26463] MSExchange MapiHttp Emsmdb", + } + + sb := strings.Builder{} + sb.WriteString(fmt.Sprintf("%-32s %-32s\n", "Collector Name", "[PerfID] Perflib Object")) + + for _, cname := range exchangeAllCollectorNames { + sb.WriteString(fmt.Sprintf("%-32s %-32s\n", cname, collectorDesc[cname])) + } + + app.UsageTemplate(sb.String()).Usage(nil) + + os.Exit(0) + } + + return nil + }) + + return c } func (c *Collector) GetName() string { @@ -195,40 +232,20 @@ func (c *Collector) Build() error { c.syncCommandsPerSec = desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder") c.activeUserCountMapiHttpEmsMDB = desc("mapihttp_emsmdb_active_user_count", "Number of unique outlook users that have shown some kind of activity in the last 2 minutes") - c.enabledCollectors = make([]string, 0, len(exchangeAllCollectorNames)) - - collectorDesc := map[string]string{ - "ADAccessProcesses": "[19108] MSExchange ADAccess Processes", - "TransportQueues": "[20524] MSExchangeTransport Queues", - "HttpProxy": "[36934] MSExchange HttpProxy", - "ActiveSync": "[25138] MSExchange ActiveSync", - "AvailabilityService": "[24914] MSExchange Availability Service", - "OutlookWebAccess": "[24618] MSExchange OWA", - "Autodiscover": "[29240] MSExchange Autodiscover", - "WorkloadManagement": "[19430] MSExchange WorkloadManagement Workloads", - "RpcClientAccess": "[29336] MSExchange RpcClientAccess", - "MapiHttpEmsmdb": "[26463] MSExchange MapiHttp Emsmdb", - } - - if *c.exchangeListAllCollectors { - fmt.Printf("%-32s %-32s\n", "Collector Name", "[PerfID] Perflib Object") //nolint:forbidigo - for _, cname := range exchangeAllCollectorNames { - fmt.Printf("%-32s %-32s\n", cname, collectorDesc[cname]) //nolint:forbidigo - } - - os.Exit(0) - } - - if utils.IsEmpty(c.exchangeCollectorsEnabled) { - c.enabledCollectors = append(c.enabledCollectors, exchangeAllCollectorNames...) + if len(c.config.CollectorsEnabled) == 0 { + c.enabledCollectors = exchangeAllCollectorNames } else { - for _, collectorName := range strings.Split(*c.exchangeCollectorsEnabled, ",") { - if slices.Contains(exchangeAllCollectorNames, collectorName) { - c.enabledCollectors = append(c.enabledCollectors, collectorName) - } else { + c.enabledCollectors = make([]string, 0, len(exchangeAllCollectorNames)) + + for _, collectorName := range c.config.CollectorsEnabled { + if !slices.Contains(exchangeAllCollectorNames, collectorName) { return fmt.Errorf("unknown exchange collector: %s", collectorName) } + + c.enabledCollectors = append(c.enabledCollectors, collectorName) } + + c.enabledCollectors = slices.Clip(c.enabledCollectors) } return nil diff --git a/pkg/collector/fsrmquota/fsrmquota.go b/pkg/collector/fsrmquota/fsrmquota.go index 2b7d634e..a8204c39 100644 --- a/pkg/collector/fsrmquota/fsrmquota.go +++ b/pkg/collector/fsrmquota/fsrmquota.go @@ -19,6 +19,7 @@ type Config struct{} var ConfigDefaults = Config{} type Collector struct { + config Config logger log.Logger quotasCount *prometheus.Desc @@ -33,8 +34,15 @@ type Collector struct { template *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/hyperv/hyperv.go b/pkg/collector/hyperv/hyperv.go index 62a41136..9e6aba98 100644 --- a/pkg/collector/hyperv/hyperv.go +++ b/pkg/collector/hyperv/hyperv.go @@ -22,6 +22,7 @@ var ConfigDefaults = Config{} // Collector is a Prometheus Collector for hyper-v. type Collector struct { + config Config logger log.Logger // Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary @@ -139,8 +140,15 @@ type Collector struct { vmMemoryRemovedMemory *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/iis/iis.go b/pkg/collector/iis/iis.go index 7b758ed7..bf0bc234 100644 --- a/pkg/collector/iis/iis.go +++ b/pkg/collector/iis/iis.go @@ -20,64 +20,23 @@ import ( const Name = "iis" type Config struct { - SiteInclude string `yaml:"site_include"` - SiteExclude string `yaml:"site_exclude"` - AppInclude string `yaml:"app_include"` - AppExclude string `yaml:"app_exclude"` + SiteInclude *regexp.Regexp `yaml:"site_include"` + SiteExclude *regexp.Regexp `yaml:"site_exclude"` + AppInclude *regexp.Regexp `yaml:"app_include"` + AppExclude *regexp.Regexp `yaml:"app_exclude"` } var ConfigDefaults = Config{ - SiteInclude: ".+", - SiteExclude: "", - AppInclude: ".+", - AppExclude: "", -} - -type simple_version struct { - major uint64 - minor uint64 -} - -func getIISVersion(logger log.Logger) simple_version { - k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\InetStp\`, registry.QUERY_VALUE) - if err != nil { - _ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err) - return simple_version{} - } - defer func() { - err = k.Close() - if err != nil { - _ = level.Warn(logger).Log("msg", "Failed to close registry key", "err", err) - } - }() - - major, _, err := k.GetIntegerValue("MajorVersion") - if err != nil { - _ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err) - return simple_version{} - } - minor, _, err := k.GetIntegerValue("MinorVersion") - if err != nil { - _ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err) - return simple_version{} - } - - _ = level.Debug(logger).Log("msg", fmt.Sprintf("Detected IIS %d.%d\n", major, minor)) - - return simple_version{ - major: major, - minor: minor, - } + SiteInclude: types.RegExpAny, + SiteExclude: types.RegExpEmpty, + AppInclude: types.RegExpAny, + AppExclude: types.RegExpEmpty, } type Collector struct { + config Config logger log.Logger - siteInclude *string - siteExclude *string - appInclude *string - appExclude *string - info *prometheus.Desc // Web Service @@ -104,9 +63,6 @@ type Collector struct { totalNotFoundErrors *prometheus.Desc totalRejectedAsyncIORequests *prometheus.Desc - siteIncludePattern *regexp.Regexp - siteExcludePattern *regexp.Regexp - // APP_POOL_WAS currentApplicationPoolState *prometheus.Desc currentApplicationPoolUptime *prometheus.Desc @@ -203,10 +159,7 @@ type Collector struct { serviceCacheOutputCacheFlushedItemsTotal *prometheus.Desc serviceCacheOutputCacheFlushesTotal *prometheus.Desc - appIncludePattern *regexp.Regexp - appExcludePattern *regexp.Regexp - - iisVersion simple_version + iisVersion simpleVersion } func New(logger log.Logger, config *Config) *Collector { @@ -214,11 +167,24 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } + if config.AppExclude == nil { + config.AppExclude = ConfigDefaults.AppExclude + } + + if config.AppInclude == nil { + config.AppInclude = ConfigDefaults.AppInclude + } + + if config.SiteExclude == nil { + config.SiteExclude = ConfigDefaults.SiteExclude + } + + if config.SiteInclude == nil { + config.SiteInclude = ConfigDefaults.SiteInclude + } + c := &Collector{ - appInclude: &config.AppInclude, - appExclude: &config.AppExclude, - siteInclude: &config.SiteInclude, - siteExclude: &config.SiteExclude, + config: *config, } c.SetLogger(logger) @@ -228,27 +194,57 @@ func New(logger log.Logger, config *Config) *Collector { func NewWithFlags(app *kingpin.Application) *Collector { c := &Collector{ - siteInclude: app.Flag( - "collector.iis.site-include", - "Regexp of sites to include. Site name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.SiteInclude).String(), - - siteExclude: app.Flag( - "collector.iis.site-exclude", - "Regexp of sites to exclude. Site name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.SiteExclude).String(), - - appInclude: app.Flag( - "collector.iis.app-include", - "Regexp of apps to include. App name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.AppInclude).String(), - - appExclude: app.Flag( - "collector.iis.app-exclude", - "Regexp of apps to exclude. App name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.AppExclude).String(), + config: ConfigDefaults, } + var appExclude, appInclude, siteExclude, siteInclude string + + app.Flag( + "collector.iis.app-exclude", + "Regexp of apps to exclude. App name must both match include and not match exclude to be included.", + ).Default(c.config.AppExclude.String()).StringVar(&appExclude) + + app.Flag( + "collector.iis.app-include", + "Regexp of apps to include. App name must both match include and not match exclude to be included.", + ).Default(c.config.AppInclude.String()).StringVar(&appInclude) + + app.Flag( + "collector.iis.site-exclude", + "Regexp of sites to exclude. Site name must both match include and not match exclude to be included.", + ).Default(c.config.SiteExclude.String()).StringVar(&siteExclude) + + app.Flag( + "collector.iis.site-include", + "Regexp of sites to include. Site name must both match include and not match exclude to be included.", + ).Default(c.config.SiteInclude.String()).StringVar(&siteInclude) + + app.Action(func(*kingpin.ParseContext) error { + var err error + + c.config.AppExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", appExclude)) + if err != nil { + return fmt.Errorf("collector.iis.app-exclude: %w", err) + } + + c.config.AppInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", appInclude)) + if err != nil { + return fmt.Errorf("collector.iis.app-include: %w", err) + } + + c.config.SiteExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", siteExclude)) + if err != nil { + return fmt.Errorf("collector.iis.site-exclude: %w", err) + } + + c.config.SiteInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", siteInclude)) + if err != nil { + return fmt.Errorf("collector.iis.site-include: %w", err) + } + + return nil + }) + return c } @@ -276,27 +272,6 @@ func (c *Collector) Close() error { func (c *Collector) Build() error { c.iisVersion = getIISVersion(c.logger) - var err error - c.siteIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.siteInclude)) - if err != nil { - return err - } - - c.siteExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.siteExclude)) - if err != nil { - return err - } - - c.appIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.appInclude)) - if err != nil { - return err - } - - c.appExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.appExclude)) - if err != nil { - return err - } - c.info = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "info"), "ISS information", @@ -918,6 +893,43 @@ func (c *Collector) Build() error { return nil } +type simpleVersion struct { + major uint64 + minor uint64 +} + +func getIISVersion(logger log.Logger) simpleVersion { + k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\InetStp\`, registry.QUERY_VALUE) + if err != nil { + _ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err) + return simpleVersion{} + } + defer func() { + err = k.Close() + if err != nil { + _ = level.Warn(logger).Log("msg", "Failed to close registry key", "err", err) + } + }() + + major, _, err := k.GetIntegerValue("MajorVersion") + if err != nil { + _ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err) + return simpleVersion{} + } + minor, _, err := k.GetIntegerValue("MinorVersion") + if err != nil { + _ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err) + return simpleVersion{} + } + + _ = level.Debug(logger).Log("msg", fmt.Sprintf("Detected IIS %d.%d\n", major, minor)) + + return simpleVersion{ + major: major, + minor: minor, + } +} + // Collect sends the metric values for each metric // to the provided prometheus Metric channel. func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { @@ -1049,7 +1061,7 @@ func (c *Collector) collectWebService(ctx *types.ScrapeContext, ch chan<- promet webServiceDeDuplicated := dedupIISNames(webService) for name, app := range webServiceDeDuplicated { - if name == "_Total" || c.siteExcludePattern.MatchString(name) || !c.siteIncludePattern.MatchString(name) { + if name == "_Total" || c.config.SiteExclude.MatchString(name) || !c.config.SiteInclude.MatchString(name) { continue } @@ -1336,8 +1348,8 @@ func (c *Collector) collectAPP_POOL_WAS(ctx *types.ScrapeContext, ch chan<- prom for name, app := range appPoolDeDuplicated { if name == "_Total" || - c.appExcludePattern.MatchString(name) || - !c.appIncludePattern.MatchString(name) { + c.config.AppExclude.MatchString(name) || + !c.config.AppInclude.MatchString(name) { continue } @@ -1516,8 +1528,8 @@ func (c *Collector) collectW3SVC_W3WP(ctx *types.ScrapeContext, ch chan<- promet pid := workerProcessNameExtractor.ReplaceAllString(w3Name, "$1") name := workerProcessNameExtractor.ReplaceAllString(w3Name, "$2") if name == "" || name == "_Total" || - c.appExcludePattern.MatchString(name) || - !c.appIncludePattern.MatchString(name) { + c.config.AppExclude.MatchString(name) || + !c.config.AppInclude.MatchString(name) { continue } @@ -1774,8 +1786,8 @@ func (c *Collector) collectW3SVC_W3WP(ctx *types.ScrapeContext, ch chan<- promet pid := workerProcessNameExtractor.ReplaceAllString(w3Name, "$1") name := workerProcessNameExtractor.ReplaceAllString(w3Name, "$2") if name == "" || name == "_Total" || - c.appExcludePattern.MatchString(name) || - !c.appIncludePattern.MatchString(name) { + c.config.AppExclude.MatchString(name) || + !c.config.AppInclude.MatchString(name) { continue } diff --git a/pkg/collector/license/license.go b/pkg/collector/license/license.go index 5441e452..eeff7053 100644 --- a/pkg/collector/license/license.go +++ b/pkg/collector/license/license.go @@ -27,13 +27,21 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics. type Collector struct { + config Config logger log.Logger licenseStatus *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/logical_disk/logical_disk.go b/pkg/collector/logical_disk/logical_disk.go index e48f0a91..4a8b3502 100644 --- a/pkg/collector/logical_disk/logical_disk.go +++ b/pkg/collector/logical_disk/logical_disk.go @@ -22,24 +22,20 @@ import ( const Name = "logical_disk" type Config struct { - VolumeInclude string `yaml:"volume_include"` - VolumeExclude string `yaml:"volume_exclude"` + VolumeInclude *regexp.Regexp `yaml:"volume_include"` + VolumeExclude *regexp.Regexp `yaml:"volume_exclude"` } var ConfigDefaults = Config{ - VolumeInclude: ".+", - VolumeExclude: "", + VolumeInclude: types.RegExpAny, + VolumeExclude: types.RegExpEmpty, } // A Collector is a Prometheus Collector for perflib logicalDisk metrics. type Collector struct { + config Config logger log.Logger - volumeInclude *string - volumeExclude *string - volumeIncludePattern *regexp.Regexp - volumeExcludePattern *regexp.Regexp - avgReadQueue *prometheus.Desc avgWriteQueue *prometheus.Desc freeSpace *prometheus.Desc @@ -73,10 +69,18 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - c := &Collector{ - volumeExclude: &config.VolumeExclude, - volumeInclude: &config.VolumeInclude, + if config.VolumeExclude == nil { + config.VolumeExclude = ConfigDefaults.VolumeExclude } + + if config.VolumeInclude == nil { + config.VolumeInclude = ConfigDefaults.VolumeInclude + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c @@ -84,16 +88,37 @@ func New(logger log.Logger, config *Config) *Collector { func NewWithFlags(app *kingpin.Application) *Collector { c := &Collector{ - volumeInclude: app.Flag( - "collector.logical_disk.volume-include", - "Regexp of volumes to include. Volume name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.VolumeInclude).String(), - volumeExclude: app.Flag( - "collector.logical_disk.volume-exclude", - "Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.VolumeExclude).String(), + config: ConfigDefaults, } + var volumeExclude, volumeInclude string + + app.Flag( + "collector.logical_disk.volume-exclude", + "Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.", + ).Default(c.config.VolumeExclude.String()).StringVar(&volumeExclude) + + app.Flag( + "collector.logical_disk.volume-include", + "Regexp of volumes to include. Volume name must both match include and not match exclude to be included.", + ).Default(c.config.VolumeInclude.String()).StringVar(&volumeInclude) + + app.Action(func(*kingpin.ParseContext) error { + var err error + + c.config.VolumeExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", volumeExclude)) + if err != nil { + return fmt.Errorf("collector.logical_disk.volume-exclude: %w", err) + } + + c.config.VolumeInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", volumeInclude)) + if err != nil { + return fmt.Errorf("collector.logical_disk.volume-include: %w", err) + } + + return nil + }) + return c } @@ -238,17 +263,6 @@ func (c *Collector) Build() error { nil, ) - var err error - c.volumeIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.volumeInclude)) - if err != nil { - return err - } - - c.volumeExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.volumeExclude)) - if err != nil { - return err - } - return nil } @@ -299,8 +313,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri for _, volume := range dst { if volume.Name == "_Total" || - c.volumeExcludePattern.MatchString(volume.Name) || - !c.volumeIncludePattern.MatchString(volume.Name) { + c.config.VolumeExclude.MatchString(volume.Name) || + !c.config.VolumeInclude.MatchString(volume.Name) { continue } diff --git a/pkg/collector/logon/logon.go b/pkg/collector/logon/logon.go index ecd4ea8f..fe361765 100644 --- a/pkg/collector/logon/logon.go +++ b/pkg/collector/logon/logon.go @@ -21,13 +21,21 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI metrics. type Collector struct { + config Config logger log.Logger logonType *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/memory/memory.go b/pkg/collector/memory/memory.go index 8feaeaee..33e3ff73 100644 --- a/pkg/collector/memory/memory.go +++ b/pkg/collector/memory/memory.go @@ -22,6 +22,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for perflib Memory metrics. type Collector struct { + config Config logger log.Logger availableBytes *prometheus.Desc @@ -58,8 +59,15 @@ type Collector struct { writeCopiesTotal *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/mscluster_cluster/mscluster_cluster.go b/pkg/collector/mscluster_cluster/mscluster_cluster.go index 45f53318..51901720 100644 --- a/pkg/collector/mscluster_cluster/mscluster_cluster.go +++ b/pkg/collector/mscluster_cluster/mscluster_cluster.go @@ -16,6 +16,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics. type Collector struct { + config Config logger log.Logger addEvictDelay *prometheus.Desc @@ -97,8 +98,15 @@ type Collector struct { witnessRestartInterval *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/mscluster_network/mscluster_network.go b/pkg/collector/mscluster_network/mscluster_network.go index d3593af8..b0726d9d 100644 --- a/pkg/collector/mscluster_network/mscluster_network.go +++ b/pkg/collector/mscluster_network/mscluster_network.go @@ -16,6 +16,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI MSCluster_Network metrics. type Collector struct { + config Config logger log.Logger characteristics *prometheus.Desc @@ -25,8 +26,15 @@ type Collector struct { state *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/mscluster_node/mscluster_node.go b/pkg/collector/mscluster_node/mscluster_node.go index 683e8079..b3a8a4ce 100644 --- a/pkg/collector/mscluster_node/mscluster_node.go +++ b/pkg/collector/mscluster_node/mscluster_node.go @@ -19,6 +19,7 @@ var NodeName []string // A Collector is a Prometheus Collector for WMI MSCluster_Node metrics. type Collector struct { + config Config logger log.Logger buildNumber *prometheus.Desc @@ -37,8 +38,15 @@ type Collector struct { statusInformation *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/mscluster_resource/mscluster_resource.go b/pkg/collector/mscluster_resource/mscluster_resource.go index 7871cc37..5f59a3f6 100644 --- a/pkg/collector/mscluster_resource/mscluster_resource.go +++ b/pkg/collector/mscluster_resource/mscluster_resource.go @@ -17,6 +17,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI MSCluster_Resource metrics. type Collector struct { + config Config logger log.Logger characteristics *prometheus.Desc @@ -38,8 +39,15 @@ type Collector struct { subclass *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/mscluster_resourcegroup/mscluster_resourcegroup.go b/pkg/collector/mscluster_resourcegroup/mscluster_resourcegroup.go index ffcb42c4..b1810e87 100644 --- a/pkg/collector/mscluster_resourcegroup/mscluster_resourcegroup.go +++ b/pkg/collector/mscluster_resourcegroup/mscluster_resourcegroup.go @@ -17,6 +17,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI MSCluster_ResourceGroup metrics. type Collector struct { + config Config logger log.Logger autoFailbackType *prometheus.Desc @@ -35,8 +36,15 @@ type Collector struct { state *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/msmq/msmq.go b/pkg/collector/msmq/msmq.go index 31a33b3c..66bbf722 100644 --- a/pkg/collector/msmq/msmq.go +++ b/pkg/collector/msmq/msmq.go @@ -17,19 +17,18 @@ import ( const Name = "msmq" type Config struct { - QueryWhereClause string `yaml:"query_where_clause"` + QueryWhereClause *string `yaml:"query_where_clause"` } var ConfigDefaults = Config{ - QueryWhereClause: "", + QueryWhereClause: utils.ToPTR(""), } // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics. type Collector struct { + config Config logger log.Logger - queryWhereClause *string - bytesInJournalQueue *prometheus.Desc bytesInQueue *prometheus.Desc messagesInJournalQueue *prometheus.Desc @@ -41,20 +40,29 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - c := &Collector{ - queryWhereClause: &config.QueryWhereClause, + if config.QueryWhereClause == nil { + config.QueryWhereClause = ConfigDefaults.QueryWhereClause } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c } func NewWithFlags(app *kingpin.Application) *Collector { - return &Collector{ - queryWhereClause: app. - 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."). - Default(ConfigDefaults.QueryWhereClause).String(), + c := &Collector{ + config: ConfigDefaults, } + + app.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."). + Default(*c.config.QueryWhereClause).StringVar(c.config.QueryWhereClause) + + return c } func (c *Collector) GetName() string { @@ -74,7 +82,7 @@ func (c *Collector) Close() error { } func (c *Collector) Build() error { - if utils.IsEmpty(c.queryWhereClause) { + if *c.config.QueryWhereClause == "" { _ = level.Warn(c.logger).Log("msg", "No where-clause specified for msmq collector. This will generate a very large number of metrics!") } @@ -115,18 +123,19 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) return nil } -type Win32_PerfRawData_MSMQ_MSMQQueue struct { +type msmqQueue struct { Name string - BytesinJournalQueue uint64 - BytesinQueue uint64 - MessagesinJournalQueue uint64 - MessagesinQueue uint64 + BytesInJournalQueue uint64 + BytesInQueue uint64 + MessagesInJournalQueue uint64 + MessagesInQueue uint64 } func (c *Collector) collect(ch chan<- prometheus.Metric) error { - var dst []Win32_PerfRawData_MSMQ_MSMQQueue - q := wmi.QueryAllWhere(&dst, *c.queryWhereClause, c.logger) + var dst []msmqQueue + + q := wmi.QueryAllForClassWhere(&dst, "Win32_PerfRawData_MSMQ_MSMQQueue", *c.config.QueryWhereClause, c.logger) if err := wmi.Query(q, &dst); err != nil { return err } @@ -135,30 +144,31 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error { ch <- prometheus.MustNewConstMetric( c.bytesInJournalQueue, prometheus.GaugeValue, - float64(msmq.BytesinJournalQueue), + float64(msmq.BytesInJournalQueue), strings.ToLower(msmq.Name), ) ch <- prometheus.MustNewConstMetric( c.bytesInQueue, prometheus.GaugeValue, - float64(msmq.BytesinQueue), + float64(msmq.BytesInQueue), strings.ToLower(msmq.Name), ) ch <- prometheus.MustNewConstMetric( c.messagesInJournalQueue, prometheus.GaugeValue, - float64(msmq.MessagesinJournalQueue), + float64(msmq.MessagesInJournalQueue), strings.ToLower(msmq.Name), ) ch <- prometheus.MustNewConstMetric( c.messagesInQueue, prometheus.GaugeValue, - float64(msmq.MessagesinQueue), + float64(msmq.MessagesInQueue), strings.ToLower(msmq.Name), ) } + return nil } diff --git a/pkg/collector/mssql/mssql.go b/pkg/collector/mssql/mssql.go index 6cdc3c46..8e5c7146 100644 --- a/pkg/collector/mssql/mssql.go +++ b/pkg/collector/mssql/mssql.go @@ -6,6 +6,8 @@ import ( "errors" "fmt" "os" + "slices" + "sort" "strings" "sync" "time" @@ -15,7 +17,6 @@ import ( "github.com/go-kit/log/level" "github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/types" - "github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus/client_golang/prometheus" "golang.org/x/sys/windows/registry" ) @@ -23,11 +24,24 @@ import ( const Name = "mssql" type Config struct { - EnabledCollectors string `yaml:"collectors_enabled"` //nolint:tagliatelle + CollectorsEnabled []string `yaml:"collectors_enabled"` } var ConfigDefaults = Config{ - EnabledCollectors: "accessmethods,availreplica,bufman,databases,dbreplica,genstats,locks,memmgr,sqlstats,sqlerrors,transactions,waitstats", + CollectorsEnabled: []string{ + "accessmethods", + "availreplica", + "bufman", + "databases", + "dbreplica", + "genstats", + "locks", + "memmgr", + "sqlstats", + "sqlerrors", + "transactions", + "waitstats", + }, } type mssqlInstancesType map[string]string @@ -39,8 +53,8 @@ func getMSSQLInstances(logger log.Logger) mssqlInstancesType { sqlDefaultInstance := make(mssqlInstancesType) sqlDefaultInstance["MSSQLSERVER"] = "" - regkey := `Software\Microsoft\Microsoft SQL Server\Instance Names\SQL` - k, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey, registry.QUERY_VALUE) + regKey := `Software\Microsoft\Microsoft SQL Server\Instance Names\SQL` + k, err := registry.OpenKey(registry.LOCAL_MACHINE, regKey, registry.QUERY_VALUE) if err != nil { _ = level.Warn(logger).Log("msg", "Couldn't open registry to determine SQL instances", "err", err) return sqlDefaultInstance @@ -128,11 +142,9 @@ func mssqlGetPerfObjectName(sqlInstance string, collector string) string { // A Collector is a Prometheus Collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics. type Collector struct { + config Config logger log.Logger - mssqlEnabledCollectors *string - mssqlPrintCollectors *bool - // meta mssqlScrapeDurationDesc *prometheus.Desc mssqlScrapeSuccessDesc *prometheus.Desc @@ -408,29 +420,55 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - printCollectors := false + if config.CollectorsEnabled == nil { + config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled + } c := &Collector{ - mssqlEnabledCollectors: &config.EnabledCollectors, - mssqlPrintCollectors: &printCollectors, + config: *config, } + c.SetLogger(logger) return c } func NewWithFlags(app *kingpin.Application) *Collector { - return &Collector{ - mssqlEnabledCollectors: app.Flag( - "collectors.mssql.classes-enabled", - "Comma-separated list of mssql WMI classes to use."). - Default(ConfigDefaults.EnabledCollectors).String(), - - mssqlPrintCollectors: app.Flag( - "collectors.mssql.class-print", - "If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.", - ).Bool(), + c := &Collector{ + config: ConfigDefaults, } + c.config.CollectorsEnabled = make([]string, 0) + + var listAllCollectors bool + + app.Flag( + "collectors.mssql.class-print", + "If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.", + ).BoolVar(&listAllCollectors) + + app.Flag( + "collectors.mssql.classes-enabled", + "Comma-separated list of mssql WMI classes to use.", + ).Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringsVar(&c.config.CollectorsEnabled) + + app.PreAction(func(*kingpin.ParseContext) error { + if listAllCollectors { + sb := strings.Builder{} + sb.WriteString("Available SQLServer Classes:\n - ") + + for name := range c.mssqlCollectors { + sb.WriteString(fmt.Sprintf(" - %s\n", name)) + } + + app.UsageTemplate(sb.String()).Usage(nil) + + os.Exit(0) + } + + return nil + }) + + return c } func (c *Collector) GetName() string { @@ -442,9 +480,14 @@ func (c *Collector) SetLogger(logger log.Logger) { } func (c *Collector) GetPerfCounter() ([]string, error) { - enabled := utils.ExpandEnabledChildCollectors(*c.mssqlEnabledCollectors) + enabled := slices.Compact(c.config.CollectorsEnabled) + + // Result must order, to prevent test failures. + sort.Strings(enabled) + c.mssqlInstances = getMSSQLInstances(c.logger) perfCounters := make([]string, 0, len(c.mssqlInstances)*len(enabled)) + for instance := range c.mssqlInstances { for _, c := range enabled { perfCounters = append(perfCounters, mssqlGetPerfObjectName(instance, c)) @@ -1922,15 +1965,6 @@ func (c *Collector) Build() error { c.mssqlCollectors = c.getMSSQLCollectors() - if *c.mssqlPrintCollectors { - fmt.Printf("Available SQLServer Classes:\n") //nolint:forbidigo - for name := range c.mssqlCollectors { - fmt.Printf(" - %s\n", name) //nolint:forbidigo - } - - os.Exit(0) - } - return nil } @@ -1973,7 +2007,11 @@ func (c *Collector) execute(ctx *types.ScrapeContext, name string, fn mssqlColle func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { wg := sync.WaitGroup{} - enabled := utils.ExpandEnabledChildCollectors(*c.mssqlEnabledCollectors) + enabled := slices.Compact(c.config.CollectorsEnabled) + + // Result must order, to prevent test failures. + sort.Strings(enabled) + for sqlInstance := range c.mssqlInstances { for _, name := range enabled { function := c.mssqlCollectors[name] @@ -1982,12 +2020,14 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri go c.execute(ctx, name, function, ch, sqlInstance, &wg) } } + wg.Wait() - // this should return an error if any? some? children errord. + // this should return an error if any? some? children errored. if c.mssqlChildCollectorFailure > 0 { return errors.New("at least one child collector failed") } + return nil } diff --git a/pkg/collector/net/net.go b/pkg/collector/net/net.go index 19d5d811..7721deae 100644 --- a/pkg/collector/net/net.go +++ b/pkg/collector/net/net.go @@ -17,24 +17,22 @@ import ( const Name = "net" type Config struct { - NicInclude string `yaml:"nic_include"` - NicExclude string `yaml:"nic_exclude"` + NicExclude *regexp.Regexp `yaml:"nic_exclude"` + NicInclude *regexp.Regexp `yaml:"nic_include"` } var ConfigDefaults = Config{ - NicInclude: ".+", - NicExclude: "", + NicExclude: types.RegExpEmpty, + NicInclude: types.RegExpAny, } var nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]") // A Collector is a Prometheus Collector for Perflib Network Interface metrics. type Collector struct { + config Config logger log.Logger - nicInclude *string - nicExclude *string - bytesReceivedTotal *prometheus.Desc bytesSentTotal *prometheus.Desc bytesTotal *prometheus.Desc @@ -48,9 +46,6 @@ type Collector struct { packetsReceivedUnknown *prometheus.Desc packetsSentTotal *prometheus.Desc currentBandwidth *prometheus.Desc - - nicIncludePattern *regexp.Regexp - nicExcludePattern *regexp.Regexp } func New(logger log.Logger, config *Config) *Collector { @@ -58,10 +53,18 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - c := &Collector{ - nicExclude: &config.NicExclude, - nicInclude: &config.NicInclude, + if config.NicExclude == nil { + config.NicExclude = ConfigDefaults.NicExclude } + + if config.NicInclude == nil { + config.NicInclude = ConfigDefaults.NicInclude + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c @@ -69,17 +72,37 @@ func New(logger log.Logger, config *Config) *Collector { func NewWithFlags(app *kingpin.Application) *Collector { c := &Collector{ - nicInclude: app.Flag( - "collector.net.nic-include", - "Regexp of NIC:s to include. NIC name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.NicInclude).String(), - - nicExclude: app.Flag( - "collector.net.nic-exclude", - "Regexp of NIC:s to exclude. NIC name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.NicExclude).String(), + config: ConfigDefaults, } + var nicExclude, nicInclude string + + app.Flag( + "collector.net.nic-exclude", + "Regexp of NIC:s to exclude. NIC name must both match include and not match exclude to be included.", + ).Default(c.config.NicExclude.String()).StringVar(&nicExclude) + + app.Flag( + "collector.net.nic-include", + "Regexp of NIC:s to include. NIC name must both match include and not match exclude to be included.", + ).Default(c.config.NicInclude.String()).StringVar(&nicInclude) + + app.Action(func(*kingpin.ParseContext) error { + var err error + + c.config.NicExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", nicExclude)) + if err != nil { + return fmt.Errorf("collector.net.nic-exclude: %w", err) + } + + c.config.NicInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", nicInclude)) + if err != nil { + return fmt.Errorf("collector.net.nic-include: %w", err) + } + + return nil + }) + return c } @@ -179,17 +202,6 @@ func (c *Collector) Build() error { nil, ) - var err error - c.nicIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.nicInclude)) - if err != nil { - return err - } - - c.nicExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.nicExclude)) - if err != nil { - return err - } - return nil } @@ -236,8 +248,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri } for _, nic := range dst { - if c.nicExcludePattern.MatchString(nic.Name) || - !c.nicIncludePattern.MatchString(nic.Name) { + if c.config.NicExclude.MatchString(nic.Name) || + !c.config.NicInclude.MatchString(nic.Name) { continue } diff --git a/pkg/collector/netframework_clrexceptions/netframework_clrexceptions.go b/pkg/collector/netframework_clrexceptions/netframework_clrexceptions.go index 71915c6b..d2049a5c 100644 --- a/pkg/collector/netframework_clrexceptions/netframework_clrexceptions.go +++ b/pkg/collector/netframework_clrexceptions/netframework_clrexceptions.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics. type Collector struct { + config Config logger log.Logger numberOfExceptionsThrown *prometheus.Desc @@ -27,8 +28,15 @@ type Collector struct { throwToCatchDepth *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/netframework_clrinterop/netframework_clrinterop.go b/pkg/collector/netframework_clrinterop/netframework_clrinterop.go index f73a5173..74333b3c 100644 --- a/pkg/collector/netframework_clrinterop/netframework_clrinterop.go +++ b/pkg/collector/netframework_clrinterop/netframework_clrinterop.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics. type Collector struct { + config Config logger log.Logger numberOfCCWs *prometheus.Desc @@ -26,8 +27,15 @@ type Collector struct { numberOfStubs *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/netframework_clrjit/netframework_clrjit.go b/pkg/collector/netframework_clrjit/netframework_clrjit.go index 702f7107..01cb5d91 100644 --- a/pkg/collector/netframework_clrjit/netframework_clrjit.go +++ b/pkg/collector/netframework_clrjit/netframework_clrjit.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics. type Collector struct { + config Config logger log.Logger numberOfMethodsJitted *prometheus.Desc @@ -27,8 +28,15 @@ type Collector struct { totalNumberOfILBytesJitted *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/netframework_clrloading/netframework_clrloading.go b/pkg/collector/netframework_clrloading/netframework_clrloading.go index 65663df6..58ef6b5d 100644 --- a/pkg/collector/netframework_clrloading/netframework_clrloading.go +++ b/pkg/collector/netframework_clrloading/netframework_clrloading.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics. type Collector struct { + config Config logger log.Logger bytesInLoaderHeap *prometheus.Desc @@ -32,8 +33,15 @@ type Collector struct { totalNumberOfLoadFailures *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/netframework_clrlocksandthreads/netframework_clrlocksandthreads.go b/pkg/collector/netframework_clrlocksandthreads/netframework_clrlocksandthreads.go index 8d110f9b..bef9b41b 100644 --- a/pkg/collector/netframework_clrlocksandthreads/netframework_clrlocksandthreads.go +++ b/pkg/collector/netframework_clrlocksandthreads/netframework_clrlocksandthreads.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics. type Collector struct { + config Config logger log.Logger currentQueueLength *prometheus.Desc @@ -30,8 +31,15 @@ type Collector struct { totalNumberOfContentions *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/netframework_clrmemory/netframework_clrmemory.go b/pkg/collector/netframework_clrmemory/netframework_clrmemory.go index 2a14343e..4602ec16 100644 --- a/pkg/collector/netframework_clrmemory/netframework_clrmemory.go +++ b/pkg/collector/netframework_clrmemory/netframework_clrmemory.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics. type Collector struct { + config Config logger log.Logger allocatedBytes *prometheus.Desc @@ -35,8 +36,15 @@ type Collector struct { timeInGC *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/netframework_clrremoting/netframework_clrremoting.go b/pkg/collector/netframework_clrremoting/netframework_clrremoting.go index 5f1bb0bc..9f803162 100644 --- a/pkg/collector/netframework_clrremoting/netframework_clrremoting.go +++ b/pkg/collector/netframework_clrremoting/netframework_clrremoting.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics. type Collector struct { + config Config logger log.Logger channels *prometheus.Desc @@ -29,8 +30,15 @@ type Collector struct { totalRemoteCalls *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/netframework_clrsecurity/netframework_clrsecurity.go b/pkg/collector/netframework_clrsecurity/netframework_clrsecurity.go index 6f6dbc03..c66bd4bd 100644 --- a/pkg/collector/netframework_clrsecurity/netframework_clrsecurity.go +++ b/pkg/collector/netframework_clrsecurity/netframework_clrsecurity.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics. type Collector struct { + config Config logger log.Logger numberLinkTimeChecks *prometheus.Desc @@ -27,8 +28,15 @@ type Collector struct { totalRuntimeChecks *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/nps/nps.go b/pkg/collector/nps/nps.go index 232919b9..170583b6 100644 --- a/pkg/collector/nps/nps.go +++ b/pkg/collector/nps/nps.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // Collector is a Prometheus Collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics. type Collector struct { + config Config logger log.Logger accessAccepts *prometheus.Desc @@ -49,8 +50,15 @@ type Collector struct { accountingUnknownType *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/os/os.go b/pkg/collector/os/os.go index 90c80456..be24fd72 100644 --- a/pkg/collector/os/os.go +++ b/pkg/collector/os/os.go @@ -32,6 +32,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI metrics. type Collector struct { + config Config logger log.Logger osInformation *prometheus.Desc @@ -55,8 +56,15 @@ type pagingFileCounter struct { UsagePeak float64 `perflib:"% Usage Peak"` } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/physical_disk/physical_disk.go b/pkg/collector/physical_disk/physical_disk.go index a0998158..4f55c672 100644 --- a/pkg/collector/physical_disk/physical_disk.go +++ b/pkg/collector/physical_disk/physical_disk.go @@ -18,28 +18,20 @@ import ( const Name = "physical_disk" type Config struct { - DiskInclude string `yaml:"disk_include"` - DiskExclude string `yaml:"disk_exclude"` + DiskInclude *regexp.Regexp `yaml:"disk_include"` + DiskExclude *regexp.Regexp `yaml:"disk_exclude"` } var ConfigDefaults = Config{ - DiskInclude: ".+", - DiskExclude: "", + DiskInclude: types.RegExpAny, + DiskExclude: types.RegExpEmpty, } // A Collector is a Prometheus Collector for perflib PhysicalDisk metrics. type Collector struct { + config Config logger log.Logger - diskInclude *string - diskExclude *string - - diskIncludeSet bool - diskExcludeSet bool - - diskIncludePattern *regexp.Regexp - diskExcludePattern *regexp.Regexp - idleTime *prometheus.Desc readBytesTotal *prometheus.Desc readLatency *prometheus.Desc @@ -59,33 +51,55 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - c := &Collector{ - diskExclude: &config.DiskExclude, - diskInclude: &config.DiskInclude, + if config.DiskExclude == nil { + config.DiskExclude = ConfigDefaults.DiskExclude } + + if config.DiskInclude == nil { + config.DiskInclude = ConfigDefaults.DiskInclude + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c } func NewWithFlags(app *kingpin.Application) *Collector { - c := &Collector{} + c := &Collector{ + config: ConfigDefaults, + } - c.diskInclude = app.Flag( - "collector.physical_disk.disk-include", - "Regexp of disks to include. Disk number must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.DiskInclude).PreAction(func(_ *kingpin.ParseContext) error { - c.diskIncludeSet = true - return nil - }).String() + var diskExclude, diskInclude string - c.diskExclude = app.Flag( + app.Flag( "collector.physical_disk.disk-exclude", "Regexp of disks to exclude. Disk number must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.DiskExclude).PreAction(func(_ *kingpin.ParseContext) error { - c.diskExcludeSet = true + ).Default(c.config.DiskExclude.String()).StringVar(&diskExclude) + + app.Flag( + "collector.physical_disk.disk-include", + "Regexp of disks to include. Disk number must both match include and not match exclude to be included.", + ).Default(c.config.DiskInclude.String()).StringVar(&diskInclude) + + app.Action(func(*kingpin.ParseContext) error { + var err error + + c.config.DiskExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", diskExclude)) + if err != nil { + return fmt.Errorf("collector.physical_disk.disk-exclude: %w", err) + } + + c.config.DiskInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", diskInclude)) + if err != nil { + return fmt.Errorf("collector.physical_disk.disk-include: %w", err) + } + return nil - }).String() + }) return c } @@ -191,17 +205,6 @@ func (c *Collector) Build() error { nil, ) - var err error - c.diskIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.diskInclude)) - if err != nil { - return err - } - - c.diskExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.diskExclude)) - if err != nil { - return err - } - return nil } @@ -242,8 +245,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri for _, disk := range dst { if disk.Name == "_Total" || - c.diskExcludePattern.MatchString(disk.Name) || - !c.diskIncludePattern.MatchString(disk.Name) { + c.config.DiskExclude.MatchString(disk.Name) || + !c.config.DiskInclude.MatchString(disk.Name) { continue } diff --git a/pkg/collector/printer/printer.go b/pkg/collector/printer/printer.go index 3181f8e9..2b0350ff 100644 --- a/pkg/collector/printer/printer.go +++ b/pkg/collector/printer/printer.go @@ -29,37 +29,41 @@ var printerStatusMap = map[uint16]string{ } type Config struct { - PrinterInclude string `yaml:"printer_include"` - PrinterExclude string `yaml:"printer_exclude"` + PrinterInclude *regexp.Regexp `yaml:"printer_include"` + PrinterExclude *regexp.Regexp `yaml:"printer_exclude"` } var ConfigDefaults = Config{ - PrinterInclude: ".+", - PrinterExclude: "", + PrinterInclude: types.RegExpAny, + PrinterExclude: types.RegExpEmpty, } type Collector struct { + config Config logger log.Logger - printerInclude *string - printerExclude *string - printerStatus *prometheus.Desc printerJobStatus *prometheus.Desc printerJobCount *prometheus.Desc - - printerIncludePattern *regexp.Regexp - printerExcludePattern *regexp.Regexp } func New(logger log.Logger, config *Config) *Collector { if config == nil { config = &ConfigDefaults } - c := &Collector{ - printerInclude: &config.PrinterInclude, - printerExclude: &config.PrinterExclude, + + if config.PrinterExclude == nil { + config.PrinterExclude = ConfigDefaults.PrinterExclude } + + if config.PrinterInclude == nil { + config.PrinterInclude = ConfigDefaults.PrinterInclude + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c @@ -67,17 +71,37 @@ func New(logger log.Logger, config *Config) *Collector { func NewWithFlags(app *kingpin.Application) *Collector { c := &Collector{ - printerInclude: app.Flag( - "collector.printer.include", - "Regular expression to match printers to collect metrics for", - ).Default(ConfigDefaults.PrinterInclude).String(), - - printerExclude: app.Flag( - "collector.printer.exclude", - "Regular expression to match printers to exclude", - ).Default(ConfigDefaults.PrinterExclude).String(), + config: ConfigDefaults, } + var printerInclude, printerExclude string + + app.Flag( + "collector.printer.include", + "Regular expression to match printers to collect metrics for", + ).Default(c.config.PrinterInclude.String()).StringVar(&printerInclude) + + app.Flag( + "collector.printer.exclude", + "Regular expression to match printers to exclude", + ).Default(c.config.PrinterExclude.String()).StringVar(&printerExclude) + + app.Action(func(*kingpin.ParseContext) error { + var err error + + c.config.PrinterInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", printerInclude)) + if err != nil { + return fmt.Errorf("collector.printer.include: %w", err) + } + + c.config.PrinterExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", printerExclude)) + if err != nil { + return fmt.Errorf("collector.printer.exclude: %w", err) + } + + return nil + }) + return c } @@ -109,27 +133,21 @@ func (c *Collector) Build() error { nil, ) - var err error - c.printerIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.printerInclude)) - if err != nil { - return err - } - c.printerExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.printerExclude)) - return err + return nil } func (c *Collector) GetName() string { return Name } func (c *Collector) GetPerfCounter() ([]string, error) { return []string{"Printer"}, nil } -type win32_Printer struct { +type wmiPrinter struct { Name string Default bool PrinterStatus uint16 JobCountSinceLastReset uint32 } -type win32_PrintJob struct { +type wmiPrintJob struct { Name string Status string } @@ -139,23 +157,26 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) _ = level.Error(c.logger).Log("msg", "failed to collect printer status metrics", "err", err) return err } + if err := c.collectPrinterJobStatus(ch); err != nil { _ = level.Error(c.logger).Log("msg", "failed to collect printer job status metrics", "err", err) return err } + return nil } func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error { - var printers []win32_Printer - q := wmi.QueryAll(&printers, c.logger) + var printers []wmiPrinter + + q := wmi.QueryAllForClass(&printers, "win32_Printer", c.logger) if err := wmi.Query(q, &printers); err != nil { return err } for _, printer := range printers { - if c.printerExcludePattern.MatchString(printer.Name) || - !c.printerIncludePattern.MatchString(printer.Name) { + if c.config.PrinterExclude.MatchString(printer.Name) || + !c.config.PrinterInclude.MatchString(printer.Name) { continue } @@ -186,8 +207,9 @@ func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error { } func (c *Collector) collectPrinterJobStatus(ch chan<- prometheus.Metric) error { - var printJobs []win32_PrintJob - q := wmi.QueryAll(&printJobs, c.logger) + var printJobs []wmiPrintJob + + q := wmi.QueryAllForClass(&printJobs, "win32_PrintJob", c.logger) if err := wmi.Query(q, &printJobs); err != nil { return err } @@ -202,6 +224,7 @@ func (c *Collector) collectPrinterJobStatus(ch chan<- prometheus.Metric) error { group.status, ) } + return nil } @@ -210,19 +233,22 @@ type PrintJobStatusGroup struct { status string } -func (c *Collector) groupPrintJobs(printJobs []win32_PrintJob) map[PrintJobStatusGroup]int { +func (c *Collector) groupPrintJobs(printJobs []wmiPrintJob) map[PrintJobStatusGroup]int { groupedPrintJobs := make(map[PrintJobStatusGroup]int) + for _, printJob := range printJobs { printerName := strings.Split(printJob.Name, ",")[0] - if c.printerExcludePattern.MatchString(printerName) || - !c.printerIncludePattern.MatchString(printerName) { + if c.config.PrinterExclude.MatchString(printerName) || + !c.config.PrinterInclude.MatchString(printerName) { continue } + groupedPrintJobs[PrintJobStatusGroup{ printerName: printerName, status: printJob.Status, }]++ } + return groupedPrintJobs } diff --git a/pkg/collector/process/process.go b/pkg/collector/process/process.go index 8aba6957..fbd9d994 100644 --- a/pkg/collector/process/process.go +++ b/pkg/collector/process/process.go @@ -15,7 +15,6 @@ import ( "github.com/go-kit/log/level" "github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/types" - "github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" "golang.org/x/sys/windows" @@ -24,31 +23,23 @@ import ( const Name = "process" type Config struct { - ProcessInclude string `yaml:"process_include"` - ProcessExclude string `yaml:"process_exclude"` - EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` //nolint:tagliatelle - EnableReportOwner bool `yaml:"enable_report_owner"` + ProcessInclude *regexp.Regexp `yaml:"process_include"` + ProcessExclude *regexp.Regexp `yaml:"process_exclude"` + EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` //nolint:tagliatelle + EnableReportOwner bool `yaml:"enable_report_owner"` } var ConfigDefaults = Config{ - ProcessInclude: ".+", - ProcessExclude: "", + ProcessInclude: types.RegExpAny, + ProcessExclude: types.RegExpEmpty, EnableWorkerProcess: false, EnableReportOwner: false, } type Collector struct { + config Config logger log.Logger - enableWorkerProcess *bool - enableReportOwner *bool - - processInclude *string - processExclude *string - - processIncludePattern *regexp.Regexp - processExcludePattern *regexp.Regexp - lookupCache map[string]string cpuTimeTotal *prometheus.Desc @@ -73,11 +64,18 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - c := &Collector{ - processExclude: &config.ProcessExclude, - processInclude: &config.ProcessInclude, - enableWorkerProcess: &config.EnableWorkerProcess, + if config.ProcessExclude == nil { + config.ProcessExclude = ConfigDefaults.ProcessExclude } + + if config.ProcessInclude == nil { + config.ProcessInclude = ConfigDefaults.ProcessInclude + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c @@ -85,26 +83,47 @@ func New(logger log.Logger, config *Config) *Collector { func NewWithFlags(app *kingpin.Application) *Collector { c := &Collector{ - processInclude: app.Flag( - "collector.process.include", - "Regexp of processes to include. Process name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.ProcessInclude).String(), - - processExclude: app.Flag( - "collector.process.exclude", - "Regexp of processes to exclude. Process name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.ProcessExclude).String(), - - enableWorkerProcess: app.Flag( - "collector.process.iis", - "Enable IIS worker process name queries. May cause the collector to leak memory.", - ).Default("false").Bool(), - - enableReportOwner: app.Flag( - "collector.process.report-owner", - "Enable reporting of process owner.", - ).Default("false").Bool(), + config: ConfigDefaults, } + + var processExclude, processInclude string + + app.Flag( + "collector.process.exclude", + "Regexp of processes to exclude. Process name must both match include and not match exclude to be included.", + ).Default(c.config.ProcessExclude.String()).StringVar(&processExclude) + + app.Flag( + "collector.process.include", + "Regexp of processes to include. Process name must both match include and not match exclude to be included.", + ).Default(c.config.ProcessInclude.String()).StringVar(&processInclude) + + app.Flag( + "collector.process.iis", + "Enable IIS worker process name queries. May cause the collector to leak memory.", + ).Default(strconv.FormatBool(c.config.EnableWorkerProcess)).BoolVar(&c.config.EnableWorkerProcess) + + app.Flag( + "collector.process.report-owner", + "Enable reporting of process owner.", + ).Default(strconv.FormatBool(c.config.EnableReportOwner)).BoolVar(&c.config.EnableReportOwner) + + app.Action(func(*kingpin.ParseContext) error { + var err error + + c.config.ProcessExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", processExclude)) + if err != nil { + return fmt.Errorf("collector.process.exclude: %w", err) + } + + c.config.ProcessInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", processInclude)) + if err != nil { + return fmt.Errorf("collector.process.include: %w", err) + } + + return nil + }) + return c } @@ -125,12 +144,12 @@ func (c *Collector) Close() error { } func (c *Collector) Build() error { - if c.processInclude != nil && *c.processInclude == ".*" && utils.IsEmpty(c.processExclude) { + if c.config.ProcessInclude.String() == "^(?:.*)$" && c.config.ProcessExclude.String() == "^(?:)$" { _ = level.Warn(c.logger).Log("msg", "No filters specified for process collector. This will generate a very large number of metrics!") } commonLabels := make([]string, 0) - if *c.enableReportOwner { + if c.config.EnableReportOwner { commonLabels = []string{"owner"} } @@ -227,18 +246,6 @@ func (c *Collector) Build() error { c.lookupCache = make(map[string]string) - var err error - - c.processIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.processInclude)) - if err != nil { - return err - } - - c.processExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.processExclude)) - if err != nil { - return err - } - return nil } @@ -262,7 +269,7 @@ type perflibProcess struct { PageFaultsPerSec float64 `perflib:"Page Faults/sec"` PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"` PageFileBytes float64 `perflib:"Page File Bytes"` - PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"` + PoolNonPagedBytes float64 `perflib:"Pool Nonpaged Bytes"` PoolPagedBytes float64 `perflib:"Pool Paged Bytes"` PriorityBase float64 `perflib:"Priority Base"` PrivateBytes float64 `perflib:"Private Bytes"` @@ -286,10 +293,10 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri return err } - var dst_wp []WorkerProcess - if *c.enableWorkerProcess { - q_wp := wmi.QueryAll(&dst_wp, c.logger) - if err := wmi.QueryNamespace(q_wp, &dst_wp, "root\\WebAdministration"); err != nil { + var workerProcesses []WorkerProcess + if c.config.EnableWorkerProcess { + queryWorkerProcess := wmi.QueryAllForClass(&workerProcesses, "WorkerProcess", c.logger) + if err := wmi.QueryNamespace(queryWorkerProcess, &workerProcesses, "root\\WebAdministration"); err != nil { _ = level.Debug(c.logger).Log("msg", "Could not query WebAdministration namespace for IIS worker processes", "err", err) } } @@ -298,17 +305,18 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri for _, process := range data { if process.Name == "_Total" || - c.processExcludePattern.MatchString(process.Name) || - !c.processIncludePattern.MatchString(process.Name) { + c.config.ProcessExclude.MatchString(process.Name) || + !c.config.ProcessInclude.MatchString(process.Name) { continue } - // Duplicate processes are suffixed # and an index number. Remove those. - processName := strings.Split(process.Name, "#")[0] - pid := strconv.FormatUint(uint64(process.IDProcess), 10) - cpid := strconv.FormatUint(uint64(process.CreatingProcessID), 10) - if *c.enableWorkerProcess { - for _, wp := range dst_wp { + // Duplicate processes are suffixed #, and an index number. Remove those. + processName, _, _ := strings.Cut(process.Name, "#") + pid := strconv.FormatUint(uint64(process.IDProcess), 10) + parentPID := strconv.FormatUint(uint64(process.CreatingProcessID), 10) + + if c.config.EnableWorkerProcess { + for _, wp := range workerProcesses { if wp.ProcessId == uint64(process.IDProcess) { processName = strings.Join([]string{processName, wp.AppPoolName}, "_") break @@ -318,7 +326,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri labels := make([]string, 0, 4) - if *c.enableReportOwner { + if c.config.EnableReportOwner { owner, err = c.getProcessOwner(int(process.IDProcess)) if err != nil { owner = "unknown" @@ -327,7 +335,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri labels = []string{owner} } - labels = append(labels, processName, pid, cpid) + labels = append(labels, processName, pid, parentPID) ch <- prometheus.MustNewConstMetric( c.startTime, @@ -416,7 +424,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri ch <- prometheus.MustNewConstMetric( c.poolBytes, prometheus.GaugeValue, - process.PoolNonpagedBytes, + process.PoolNonPagedBytes, append(labels, "nonpaged")..., ) diff --git a/pkg/collector/remote_fx/remote_fx.go b/pkg/collector/remote_fx/remote_fx.go index 1f3e455d..4143b16c 100644 --- a/pkg/collector/remote_fx/remote_fx.go +++ b/pkg/collector/remote_fx/remote_fx.go @@ -26,6 +26,7 @@ var ConfigDefaults = Config{} // https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxnetwork/ // https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxgraphics/ type Collector struct { + config Config logger log.Logger // net @@ -53,8 +54,15 @@ type Collector struct { sourceFramesPerSecond *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/scheduled_task/scheduled_task.go b/pkg/collector/scheduled_task/scheduled_task.go index a3139fc1..c1ef1799 100644 --- a/pkg/collector/scheduled_task/scheduled_task.go +++ b/pkg/collector/scheduled_task/scheduled_task.go @@ -18,35 +18,25 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -const ( - Name = "scheduled_task" - - FlagScheduledTaskExclude = "collector.scheduled_task.exclude" - FlagScheduledTaskInclude = "collector.scheduled_task.include" -) +const Name = "scheduled_task" type Config struct { - TaskExclude string `yaml:"task_exclude"` - TaskInclude string `yaml:"task_include"` + TaskExclude *regexp.Regexp `yaml:"task_exclude"` + TaskInclude *regexp.Regexp `yaml:"task_include"` } var ConfigDefaults = Config{ - TaskExclude: "", - TaskInclude: ".+", + TaskExclude: types.RegExpEmpty, + TaskInclude: types.RegExpAny, } type Collector struct { + config Config logger log.Logger - taskExclude *string - taskInclude *string - lastResult *prometheus.Desc missedRuns *prometheus.Desc state *prometheus.Desc - - taskIncludePattern *regexp.Regexp - taskExcludePattern *regexp.Regexp } // TaskState ... @@ -80,10 +70,18 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - c := &Collector{ - taskExclude: &config.TaskExclude, - taskInclude: &config.TaskInclude, + if config.TaskExclude == nil { + config.TaskExclude = ConfigDefaults.TaskExclude } + + if config.TaskInclude == nil { + config.TaskInclude = ConfigDefaults.TaskInclude + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c @@ -91,17 +89,37 @@ func New(logger log.Logger, config *Config) *Collector { func NewWithFlags(app *kingpin.Application) *Collector { c := &Collector{ - taskInclude: app.Flag( - FlagScheduledTaskInclude, - "Regexp of tasks to include. Task path must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.TaskInclude).String(), - - taskExclude: app.Flag( - FlagScheduledTaskExclude, - "Regexp of tasks to exclude. Task path must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.TaskExclude).String(), + config: ConfigDefaults, } + var taskExclude, taskInclude string + + app.Flag( + "collector.scheduled_task.exclude", + "Regexp of tasks to exclude. Task path must both match include and not match exclude to be included.", + ).Default(c.config.TaskExclude.String()).StringVar(&taskExclude) + + app.Flag( + "collector.scheduled_task.include", + "Regexp of tasks to include. Task path must both match include and not match exclude to be included.", + ).Default(c.config.TaskExclude.String()).StringVar(&taskInclude) + + app.Action(func(*kingpin.ParseContext) error { + var err error + + c.config.TaskExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", taskExclude)) + if err != nil { + return fmt.Errorf("collector.physical_disk.disk-exclude: %w", err) + } + + c.config.TaskInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", taskInclude)) + if err != nil { + return fmt.Errorf("collector.physical_disk.disk-include: %w", err) + } + + return nil + }) + return c } @@ -143,18 +161,6 @@ func (c *Collector) Build() error { nil, ) - var err error - - c.taskIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.taskInclude)) - if err != nil { - return err - } - - c.taskExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.taskExclude)) - if err != nil { - return err - } - return nil } @@ -176,8 +182,8 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error { } for _, task := range scheduledTasks { - if c.taskExcludePattern.MatchString(task.Path) || - !c.taskIncludePattern.MatchString(task.Path) { + if c.config.TaskExclude.MatchString(task.Path) || + !c.config.TaskInclude.MatchString(task.Path) { continue } diff --git a/pkg/collector/service/service.go b/pkg/collector/service/service.go index b2d0fede..6b9fc41a 100644 --- a/pkg/collector/service/service.go +++ b/pkg/collector/service/service.go @@ -226,7 +226,7 @@ var ( func (c *Collector) collectWMI(ch chan<- prometheus.Metric) error { var dst []Win32_Service - q := wmi.QueryAllWhere(&dst, *c.serviceWhereClause, c.logger) + q := wmi.QueryAllWhere(&dst, *c.serviceWhereClause, c.logger) //nolint:staticcheck if err := wmi.Query(q, &dst); err != nil { return err } diff --git a/pkg/collector/smb/smb.go b/pkg/collector/smb/smb.go index 42bab8a1..19d6c41c 100644 --- a/pkg/collector/smb/smb.go +++ b/pkg/collector/smb/smb.go @@ -3,9 +3,6 @@ package smb import ( - "fmt" - "os" - "slices" "strings" "github.com/alecthomas/kingpin/v2" @@ -18,29 +15,16 @@ import ( const Name = "smb" -type Config struct { - CollectorsEnabled string `yaml:"collectors_enabled"` -} +type Config struct{} -var ConfigDefaults = Config{ - CollectorsEnabled: "", -} +var ConfigDefaults = Config{} type Collector struct { + config Config logger log.Logger - smbListAllCollectors *bool - smbCollectorsEnabled *string - treeConnectCount *prometheus.Desc currentOpenFileCount *prometheus.Desc - - enabledCollectors []string -} - -// All available Collector functions. -var smbAllCollectorNames = []string{ - "ServerShares", } func New(logger log.Logger, config *Config) *Collector { @@ -48,10 +32,8 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - smbListAllCollectors := false c := &Collector{ - smbCollectorsEnabled: &config.CollectorsEnabled, - smbListAllCollectors: &smbListAllCollectors, + config: *config, } c.SetLogger(logger) @@ -59,18 +41,8 @@ func New(logger log.Logger, config *Config) *Collector { return c } -func NewWithFlags(app *kingpin.Application) *Collector { - return &Collector{ - smbListAllCollectors: app.Flag( - "collectors.smb.list", - "List the collectors along with their perflib object name/ids", - ).Bool(), - - smbCollectorsEnabled: app.Flag( - "collectors.smb.enabled", - "Comma-separated list of collectors to use. Defaults to all, if not specified.", - ).Default(ConfigDefaults.CollectorsEnabled).String(), - } +func NewWithFlags(_ *kingpin.Application) *Collector { + return &Collector{} } func (c *Collector) GetName() string { @@ -105,48 +77,17 @@ func (c *Collector) Build() error { c.currentOpenFileCount = desc("server_shares_current_open_file_count", "Current total count open files on the SMB Server") c.treeConnectCount = desc("server_shares_tree_connect_count", "Count of user connections to the SMB Server") - c.enabledCollectors = make([]string, 0, len(smbAllCollectorNames)) - - collectorDesc := map[string]string{ - "ServerShares": "SMB Server Shares", - } - - if *c.smbListAllCollectors { - fmt.Printf("%-32s %-32s\n", "Collector Name", "Perflib Object") //nolint:forbidigo - for _, cname := range smbAllCollectorNames { - fmt.Printf("%-32s %-32s\n", cname, collectorDesc[cname]) //nolint:forbidigo - } - - os.Exit(0) - } - - if *c.smbCollectorsEnabled == "" { - c.enabledCollectors = append(c.enabledCollectors, smbAllCollectorNames...) - } else { - for _, collectorName := range strings.Split(*c.smbCollectorsEnabled, ",") { - if slices.Contains(smbAllCollectorNames, collectorName) { - c.enabledCollectors = append(c.enabledCollectors, collectorName) - } else { - return fmt.Errorf("unknown smb collector: %s", collectorName) - } - } - } - return nil } // Collect collects smb metrics and sends them to prometheus. func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { - collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{ - "ServerShares": c.collectServerShares, + if err := c.collectServerShares(ctx, ch); err != nil { + _ = level.Error(c.logger).Log("msg", "failed to collect server share metrics", "err", err) + + return err } - for _, collectorName := range c.enabledCollectors { - if err := collectorFuncs[collectorName](ctx, ch); err != nil { - _ = level.Error(c.logger).Log("msg", "Error in "+collectorName, "err", err) - return err - } - } return nil } diff --git a/pkg/collector/smbclient/smbclient.go b/pkg/collector/smbclient/smbclient.go index 934a0d8b..72a10b36 100644 --- a/pkg/collector/smbclient/smbclient.go +++ b/pkg/collector/smbclient/smbclient.go @@ -3,9 +3,6 @@ package smbclient import ( - "fmt" - "os" - "slices" "strings" "github.com/alecthomas/kingpin/v2" @@ -20,22 +17,14 @@ const ( Name = "smbclient" ) -type Config struct { - CollectorsEnabled string `yaml:"collectors_enabled"` -} +type Config struct{} -var ConfigDefaults = Config{ - CollectorsEnabled: "", -} +var ConfigDefaults = Config{} type Collector struct { + config Config logger log.Logger - enabledCollectors []string - - smbClientListAllCollectors *bool - smbClientCollectorsEnabled *string - readBytesTotal *prometheus.Desc readBytesTransmittedViaSMBDirectTotal *prometheus.Desc readRequestQueueSecsTotal *prometheus.Desc @@ -60,38 +49,22 @@ type Collector struct { requestSecs *prometheus.Desc } -// All available collector functions. -var smbclientAllCollectorNames = []string{ - "ClientShares", -} - func New(logger log.Logger, config *Config) *Collector { if config == nil { config = &ConfigDefaults } - smbclientListAllCollectors := false c := &Collector{ - smbClientCollectorsEnabled: &config.CollectorsEnabled, - smbClientListAllCollectors: &smbclientListAllCollectors, + config: *config, } + c.SetLogger(logger) return c } -func NewWithFlags(app *kingpin.Application) *Collector { - return &Collector{ - smbClientListAllCollectors: app.Flag( - "collectors.smbclient.list", - "List the collectors along with their perflib object name/ids", - ).Bool(), - - smbClientCollectorsEnabled: app.Flag( - "collectors.smbclient.enabled", - "Comma-separated list of collectors to use. Defaults to all, if not specified.", - ).Default(ConfigDefaults.CollectorsEnabled).String(), - } +func NewWithFlags(_ *kingpin.Application) *Collector { + return &Collector{} } func (c *Collector) GetName() string { @@ -208,48 +181,16 @@ func (c *Collector) Build() error { []string{"server", "share"}, ) - c.enabledCollectors = make([]string, 0, len(smbclientAllCollectorNames)) - - collectorDesc := map[string]string{ - "ClientShares": "SMB Client Shares", - } - - if *c.smbClientListAllCollectors { - fmt.Printf("%-32s %-32s\n", "Collector Name", "Perflib Object") //nolint:forbidigo - for _, cname := range smbclientAllCollectorNames { - fmt.Printf("%-32s %-32s\n", cname, collectorDesc[cname]) //nolint:forbidigo - } - - os.Exit(0) - } - - if *c.smbClientCollectorsEnabled == "" { - c.enabledCollectors = append(c.enabledCollectors, smbclientAllCollectorNames...) - } else { - for _, collectorName := range strings.Split(*c.smbClientCollectorsEnabled, ",") { - if slices.Contains(smbclientAllCollectorNames, collectorName) { - c.enabledCollectors = append(c.enabledCollectors, collectorName) - } else { - return fmt.Errorf("unknown smbclient Collector: %s", collectorName) - } - } - } - return nil } // Collect collects smb client metrics and sends them to prometheus. func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { - collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{ - "ClientShares": c.collectClientShares, + if err := c.collectClientShares(ctx, ch); err != nil { + _ = level.Error(c.logger).Log("msg", "Error in ClientShares", "err", err) + return err } - for _, collectorName := range c.enabledCollectors { - if err := collectorFuncs[collectorName](ctx, ch); err != nil { - _ = level.Error(c.logger).Log("msg", "Error in "+collectorName, "err", err) - return err - } - } return nil } diff --git a/pkg/collector/smtp/smtp.go b/pkg/collector/smtp/smtp.go index b54ccbfe..b25156f5 100644 --- a/pkg/collector/smtp/smtp.go +++ b/pkg/collector/smtp/smtp.go @@ -17,23 +17,19 @@ import ( const Name = "smtp" type Config struct { - ServerInclude string `yaml:"server_include"` - ServerExclude string `yaml:"server_exclude"` + ServerInclude *regexp.Regexp `yaml:"server_include"` + ServerExclude *regexp.Regexp `yaml:"server_exclude"` } var ConfigDefaults = Config{ - ServerInclude: ".+", - ServerExclude: "", + ServerInclude: types.RegExpAny, + ServerExclude: types.RegExpEmpty, } type Collector struct { + config Config logger log.Logger - serverInclude *string - serverExclude *string - serverIncludePattern *regexp.Regexp - serverExcludePattern *regexp.Regexp - badMailedMessagesBadPickupFileTotal *prometheus.Desc badMailedMessagesGeneralFailureTotal *prometheus.Desc badMailedMessagesHopCountExceededTotal *prometheus.Desc @@ -83,10 +79,18 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - c := &Collector{ - serverExclude: &config.ServerExclude, - serverInclude: &config.ServerInclude, + if config.ServerExclude == nil { + config.ServerExclude = ConfigDefaults.ServerExclude } + + if config.ServerInclude == nil { + config.ServerInclude = ConfigDefaults.ServerInclude + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c @@ -94,17 +98,37 @@ func New(logger log.Logger, config *Config) *Collector { func NewWithFlags(app *kingpin.Application) *Collector { c := &Collector{ - serverInclude: app.Flag( - "collector.smtp.server-include", - "Regexp of virtual servers to include. Server name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.ServerInclude).String(), - - serverExclude: app.Flag( - "collector.smtp.server-exclude", - "Regexp of virtual servers to exclude. Server name must both match include and not match exclude to be included.", - ).Default(ConfigDefaults.ServerExclude).String(), + config: ConfigDefaults, } + var serverExclude, serverInclude string + + app.Flag( + "collector.smtp.server-exclude", + "Regexp of virtual servers to exclude. Server name must both match include and not match exclude to be included.", + ).Default(c.config.ServerExclude.String()).StringVar(&serverExclude) + + app.Flag( + "collector.smtp.server-include", + "Regexp of virtual servers to include. Server name must both match include and not match exclude to be included.", + ).Default(c.config.ServerInclude.String()).StringVar(&serverInclude) + + app.Action(func(*kingpin.ParseContext) error { + var err error + + c.config.ServerExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", serverExclude)) + if err != nil { + return fmt.Errorf("collector.smtp.server-exclude: %w", err) + } + + c.config.ServerInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", serverInclude)) + if err != nil { + return fmt.Errorf("collector.smtp.server-include: %w", err) + } + + return nil + }) + return c } @@ -380,18 +404,6 @@ func (c *Collector) Build() error { nil, ) - var err error - - c.serverIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.serverInclude)) - if err != nil { - return err - } - - c.serverExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.serverExclude)) - if err != nil { - return err - } - return nil } @@ -461,8 +473,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri for _, server := range dst { if server.Name == "_Total" || - c.serverExcludePattern.MatchString(server.Name) || - !c.serverIncludePattern.MatchString(server.Name) { + c.config.ServerExclude.MatchString(server.Name) || + !c.config.ServerInclude.MatchString(server.Name) { continue } diff --git a/pkg/collector/system/system.go b/pkg/collector/system/system.go index 211ee671..0e97eaed 100644 --- a/pkg/collector/system/system.go +++ b/pkg/collector/system/system.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI metrics. type Collector struct { + config Config logger log.Logger contextSwitchesTotal *prometheus.Desc @@ -29,8 +30,15 @@ type Collector struct { threads *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/tcp/tcp.go b/pkg/collector/tcp/tcp.go index 33d2021e..f874b88a 100644 --- a/pkg/collector/tcp/tcp.go +++ b/pkg/collector/tcp/tcp.go @@ -19,6 +19,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics. type Collector struct { + config Config logger log.Logger connectionFailures *prometheus.Desc @@ -32,8 +33,15 @@ type Collector struct { segmentsSentTotal *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/teradici_pcoip/teradici_pcoip.go b/pkg/collector/teradici_pcoip/teradici_pcoip.go index 83857650..abf76615 100644 --- a/pkg/collector/teradici_pcoip/teradici_pcoip.go +++ b/pkg/collector/teradici_pcoip/teradici_pcoip.go @@ -26,6 +26,7 @@ var ConfigDefaults = Config{} // win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics // win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics. type Collector struct { + config Config logger log.Logger audioBytesReceived *prometheus.Desc @@ -71,8 +72,15 @@ type Collector struct { usbTXBWKBitPerSec *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/terminal_services/terminal_services.go b/pkg/collector/terminal_services/terminal_services.go index 2abe3580..a2100a6a 100644 --- a/pkg/collector/terminal_services/terminal_services.go +++ b/pkg/collector/terminal_services/terminal_services.go @@ -51,6 +51,7 @@ func isConnectionBrokerServer(logger log.Logger) bool { // https://docs.microsoft.com/en-us/previous-versions/aa394344(v%3Dvs.85) // https://wutils.com/wmi/root/cimv2/win32_perfrawdata_localsessionmanager_terminalservices/ type Collector struct { + config Config logger log.Logger connectionBrokerEnabled bool @@ -74,8 +75,15 @@ type Collector struct { workingSetPeak *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/textfile/textfile.go b/pkg/collector/textfile/textfile.go index e092a264..411f50d3 100644 --- a/pkg/collector/textfile/textfile.go +++ b/pkg/collector/textfile/textfile.go @@ -31,7 +31,6 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus-community/windows_exporter/pkg/types" - "github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" @@ -40,19 +39,17 @@ import ( const Name = "textfile" type Config struct { - TextFileDirectories string `yaml:"text_file_directories"` + TextFileDirectories []string `yaml:"text_file_directories"` } var ConfigDefaults = Config{ - TextFileDirectories: getDefaultPath(), + TextFileDirectories: []string{getDefaultPath()}, } type Collector struct { + config Config logger log.Logger - textFileDirectories *string - - directories string // Only set for testing to get predictable output. mTime *float64 @@ -64,21 +61,31 @@ func New(logger log.Logger, config *Config) *Collector { config = &ConfigDefaults } - c := &Collector{ - textFileDirectories: &config.TextFileDirectories, + if config.TextFileDirectories == nil { + config.TextFileDirectories = ConfigDefaults.TextFileDirectories } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c } func NewWithFlags(app *kingpin.Application) *Collector { - return &Collector{ - textFileDirectories: app.Flag( - "collector.textfile.directories", - "Directory or Directories to read text files with metrics from.", - ).Default(ConfigDefaults.TextFileDirectories).String(), + c := &Collector{ + config: ConfigDefaults, } + c.config.TextFileDirectories = make([]string, 0) + + app.Flag( + "collector.textfile.directories", + "Directory or Directories to read text files with metrics from.", + ).Default(strings.Join(ConfigDefaults.TextFileDirectories, ",")).StringsVar(&c.config.TextFileDirectories) + + return c } func (c *Collector) GetName() string { @@ -98,12 +105,8 @@ func (c *Collector) Close() error { } func (c *Collector) Build() error { - c.directories = "" - if utils.HasValue(c.textFileDirectories) { - c.directories = strings.Trim(*c.textFileDirectories, ",") - } - - _ = level.Info(c.logger).Log("msg", "textfile Collector directories: "+c.directories) + _ = level.Info(c.logger). + Log("msg", "textfile Collector directories: "+strings.Join(c.config.TextFileDirectories, ",")) c.mTimeDesc = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, "textfile", "mtime_seconds"), @@ -242,18 +245,18 @@ func (c *Collector) convertMetricFamily(metricFamily *dto.MetricFamily, ch chan< } } -func (c *Collector) exportMTimes(mtimes map[string]time.Time, ch chan<- prometheus.Metric) { +func (c *Collector) exportMTimes(mTimes map[string]time.Time, ch chan<- prometheus.Metric) { // Export the mtimes of the successful files. - if len(mtimes) > 0 { + if len(mTimes) > 0 { // Sorting is needed for predictable output comparison in tests. - filenames := make([]string, 0, len(mtimes)) - for filename := range mtimes { + filenames := make([]string, 0, len(mTimes)) + for filename := range mTimes { filenames = append(filenames, filename) } sort.Strings(filenames) for _, filename := range filenames { - mtime := float64(mtimes[filename].UnixNano() / 1e9) + mtime := float64(mTimes[filename].UnixNano() / 1e9) if c.mTime != nil { mtime = *c.mTime } @@ -289,14 +292,15 @@ func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) { // Collect implements the Collector interface. func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { errorMetric := 0.0 - mtimes := map[string]time.Time{} + mTimes := map[string]time.Time{} + // Create empty metricFamily slice here and append parsedFamilies to it inside the loop. // Once loop is complete, raise error if any duplicates are present. // This will ensure that duplicate metrics are correctly detected between multiple .prom files. - metricFamilies := []*dto.MetricFamily{} + var metricFamilies []*dto.MetricFamily // Iterate over files and accumulate their metrics. - for _, directory := range strings.Split(c.directories, ",") { + for _, directory := range c.config.TextFileDirectories { err := filepath.WalkDir(directory, func(path string, dirEntry os.DirEntry, err error) error { if err != nil { _ = level.Error(c.logger).Log("msg", "Error reading directory: "+path, "err", err) @@ -317,18 +321,18 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) errorMetric = 1.0 return nil } - if _, hasName := mtimes[fileInfo.Name()]; hasName { + if _, hasName := mTimes[fileInfo.Name()]; hasName { _ = level.Error(c.logger).Log("msg", fmt.Sprintf("Duplicate filename detected: %q. Skip File.", path)) errorMetric = 1.0 return nil } - mtimes[fileInfo.Name()] = fileInfo.ModTime() + mTimes[fileInfo.Name()] = fileInfo.ModTime() metricFamilies = append(metricFamilies, families_array...) } return nil }) if err != nil && directory != "" { - _ = level.Error(c.logger).Log("msg", "Error reading textfile Collector directory: "+c.directories, "err", err) + _ = level.Error(c.logger).Log("msg", "Error reading textfile Collector directory: "+directory, "err", err) errorMetric = 1.0 } } @@ -343,7 +347,7 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) } } - c.exportMTimes(mtimes, ch) + c.exportMTimes(mTimes, ch) // Export if there were errors. ch <- prometheus.MustNewConstMetric( prometheus.NewDesc( diff --git a/pkg/collector/textfile/textfile_test_test.go b/pkg/collector/textfile/textfile_test_test.go index 6a7c6887..78c975fc 100644 --- a/pkg/collector/textfile/textfile_test_test.go +++ b/pkg/collector/textfile/textfile_test_test.go @@ -22,11 +22,11 @@ func TestMultipleDirectories(t *testing.T) { testDir := baseDir + "/multiple-dirs" testDirs := fmt.Sprintf("%[1]s/dir1,%[1]s/dir2,%[1]s/dir3", testDir) - textfileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{ - TextFileDirectories: testDirs, + textFileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{ + TextFileDirectories: strings.Split(testDirs, ","), }) - collectors := collector.New(map[string]collector.Collector{textfile.Name: textfileCollector}) + collectors := collector.New(map[string]collector.Collector{textfile.Name: textFileCollector}) require.NoError(t, collectors.Build()) scrapeContext, err := collectors.PrepareScrapeContext() @@ -47,7 +47,7 @@ func TestMultipleDirectories(t *testing.T) { } }() - err = textfileCollector.Collect(scrapeContext, metrics) + err = textFileCollector.Collect(scrapeContext, metrics) if err != nil { t.Errorf("Unexpected error %s", err) } @@ -63,11 +63,11 @@ func TestDuplicateFileName(t *testing.T) { t.Parallel() testDir := baseDir + "/duplicate-filename" - textfileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{ - TextFileDirectories: testDir, + textFileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{ + TextFileDirectories: []string{testDir}, }) - collectors := collector.New(map[string]collector.Collector{textfile.Name: textfileCollector}) + collectors := collector.New(map[string]collector.Collector{textfile.Name: textFileCollector}) require.NoError(t, collectors.Build()) scrapeContext, err := collectors.PrepareScrapeContext() @@ -87,13 +87,15 @@ func TestDuplicateFileName(t *testing.T) { got += metric.String() } }() - err = textfileCollector.Collect(scrapeContext, metrics) + err = textFileCollector.Collect(scrapeContext, metrics) if err != nil { t.Errorf("Unexpected error %s", err) } + if !strings.Contains(got, "file") { t.Errorf("Unexpected output %q", got) } + if strings.Contains(got, "sub_file") { t.Errorf("Unexpected output %q", got) } diff --git a/pkg/collector/thermalzone/thermalzone.go b/pkg/collector/thermalzone/thermalzone.go index cbc47e86..a72ea5db 100644 --- a/pkg/collector/thermalzone/thermalzone.go +++ b/pkg/collector/thermalzone/thermalzone.go @@ -21,6 +21,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics. type Collector struct { + config Config logger log.Logger percentPassiveLimit *prometheus.Desc @@ -28,8 +29,15 @@ type Collector struct { throttleReasons *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/time/time.go b/pkg/collector/time/time.go index aec5d6fa..e78d98d9 100644 --- a/pkg/collector/time/time.go +++ b/pkg/collector/time/time.go @@ -22,6 +22,7 @@ var ConfigDefaults = Config{} // Collector is a Prometheus Collector for Perflib counter metrics. type Collector struct { + config Config logger log.Logger clockFrequencyAdjustmentPPBTotal *prometheus.Desc @@ -32,8 +33,15 @@ type Collector struct { ntpServerOutgoingResponsesTotal *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/vmware/vmware.go b/pkg/collector/vmware/vmware.go index a3e8583e..52514d11 100644 --- a/pkg/collector/vmware/vmware.go +++ b/pkg/collector/vmware/vmware.go @@ -22,6 +22,7 @@ var ConfigDefaults = Config{} // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics. type Collector struct { + config Config logger log.Logger memActive *prometheus.Desc @@ -46,8 +47,15 @@ type Collector struct { hostProcessorSpeedMHz *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/collector/vmware_blast/vmware_blast.go b/pkg/collector/vmware_blast/vmware_blast.go index 998f2855..4162f68a 100644 --- a/pkg/collector/vmware_blast/vmware_blast.go +++ b/pkg/collector/vmware_blast/vmware_blast.go @@ -32,6 +32,7 @@ var ConfigDefaults = Config{} // win32_PerfRawData_Counters_VMwareBlastWindowsMediaMMRCounters type Collector struct { + config Config logger log.Logger audioReceivedBytes *prometheus.Desc @@ -116,8 +117,15 @@ type Collector struct { windowsMediaMMRTransmittedPackets *prometheus.Desc } -func New(logger log.Logger, _ *Config) *Collector { - c := &Collector{} +func New(logger log.Logger, config *Config) *Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &Collector{ + config: *config, + } + c.SetLogger(logger) return c diff --git a/pkg/types/regexp.go b/pkg/types/regexp.go new file mode 100644 index 00000000..5ba91308 --- /dev/null +++ b/pkg/types/regexp.go @@ -0,0 +1,8 @@ +package types + +import "regexp" + +var ( + RegExpAny = regexp.MustCompile(".+") + RegExpEmpty = regexp.MustCompile("^$") +) diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 089477dc..6619e4bb 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -20,3 +20,7 @@ func HasValue(v *string) bool { func IsEmpty(v *string) bool { return v == nil || *v == "" } + +func ToPTR[t any](v t) *t { + return &v +} diff --git a/pkg/wmi/wmi.go b/pkg/wmi/wmi.go index 92102ac9..168773af 100644 --- a/pkg/wmi/wmi.go +++ b/pkg/wmi/wmi.go @@ -62,6 +62,7 @@ func QueryAllForClass(_ interface{}, class string, logger log.Logger) string { return b.String() } +// Deprecated: Use QueryAllForClassWhere instead. func QueryAllWhere(src interface{}, where string, logger log.Logger) string { var b bytes.Buffer b.WriteString("SELECT * FROM ")