From eff124250ff5ce52b47fd13827fe7620f0efdb47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sun, 24 Nov 2024 15:53:56 +0100 Subject: [PATCH] chore: move exporter binary to cmd package (#1768) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- .golangci.yaml | 5 +- .promu.yml | 1 + cmd/windows_exporter/doc.go | 195 ++++++++++++++++++++ exporter.go => cmd/windows_exporter/main.go | 0 cmd/windows_exporter/winres/icon.png | Bin 0 -> 10903 bytes cmd/windows_exporter/winres/winres.json | 56 ++++++ internal/log/eventlog/eventlog.go | 4 +- internal/windowsservice/doc.go | 23 +++ internal/windowsservice/init.go | 60 ++++++ internal/windowsservice/log.go | 44 +++++ internal/windowsservice/windowsservice.go | 69 +------ winres/winres.json | 52 ------ 12 files changed, 395 insertions(+), 114 deletions(-) create mode 100644 cmd/windows_exporter/doc.go rename exporter.go => cmd/windows_exporter/main.go (100%) create mode 100644 cmd/windows_exporter/winres/icon.png create mode 100644 cmd/windows_exporter/winres/winres.json create mode 100644 internal/windowsservice/doc.go create mode 100644 internal/windowsservice/init.go create mode 100644 internal/windowsservice/log.go delete mode 100644 winres/winres.json diff --git a/.golangci.yaml b/.golangci.yaml index 2d625578a..49662f63e 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -26,7 +26,10 @@ linters: - wrapcheck run: - timeout: 5m + timeout: 15m + +output: + sort-results: true linters-settings: gosec: diff --git a/.promu.yml b/.promu.yml index 911167003..9a736cb09 100644 --- a/.promu.yml +++ b/.promu.yml @@ -8,6 +8,7 @@ repository: build: binaries: - name: windows_exporter + path: ./cmd/windows_exporter tags: all: - trimpath diff --git a/cmd/windows_exporter/doc.go b/cmd/windows_exporter/doc.go new file mode 100644 index 000000000..244aa7fae --- /dev/null +++ b/cmd/windows_exporter/doc.go @@ -0,0 +1,195 @@ +// Copyright 2024 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* +The main package for the windows_exporter executable. + +usage: windows_exporter [] + +A metrics collector for Windows. + +Flags: + + -h, --[no-]help Show context-sensitive help (also try + --help-long and --help-man). + --config.file=CONFIG.FILE YAML configuration file to use. Values set in + this file will be overridden by CLI flags. + --[no-]config.file.insecure-skip-verify + Skip TLS verification in loading YAML + configuration. + --web.listen-address=:9182 ... + Addresses on which to expose metrics and web + interface. Repeatable for multiple addresses. + Examples: `:9100` or `[::1]:9100` for http, + `vsock://:9100` for vsock + --web.config.file="" Path to configuration file that can + enable TLS or authentication. See: + https://github.com/prometheus/exporter-toolkit/blob/master/docs/web-configuration.md + --telemetry.path="/metrics" + URL path for surfacing collected metrics. + --[no-]web.disable-exporter-metrics + Exclude metrics about the exporter itself + (promhttp_*, process_*, go_*). + --telemetry.max-requests=5 + Maximum number of concurrent requests. 0 to + disable. + --collectors.enabled="cpu,cs,memory,logical_disk,physical_disk,net,os,service,system" + Comma-separated list of collectors to use. + Use '[defaults]' as a placeholder for all the + collectors enabled by default. + --scrape.timeout-margin=0.5 + Seconds to subtract from the timeout allowed by + the client. Tune to allow for overhead or high + loads. + --[no-]debug.enabled If true, windows_exporter will expose debug + endpoints under /debug/pprof. + --process.priority="normal" + Priority of the exporter process. Higher + priorities may improve exporter responsiveness + during periods of system load. Can be one of + ["realtime", "high", "abovenormal", "normal", + "belownormal", "low"] + --log.level=info Only log messages with the given severity or + above. One of: [debug, info, warn, error] + --log.format=logfmt Output format of log messages. One of: [logfmt, + json] + --log.file=stderr Output file of log messages. One of [stdout, + stderr, eventlog, ] + --[no-]version Show application version. + --collector.scheduled_task.exclude="" + Regexp of tasks to exclude. Task path must + both match include and not match exclude to be + included. + --collector.scheduled_task.include=".+" + Regexp of tasks to include. Task path must + both match include and not match exclude to be + included. + --[no-]collector.updates.online + Whether to search for updates online. + --collector.updates.scrape-interval=6h0m0s + Define the interval of scraping Windows Update + information. + --[no-]collector.exchange.list + List the collectors along with their perflib + object name/ids + --collector.exchange.enabled="ADAccessProcesses,TransportQueues,HttpProxy,ActiveSync,AvailabilityService,OutlookWebAccess,Autodiscover,WorkloadManagement,RpcClientAccess,MapiHttpEmsmdb" + Comma-separated list of collectors to use. + Defaults to all, if not specified. + --collector.net.nic-exclude="" + Regexp of NIC:s to exclude. NIC name must + both match include and not match exclude to be + included. + --collector.net.nic-include=".+" + Regexp of NIC:s to include. NIC name must + both match include and not match exclude to be + included. + --collector.net.enabled="metrics,nic_addresses" + Comma-separated list of collectors to use. + Defaults to all, if not specified. + --collector.mscluster.enabled="cluster,network,node,resource,resourcegroup" + Comma-separated list of collectors to use. + --collector.mssql.enabled="accessmethods,availreplica,bufman,databases,dbreplica,genstats,locks,memmgr,sqlerrors,sqlstats,transactions,waitstats" + Comma-separated list of collectors to use. + --collector.mssql.port=1433 + Port of MSSQL server used for + windows_mssql_info metric. + --collector.physical_disk.disk-exclude="" + Regexp of disks to exclude. Disk number must + both match include and not match exclude to be + included. + --collector.physical_disk.disk-include=".+" + Regexp of disks to include. Disk number must + both match include and not match exclude to be + included. + --collector.textfile.directories="C:\\Users\\Jan\\GolandProjects\\windows_exporter\\textfile_inputs" + Directory or Directories to read text files + with metrics from. + --collector.filetime.file-patterns="" + Comma-separated list of file patterns. + Each pattern is a glob pattern that can + contain `*`, `?`, and `**` (recursive). See + https://github.com/bmatcuk/doublestar#patterns + --collector.iis.app-exclude="" + Regexp of apps to exclude. App name must both + match include and not match exclude to be + included. + --collector.iis.app-include=".+" + Regexp of apps to include. App name must both + match include and not match exclude to be + included. + --collector.iis.site-exclude="" + Regexp of sites to exclude. Site name must + both match include and not match exclude to be + included. + --collector.iis.site-include=".+" + Regexp of sites to include. Site name must + both match include and not match exclude to be + included. + --collector.perfdata.objects="" + Objects of performance data to observe. + See docs for more information on how to use + this flag. By default, no objects are observed. + --collector.printer.include=".+" + Regular expression to match printers to collect + metrics for + --collector.printer.exclude="" + Regular expression to match printers to exclude + --collector.process.exclude="" + Regexp of processes to exclude. Process name + must both match include and not match exclude + to be included. + --collector.process.include=".+" + Regexp of processes to include. Process name + must both match include and not match exclude + to be included. + --[no-]collector.process.iis + Enable IIS worker process name queries. + May cause the collector to leak memory. + --collector.hyperv.enabled="datastore,dynamic_memory_balancer,dynamic_memory_vm,hypervisor_logical_processor,hypervisor_root_partition,hypervisor_root_virtual_processor,hypervisor_virtual_processor,legacy_network_adapter,virtual_machine_health_summary,virtual_machine_vid_partition,virtual_network_adapter,virtual_network_adapter_drop_reasons,virtual_smb,virtual_storage_device,virtual_switch" + Comma-separated list of collectors to use. + --collector.logical_disk.volume-exclude="" + Regexp of volumes to exclude. Volume name must + both match include and not match exclude to be + included. + --collector.logical_disk.volume-include=".+" + Regexp of volumes to include. Volume name must + both match include and not match exclude to be + included. + --collector.smtp.server-exclude="" + Regexp of virtual servers to exclude. Server + name must both match include and not match + exclude to be included. + --collector.smtp.server-include=".+" + Regexp of virtual servers to include. Server + name must both match include and not match + exclude to be included. + --collector.tcp.enabled="metrics,connections_state" + Comma-separated list of collectors to use. + Defaults to all, if not specified. + --collector.dfsr.sources-enabled="connection,folder,volume" + Comma-separated list of DFSR Perflib sources to + use. + --collector.service.exclude="" + Regexp of service to exclude. Service name (not + the display name!) must both match include and + not match exclude to be included. + --collector.service.include=".+" + Regexp of service to include. Process name (not + the display name!) must both match include and + not match exclude to be included. + --collector.time.enabled="system_time,ntp" + Comma-separated list of collectors to use. + Defaults to all, if not specified. ntp may not + available on all systems. +*/ +package main diff --git a/exporter.go b/cmd/windows_exporter/main.go similarity index 100% rename from exporter.go rename to cmd/windows_exporter/main.go diff --git a/cmd/windows_exporter/winres/icon.png b/cmd/windows_exporter/winres/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..998aadec95cee34fb7af937f7e81fbcdb303b4f2 GIT binary patch literal 10903 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 O0d*B^<#I)2=>Gw}mLLuQ literal 0 HcmV?d00001 diff --git a/cmd/windows_exporter/winres/winres.json b/cmd/windows_exporter/winres/winres.json new file mode 100644 index 000000000..35eda4075 --- /dev/null +++ b/cmd/windows_exporter/winres/winres.json @@ -0,0 +1,56 @@ +{ + "RT_GROUP_ICON": { + "APP": { + "0000": [ + "icon.png" + ] + } + }, + "RT_MANIFEST": { + "#1": { + "0409": { + "description": "A Prometheus exporter for Windows machines.", + "minimum-os": "win7", + "execution-level": "as invoker", + "ui-access": false, + "auto-elevate": false, + "dpi-awareness": "system", + "disable-theming": false, + "disable-window-filtering": false, + "high-resolution-scrolling-aware": false, + "ultra-high-resolution-scrolling-aware": false, + "long-path-aware": false, + "printer-driver-isolation": false, + "gdi-scaling": false, + "segment-heap": false, + "use-common-controls-v6": false + } + } + }, + "RT_VERSION": { + "#1": { + "0000": { + "fixed": { + "file_version": "0.0.0.0", + "product_version": "0.0.0.0" + }, + "info": { + "0409": { + "Comments": "", + "CompanyName": "Prometheus Community", + "FileDescription": "A Prometheus exporter for Windows machines.", + "FileVersion": "", + "InternalName": "windows_exporter", + "LegalCopyright": "", + "LegalTrademarks": "", + "OriginalFilename": "", + "PrivateBuild": "", + "ProductName": "windows_exporter", + "ProductVersion": "", + "SpecialBuild": "" + } + } + } + } + } +} diff --git a/internal/log/eventlog/eventlog.go b/internal/log/eventlog/eventlog.go index 47a50a07f..04abccaab 100644 --- a/internal/log/eventlog/eventlog.go +++ b/internal/log/eventlog/eventlog.go @@ -28,7 +28,7 @@ const ( // NeLogOemCode is a generic error log entry for OEMs to use to // elog errors from OEM value added services. // See: https://github.com/microsoft/win32metadata/blob/2f3c5282ce1024a712aeccd90d3aa50bf7a49e27/generation/WinSDK/RecompiledIdlHeaders/um/LMErrlog.h#L824-L845 - neLogOemCode = uint32(3299) + NeLogOemCode = uint32(3299) ) // Interface guard. @@ -62,5 +62,5 @@ func (w *Writer) Write(p []byte) (int, error) { ss := []*uint16{msg, nil, nil, nil, nil, nil, nil, nil, nil} - return len(p), windows.ReportEvent(w.handle, eType, 0, neLogOemCode, 0, 9, 0, &ss[0], nil) + return len(p), windows.ReportEvent(w.handle, eType, 0, NeLogOemCode, 0, 9, 0, &ss[0], nil) } diff --git a/internal/windowsservice/doc.go b/internal/windowsservice/doc.go new file mode 100644 index 000000000..69319d48d --- /dev/null +++ b/internal/windowsservice/doc.go @@ -0,0 +1,23 @@ +// Copyright 2024 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build windows + +// Package windowsservice allows initiating time-sensitive components like registering the Windows service +// as early as possible in the startup process. +// init functions are called in the order they are declared, so this package should be imported first. +// Declare imports on this package should be avoided where possible. +// +// Ref: https://github.com/prometheus-community/windows_exporter/issues/551#issuecomment-1220774835 + +package windowsservice diff --git a/internal/windowsservice/init.go b/internal/windowsservice/init.go new file mode 100644 index 000000000..273811197 --- /dev/null +++ b/internal/windowsservice/init.go @@ -0,0 +1,60 @@ +// Copyright 2024 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package windowsservice + +import ( + "fmt" + "os" + + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/svc" +) + +var ( + // IsService is true if the exporter is running as a Windows service. + IsService bool + // ExitCodeCh is a channel to send the exit code return from the [github.com/prometheus-community/windows_exporter/cmd/windows_exporter] function to the service manager. + ExitCodeCh = make(chan int) + + // StopCh is a channel to send a signal to the service manager that the service is stopping. + StopCh = make(chan struct{}) +) + +//nolint:gochecknoinits // An init function is required to communicate with the Windows service manager early in the program. +func init() { + var err error + + IsService, err = svc.IsWindowsService() + if err != nil { + if err := logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("failed to detect service: %v", err)); err != nil { + os.Exit(2) + } + + os.Exit(1) + } + + if !IsService { + return + } + + if err := logToEventToLog(windows.EVENTLOG_INFORMATION_TYPE, "attempting to start exporter service"); err != nil { + os.Exit(2) + } + + go func() { + if err := svc.Run(serviceName, &windowsExporterService{}); err != nil { + _ = logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("failed to start service: %v", err)) + } + }() +} diff --git a/internal/windowsservice/log.go b/internal/windowsservice/log.go new file mode 100644 index 000000000..353b04f45 --- /dev/null +++ b/internal/windowsservice/log.go @@ -0,0 +1,44 @@ +// Copyright 2024 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build windows + +package windowsservice + +import ( + "fmt" + + wineventlog "github.com/prometheus-community/windows_exporter/internal/log/eventlog" + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/svc/eventlog" +) + +// logToEventToLog logs a message to the Windows event log. +func logToEventToLog(eType uint16, msg string) error { + eventLog, err := eventlog.Open("windows_exporter") + if err != nil { + return fmt.Errorf("failed to open event log: %w", err) + } + defer func(eventLog *eventlog.Log) { + _ = eventLog.Close() + }(eventLog) + + p, err := windows.UTF16PtrFromString(msg) + if err != nil { + return fmt.Errorf("error convert string to UTF-16: %w", err) + } + + ss := []*uint16{p, nil, nil, nil, nil, nil, nil, nil, nil} + + return windows.ReportEvent(eventLog.Handle, eType, 0, wineventlog.NeLogOemCode, 0, 9, 0, &ss[0], nil) +} diff --git a/internal/windowsservice/windowsservice.go b/internal/windowsservice/windowsservice.go index 106b27bd4..0be685b0c 100644 --- a/internal/windowsservice/windowsservice.go +++ b/internal/windowsservice/windowsservice.go @@ -11,18 +11,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -// windowsservice allows us to initiate Time Sensitive components (Like registering the windows service) as early as possible in the startup process //go:build windows package windowsservice import ( "fmt" - "os" "golang.org/x/sys/windows" "golang.org/x/sys/windows/svc" - "golang.org/x/sys/windows/svc/eventlog" ) const ( @@ -31,83 +28,37 @@ const ( type windowsExporterService struct{} +// Execute is the entry point for the Windows service manager. func (s *windowsExporterService) Execute(_ []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (bool, uint32) { - const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown changes <- svc.Status{State: svc.StartPending} - changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted} + changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown} for { select { case exitCodeCh := <-ExitCodeCh: + // Stop the service if an exit code from the main function is received. changes <- svc.Status{State: svc.StopPending} return true, uint32(exitCodeCh) case c := <-r: + // Handle the service control request. switch c.Cmd { case svc.Interrogate: changes <- c.CurrentStatus case svc.Stop, svc.Shutdown: + // Stop the service if a stop or shutdown request is received. _ = logToEventToLog(windows.EVENTLOG_INFORMATION_TYPE, "service stop received") changes <- svc.Status{State: svc.StopPending} - return false, 0 + // Send a signal to the main function to stop the service. + StopCh <- struct{}{} + + // Wait for the main function to stop the service. + return false, uint32(<-ExitCodeCh) default: _ = logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("unexpected control request #%d", c)) } } } } - -var ( - IsService bool - ExitCodeCh = make(chan int) - StopCh = make(chan struct{}) -) - -//nolint:gochecknoinits -func init() { - var err error - - IsService, err = svc.IsWindowsService() - if err != nil { - err = logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("Failed to detect service: %v", err)) - if err != nil { - os.Exit(2) - } - - os.Exit(1) - } - - if IsService { - err = logToEventToLog(windows.EVENTLOG_INFORMATION_TYPE, "Attempting to start exporter service") - - go func() { - err = svc.Run(serviceName, &windowsExporterService{}) - if err != nil { - _ = logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("Failed to start service: %v", err)) - } - - StopCh <- struct{}{} - }() - } -} - -func logToEventToLog(eType uint16, msg string) error { - eventLog, err := eventlog.Open("windows_exporter") - if err != nil { - return fmt.Errorf("failed to open event log: %w", err) - } - defer func(eventLog *eventlog.Log) { - _ = eventLog.Close() - }(eventLog) - - p, err := windows.UTF16PtrFromString(msg) - if err != nil { - return fmt.Errorf("error convert string to UTF-16: %w", err) - } - - ss := []*uint16{p, nil, nil, nil, nil, nil, nil, nil, nil} - - return windows.ReportEvent(eventLog.Handle, eType, 0, 3299, 0, 9, 0, &ss[0], nil) -} diff --git a/winres/winres.json b/winres/winres.json deleted file mode 100644 index 1efcfb851..000000000 --- a/winres/winres.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "RT_GROUP_ICON": { - "APP": {} - }, - "RT_MANIFEST": { - "#1": { - "0409": { - "description": "A Prometheus exporter for Windows machines.", - "minimum-os": "win7", - "execution-level": "as invoker", - "ui-access": false, - "auto-elevate": false, - "dpi-awareness": "system", - "disable-theming": false, - "disable-window-filtering": false, - "high-resolution-scrolling-aware": false, - "ultra-high-resolution-scrolling-aware": false, - "long-path-aware": false, - "printer-driver-isolation": false, - "gdi-scaling": false, - "segment-heap": false, - "use-common-controls-v6": false - } - } - }, - "RT_VERSION": { - "#1": { - "0000": { - "fixed": { - "file_version": "0.0.0.0", - "product_version": "0.0.0.0" - }, - "info": { - "0409": { - "Comments": "", - "CompanyName": "Prometheus Community", - "FileDescription": "A Prometheus exporter for Windows machines.", - "FileVersion": "", - "InternalName": "", - "LegalCopyright": "", - "LegalTrademarks": "", - "OriginalFilename": "", - "PrivateBuild": "", - "ProductName": "windows_exporter", - "ProductVersion": "", - "SpecialBuild": "" - } - } - } - } - } -}