diff --git a/exporter.go b/exporter.go index 38d968b2c..42e805c63 100644 --- a/exporter.go +++ b/exporter.go @@ -4,6 +4,10 @@ package main import ( + //Its important that we do these first so that we can register with the windows service control ASAP to avoid timeouts + "github.com/prometheus-community/windows_exporter/initiate" + "github.com/prometheus-community/windows_exporter/log" + "encoding/json" "fmt" "net/http" @@ -16,12 +20,10 @@ import ( "sync" "time" - "golang.org/x/sys/windows/svc" - "github.com/StackExchange/wmi" "github.com/prometheus-community/windows_exporter/collector" "github.com/prometheus-community/windows_exporter/config" - "github.com/prometheus-community/windows_exporter/log" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -50,7 +52,6 @@ type prometheusVersion struct { const ( defaultCollectors = "cpu,cs,logical_disk,net,os,service,system,textfile" defaultCollectorsPlaceholder = "[defaults]" - serviceName = "windows_exporter" ) var ( @@ -289,7 +290,6 @@ func main() { "Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads.", ).Default("0.5").Float64() ) - log.AddFlags(kingpin.CommandLine) kingpin.Version(version.Print("windows_exporter")) kingpin.HelpFlag.Short('h') @@ -297,7 +297,7 @@ func main() { // Load values from configuration file(s). Executable flags must first be parsed, in order // to load the specified file(s). kingpin.Parse() - + log.Debug("Logging has Started") if *configFile != "" { resolver, err := config.NewResolver(*configFile) if err != nil { @@ -327,21 +327,6 @@ func main() { initWbem() - isService, err := svc.IsWindowsService() - if err != nil { - log.Fatal(err) - } - - stopCh := make(chan bool) - if isService { - go func() { - err = svc.Run(serviceName, &windowsExporterService{stopCh: stopCh}) - if err != nil { - log.Errorf("Failed to start service: %v", err) - } - }() - } - collectors, err := loadCollectors(*enabledCollectors) if err != nil { log.Fatalf("Couldn't load collectors: %s", err) @@ -421,7 +406,7 @@ func main() { }() for { - if <-stopCh { + if <-initiate.StopCh { log.Info("Shutting down windows_exporter") break } @@ -463,33 +448,6 @@ func withConcurrencyLimit(n int, next http.HandlerFunc) http.HandlerFunc { } } -type windowsExporterService struct { - stopCh chan<- bool -} - -func (s *windowsExporterService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) { - const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown - changes <- svc.Status{State: svc.StartPending} - changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted} -loop: - for { - select { - case c := <-r: - switch c.Cmd { - case svc.Interrogate: - changes <- c.CurrentStatus - case svc.Stop, svc.Shutdown: - s.stopCh <- true - break loop - default: - log.Error(fmt.Sprintf("unexpected control request #%d", c)) - } - } - } - changes <- svc.Status{State: svc.StopPending} - return -} - type metricsHandler struct { timeoutMargin float64 collectorFactory func(timeout time.Duration, requestedCollectors []string) (error, *windowsCollector) diff --git a/initiate/initiate.go b/initiate/initiate.go new file mode 100644 index 000000000..9b4c08e8a --- /dev/null +++ b/initiate/initiate.go @@ -0,0 +1,60 @@ +//This package allows us to initiate Time Sensitive components (Like registering the windows service) as early as possible in the startup process +package initiate + +import ( + "fmt" + + "github.com/prometheus-community/windows_exporter/log" + "golang.org/x/sys/windows/svc" +) + +const ( + serviceName = "windows_exporter" +) + +type windowsExporterService struct { + stopCh chan<- bool +} + +func (s *windowsExporterService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) { + const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown + changes <- svc.Status{State: svc.StartPending} + changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted} +loop: + for { + select { + case c := <-r: + switch c.Cmd { + case svc.Interrogate: + changes <- c.CurrentStatus + case svc.Stop, svc.Shutdown: + log.Debug("Service Stop Received") + s.stopCh <- true + break loop + default: + log.Error(fmt.Sprintf("unexpected control request #%d", c)) + } + } + } + changes <- svc.Status{State: svc.StopPending} + return +} + +var StopCh = make(chan bool) + +func init() { + log.Debug("Checking if We are a service") + isService, err := svc.IsWindowsService() + if err != nil { + log.Fatal(err) + } + log.Debug("Attempting to start exporter service") + if isService { + go func() { + err = svc.Run(serviceName, &windowsExporterService{stopCh: StopCh}) + if err != nil { + log.Errorf("Failed to start service: %v", err) + } + }() + } +}