From e1c717be709b08f3230f74ce7ed0ba6c9c1519e2 Mon Sep 17 00:00:00 2001 From: ThinkChaos Date: Wed, 3 Apr 2024 10:31:34 -0400 Subject: [PATCH] refactor: switch metrics to Service pattern --- cmd/serve.go | 5 ++++ config/config.go | 14 +++++---- config/doh_service.go | 12 ++++++-- metrics/metrics.go | 17 ++++------- metrics/metrics_event_publisher.go | 4 +-- metrics/service.go | 48 ++++++++++++++++++++++++++++++ server/server.go | 7 ++--- server/server_endpoints.go | 3 -- 8 files changed, 81 insertions(+), 29 deletions(-) create mode 100644 metrics/service.go diff --git a/cmd/serve.go b/cmd/serve.go index 6520e3a4c..4587cba10 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -10,6 +10,7 @@ import ( "github.com/0xERR0R/blocky/config" "github.com/0xERR0R/blocky/evt" "github.com/0xERR0R/blocky/log" + "github.com/0xERR0R/blocky/metrics" "github.com/0xERR0R/blocky/server" "github.com/0xERR0R/blocky/util" @@ -47,6 +48,10 @@ func startServer(_ *cobra.Command, _ []string) error { ctx, cancelFn := context.WithCancel(context.Background()) defer cancelFn() + if cfg.Prometheus.Enable { + metrics.StartCollection() + } + srv, err := server.NewServer(ctx, cfg) if err != nil { return fmt.Errorf("can't start server: %w", err) diff --git a/config/config.go b/config/config.go index e5c43a95e..8b04a7434 100644 --- a/config/config.go +++ b/config/config.go @@ -271,7 +271,8 @@ type Config struct { // The `yaml` struct tags are just for manual testing, // and require replacing `yaml:"-"` in Config to work. type Services struct { - DoH DoHService `yaml:"dns-over-https"` + DoH DoHService `yaml:"dns-over-https"` + Metrics MetricsService `yaml:"metrics"` } type Ports struct { @@ -618,11 +619,14 @@ func (cfg *Config) validate(logger *logrus.Entry) { // This should be replaced with a migration once everything from Ports is supported in Services. // Done this way for now to avoid creating temporary generic services and updating all Ports related code at once. func (cfg *Config) CopyPortsToServices() { + httpAddrs := httpAddrs{ + HTTPAddrs: HTTPAddrs{HTTP: cfg.Ports.HTTP}, + HTTPSAddrs: HTTPSAddrs{HTTPS: cfg.Ports.HTTPS}, + } + cfg.Services = Services{ - DoH: DoHService{Addrs: DoHAddrs{ - HTTPAddrs: HTTPAddrs{HTTP: cfg.Ports.HTTP}, - HTTPSAddrs: HTTPSAddrs{HTTPS: cfg.Ports.HTTPS}, - }}, + DoH: DoHService{Addrs: httpAddrs}, + Metrics: MetricsService{Addrs: httpAddrs}, } } diff --git a/config/doh_service.go b/config/doh_service.go index 6ac98ed3e..27c429448 100644 --- a/config/doh_service.go +++ b/config/doh_service.go @@ -1,10 +1,16 @@ package config -type DoHService struct { - Addrs DoHAddrs `yaml:"addrs"` +type ( + DoHService httpService + MetricsService httpService +) + +// httpService can be used by any service that uses HTTP(S). +type httpService struct { + Addrs httpAddrs `yaml:"addrs"` } -type DoHAddrs struct { +type httpAddrs struct { HTTPAddrs `yaml:",inline"` HTTPSAddrs `yaml:",inline"` } diff --git a/metrics/metrics.go b/metrics/metrics.go index c8767917a..907d7d384 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -1,12 +1,8 @@ package metrics import ( - "github.com/0xERR0R/blocky/config" - - "github.com/go-chi/chi/v5" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" - "github.com/prometheus/client_golang/prometheus/promhttp" ) //nolint:gochecknoglobals @@ -17,12 +13,9 @@ func RegisterMetric(c prometheus.Collector) { _ = reg.Register(c) } -// Start starts prometheus endpoint -func Start(router *chi.Mux, cfg config.Metrics) { - if cfg.Enable { - _ = reg.Register(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{})) - _ = reg.Register(collectors.NewGoCollector()) - router.Handle(cfg.Path, promhttp.InstrumentMetricHandler(reg, - promhttp.HandlerFor(reg, promhttp.HandlerOpts{}))) - } +func StartCollection() { + _ = reg.Register(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{})) + _ = reg.Register(collectors.NewGoCollector()) + + registerEventListeners() } diff --git a/metrics/metrics_event_publisher.go b/metrics/metrics_event_publisher.go index effc3f761..fda4e5a76 100644 --- a/metrics/metrics_event_publisher.go +++ b/metrics/metrics_event_publisher.go @@ -11,8 +11,8 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -// RegisterEventListeners registers all metric handlers by the event bus -func RegisterEventListeners() { +// registerEventListeners registers all metric handlers on the event bus +func registerEventListeners() { registerBlockingEventListeners() registerCachingEventListeners() registerApplicationEventListeners() diff --git a/metrics/service.go b/metrics/service.go new file mode 100644 index 000000000..2bac7199a --- /dev/null +++ b/metrics/service.go @@ -0,0 +1,48 @@ +package metrics + +import ( + "github.com/0xERR0R/blocky/config" + "github.com/0xERR0R/blocky/service" + "github.com/0xERR0R/blocky/util" + "github.com/go-chi/chi/v5" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +// Service implements service.HTTPService. +type Service struct { + service.HTTPInfo +} + +func NewService(cfg config.MetricsService, metricsCfg config.Metrics) *Service { + endpoints := util.ConcatSlices( + service.EndpointsFromAddrs(service.HTTPProtocol, cfg.Addrs.HTTP), + service.EndpointsFromAddrs(service.HTTPSProtocol, cfg.Addrs.HTTPS), + ) + + if !metricsCfg.Enable || len(endpoints) == 0 { + // Avoid setting up collectors and listeners + return new(Service) + } + + s := &Service{ + HTTPInfo: service.HTTPInfo{ + Info: service.Info{ + Name: "Metrics", + Endpoints: endpoints, + }, + + Mux: chi.NewMux(), + }, + } + + s.Mux.Handle( + metricsCfg.Path, + promhttp.InstrumentMetricHandler(reg, promhttp.HandlerFor(reg, promhttp.HandlerOpts{})), + ) + + return s +} + +func (s *Service) Merge(other service.Service) (service.Merger, error) { + return service.MergeHTTP(s, other) +} diff --git a/server/server.go b/server/server.go index 53518bb8f..5a6bf9c70 100644 --- a/server/server.go +++ b/server/server.go @@ -118,8 +118,6 @@ func newTLSConfig(cfg *config.Config) (*tls.Config, error) { } // NewServer creates new server instance with passed config -// -//nolint:funlen func NewServer(ctx context.Context, cfg *config.Config) (server *Server, err error) { cfg.CopyPortsToServices() @@ -142,8 +140,6 @@ func NewServer(ctx context.Context, cfg *config.Config) (server *Server, err err return nil, err } - metrics.RegisterEventListeners() - bootstrap, err := resolver.NewBootstrap(ctx, cfg) if err != nil { return nil, err @@ -194,6 +190,7 @@ func (s *Server) createServices() ([]service.Service, error) { res := []service.Service{ newHTTPMiscService(s.cfg, openAPIImpl), newDoHService(s.cfg.Services.DoH, s.handleReq), + metrics.NewService(s.cfg.Services.Metrics, s.cfg.Prometheus), } // Remove services the user has not enabled @@ -244,6 +241,8 @@ func createListeners(ctx context.Context, cfg *config.Config, tlsCfg *tls.Config newListeners(ctx, service.HTTPSProtocol, cfg.Ports.HTTPS, listenTLS, res), newListeners(ctx, service.HTTPProtocol, cfg.Services.DoH.Addrs.HTTP, service.ListenTCP, res), newListeners(ctx, service.HTTPSProtocol, cfg.Services.DoH.Addrs.HTTPS, listenTLS, res), + newListeners(ctx, service.HTTPProtocol, cfg.Services.Metrics.Addrs.HTTP, service.ListenTCP, res), + newListeners(ctx, service.HTTPSProtocol, cfg.Services.Metrics.Addrs.HTTPS, listenTLS, res), ) if err != nil { return nil, err diff --git a/server/server_endpoints.go b/server/server_endpoints.go index 81d3e675b..c5e8dd433 100644 --- a/server/server_endpoints.go +++ b/server/server_endpoints.go @@ -7,7 +7,6 @@ import ( "net" "net/http" - "github.com/0xERR0R/blocky/metrics" "github.com/0xERR0R/blocky/resolver" "github.com/0xERR0R/blocky/api" @@ -74,8 +73,6 @@ func createHTTPRouter(cfg *config.Config, openAPIImpl api.StrictServerInterface) configureRootHandler(cfg, router) - metrics.Start(router, cfg.Prometheus) - return router }