package main import ( "context" "fmt" "log" "net" "net/http" "os" "github.com/gorilla/handlers" "github.com/prometheus/client_golang/prometheus/promhttp" ) // HTTPOutput serves the Prometheus metrics endpoint. type HTTPOutput struct { server *http.Server config *HTTPOutputConfig } // NewHTTPOutput creates the HTTP output and applies the current configuration. func NewHTTPOutput() *HTTPOutput { s := new(HTTPOutput) s.server = &http.Server{} s.Reload() return s } // AddHandlers (re)builds the request multiplexer: the metrics endpoint plus a // landing page linking to it. func (s *HTTPOutput) AddHandlers() { mux := http.NewServeMux() s.server.Handler = mux mux.Handle(s.config.MetricsPath, handlers.CombinedLoggingHandler(os.Stdout, promhttp.HandlerFor(app.registry, promhttp.HandlerOpts{}))) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(` Drive Health Metrics

Drive Health Metrics

Metrics

`)) }) } // Reload refreshes the configuration, listen address, and handlers. func (s *HTTPOutput) Reload() { s.config = &app.config.HTTP s.server.Addr = fmt.Sprintf("%s:%d", s.config.BindAddr, s.config.Port) s.AddHandlers() } // OutputEnabled reports whether the HTTP output is enabled. func (s *HTTPOutput) OutputEnabled() bool { return s.config.Enabled } // Start launches the server and blocks until it is accepting connections. func (s *HTTPOutput) Start(ctx context.Context) { isListening := make(chan bool) go s.StartWithIsListening(ctx, isListening) <-isListening } // StartWithIsListening runs the server, signalling on isListening once the // listener is bound, and shutting down when the context is cancelled. func (s *HTTPOutput) StartWithIsListening(ctx context.Context, isListening chan bool) { if !s.config.Enabled { isListening <- true return } go func() { <-ctx.Done() if err := s.server.Shutdown(context.Background()); err != nil { log.Println("Error shutting down http server:", err) } }() log.Println("Starting http server:", s.server.Addr) l, err := net.Listen("tcp", s.server.Addr) if err != nil { log.Fatal("Listen: ", err) } isListening <- true if err := s.server.Serve(l); err != nil && err != http.ErrServerClosed { log.Println("HTTP server failure:", err) } }