| 84 | } |
| 85 | |
| 86 | func (reg *Registry) AddServerRuntimeHooks(serverId string, tlsConfigPromise TLSConfigPromise) { |
| 87 | if reg.params.Config.PrometheusServeAddr != "" { |
| 88 | // The Handler function provides a default handler to expose metrics |
| 89 | // via an HTTP server. "/metrics" is the usual endpoint for that. |
| 90 | mux := http.NewServeMux() |
| 91 | mux.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{})) |
| 92 | srv := http.Server{ |
| 93 | Addr: reg.params.Config.PrometheusServeAddr, |
| 94 | Handler: mux, |
| 95 | } |
| 96 | |
| 97 | reg.params.JobGroup.Add(job.OneShot(serverId, func(ctx context.Context, _ cell.Health) error { |
| 98 | tlsEnabled := tlsConfigPromise != nil |
| 99 | reg.params.Logger.Info("Serving prometheus metrics", |
| 100 | logfields.Server, serverId, |
| 101 | logfields.Address, reg.params.Config.PrometheusServeAddr, |
| 102 | logfields.TLS, tlsEnabled, |
| 103 | ) |
| 104 | |
| 105 | listenAndServeFn := srv.ListenAndServe |
| 106 | if tlsEnabled { |
| 107 | reg.params.Logger.Info("Waiting for TLS certificates to become available") |
| 108 | tlsConfig, err := tlsConfigPromise.Await(ctx) |
| 109 | if err != nil { |
| 110 | return err |
| 111 | } |
| 112 | srv.TLSConfig = tlsConfig |
| 113 | listenAndServeFn = func() error { |
| 114 | return srv.ListenAndServeTLS("", "") |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | if err := listenAndServeFn(); err != nil && !errors.Is(err, http.ErrServerClosed) { |
| 119 | reg.params.Shutdowner.Shutdown(hive.ShutdownWithError(err)) |
| 120 | } |
| 121 | return nil |
| 122 | })) |
| 123 | reg.params.Lifecycle.Append(cell.Hook{ |
| 124 | OnStop: func(hc cell.HookContext) error { |
| 125 | return srv.Shutdown(hc) |
| 126 | }, |
| 127 | }) |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | // NewRegistry constructs a new registry that is not initialized with |
| 132 | // hive/legacy metrics and has registered its runtime hooks yet. |