package serverimp import ( "context" "errors" "net" "net/http" "strings" "time" "github.com/go-chi/chi/v5" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/tech/sendico/pkg/api/routers" "github.com/tech/sendico/pkg/api/routers/health" "go.uber.org/zap" ) func (i *Imp) startMetrics(cfg *metricsConfig) { if i == nil { return } address := "" if cfg != nil { address = strings.TrimSpace(cfg.Address) } if address == "" { i.logger.Info("Metrics endpoint disabled") return } listener, err := net.Listen("tcp", address) if err != nil { i.logger.Error("Failed to bind metrics listener", zap.String("address", address), zap.Error(err)) return } router := chi.NewRouter() router.Handle("/metrics", promhttp.Handler()) var healthRouter routers.Health if hr, err := routers.NewHealthRouter(i.logger.Named("metrics"), router, ""); err != nil { i.logger.Warn("Failed to initialise health router", zap.Error(err)) } else { hr.SetStatus(health.SSStarting) healthRouter = hr } i.metricsHealth = healthRouter i.metricsSrv = &http.Server{ Addr: address, Handler: router, ReadHeaderTimeout: 5 * time.Second, } go func() { i.logger.Info("Prometheus endpoint listening", zap.String("address", address)) if err := i.metricsSrv.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) { i.logger.Error("Prometheus endpoint stopped unexpectedly", zap.Error(err)) if healthRouter != nil { healthRouter.SetStatus(health.SSTerminating) } } }() } func (i *Imp) shutdownMetrics(ctx context.Context) { if i.metricsHealth != nil { i.metricsHealth.SetStatus(health.SSTerminating) i.metricsHealth.Finish() i.metricsHealth = nil } if i.metricsSrv == nil { return } if err := i.metricsSrv.Shutdown(ctx); err != nil && !errors.Is(err, http.ErrServerClosed) { i.logger.Warn("Failed to stop metrics server", zap.Error(err)) } else { i.logger.Info("Metrics server stopped") } i.metricsSrv = nil } func (i *Imp) setMetricsStatus(status health.ServiceStatus) { if i == nil || i.metricsHealth == nil { return } i.metricsHealth.SetStatus(status) }