90 lines
2.4 KiB
Go
90 lines
2.4 KiB
Go
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(`<html>
|
|
<head><title>Drive Health Metrics</title></head>
|
|
<body>
|
|
<h1>Drive Health Metrics</h1>
|
|
<p><a href='` + s.config.MetricsPath + `'>Metrics</a></p>
|
|
</body>
|
|
</html>`))
|
|
})
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
}
|