diff --git a/cmd/prometheus/main.go b/cmd/prometheus/main.go index df69c8866..ab06d5cd6 100644 --- a/cmd/prometheus/main.go +++ b/cmd/prometheus/main.go @@ -558,6 +558,12 @@ func main() { } defer closer.Close() + listener, err := webHandler.Listener() + if err != nil { + level.Error(logger).Log("msg", "Unable to start web listener", "err", err) + os.Exit(1) + } + var g run.Group { // Termination handler. @@ -772,7 +778,7 @@ func main() { // Web handler. g.Add( func() error { - if err := webHandler.Run(ctxWeb); err != nil { + if err := webHandler.Run(ctxWeb, listener); err != nil { return errors.Wrapf(err, "error starting web server") } return nil diff --git a/web/web.go b/web/web.go index 8c3155983..78d640bbf 100644 --- a/web/web.go +++ b/web/web.go @@ -524,13 +524,13 @@ func (h *Handler) Reload() <-chan chan error { return h.reloadCh } -// Run serves the HTTP endpoints. -func (h *Handler) Run(ctx context.Context) error { +// Listener creates the TCP listener for web requests. +func (h *Handler) Listener() (net.Listener, error) { level.Info(h.logger).Log("msg", "Start listening for connections", "address", h.options.ListenAddress) listener, err := net.Listen("tcp", h.options.ListenAddress) if err != nil { - return err + return listener, err } listener = netutil.LimitListener(listener, h.options.MaxConnections) @@ -539,6 +539,11 @@ func (h *Handler) Run(ctx context.Context) error { conntrack.TrackWithName("http"), conntrack.TrackWithTracing()) + return listener, nil +} + +// Run serves the HTTP endpoints. +func (h *Handler) Run(ctx context.Context, listener net.Listener) error { operationName := nethttp.OperationNameFunc(func(r *http.Request) string { return fmt.Sprintf("%s %s", r.Method, r.URL.Path) }) diff --git a/web/web_test.go b/web/web_test.go index c32485db5..ef9e04795 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -143,11 +143,15 @@ func TestReadyAndHealthy(t *testing.T) { webHandler.config = &config.Config{} webHandler.notifier = ¬ifier.Manager{} + l, err := webHandler.Listener() + if err != nil { + panic(fmt.Sprintf("Unable to start web listener: %s", err)) + } ctx, cancel := context.WithCancel(context.Background()) defer cancel() go func() { - err := webHandler.Run(ctx) + err := webHandler.Run(ctx, l) if err != nil { panic(fmt.Sprintf("Can't start web handler:%s", err)) } @@ -252,10 +256,14 @@ func TestRoutePrefix(t *testing.T) { opts.Flags = map[string]string{} webHandler := New(nil, opts) + l, err := webHandler.Listener() + if err != nil { + panic(fmt.Sprintf("Unable to start web listener: %s", err)) + } ctx, cancel := context.WithCancel(context.Background()) defer cancel() go func() { - err := webHandler.Run(ctx) + err := webHandler.Run(ctx, l) if err != nil { panic(fmt.Sprintf("Can't start web handler:%s", err)) } @@ -420,12 +428,16 @@ func TestShutdownWithStaleConnection(t *testing.T) { webHandler.config = &config.Config{} webHandler.notifier = ¬ifier.Manager{} + l, err := webHandler.Listener() + if err != nil { + panic(fmt.Sprintf("Unable to start web listener: %s", err)) + } closed := make(chan struct{}) ctx, cancel := context.WithCancel(context.Background()) go func() { - err := webHandler.Run(ctx) + err := webHandler.Run(ctx, l) if err != nil { panic(fmt.Sprintf("Can't start web handler:%s", err)) } @@ -467,10 +479,14 @@ func TestHandleMultipleQuitRequests(t *testing.T) { webHandler := New(nil, opts) webHandler.config = &config.Config{} webHandler.notifier = ¬ifier.Manager{} + l, err := webHandler.Listener() + if err != nil { + panic(fmt.Sprintf("Unable to start web listener: %s", err)) + } ctx, cancel := context.WithCancel(context.Background()) closed := make(chan struct{}) go func() { - err := webHandler.Run(ctx) + err := webHandler.Run(ctx, l) if err != nil { panic(fmt.Sprintf("Can't start web handler:%s", err)) }