From 183205cba4d0559fa40a2b71cde9e7b9c1f3876b Mon Sep 17 00:00:00 2001 From: hfuss Date: Sat, 15 Feb 2025 14:20:12 -0500 Subject: [PATCH 1/2] [ffapi] Renaming Metrics Server to Monitoring and Allowing Additional Routes Signed-off-by: hfuss --- pkg/ffapi/apiserver.go | 41 +++++++++++++++++++++-------------- pkg/ffapi/apiserver_config.go | 12 +++++----- pkg/ffapi/apiserver_test.go | 32 +++++++++++++-------------- 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/pkg/ffapi/apiserver.go b/pkg/ffapi/apiserver.go index d1d639a3..bd2d8a46 100644 --- a/pkg/ffapi/apiserver.go +++ b/pkg/ffapi/apiserver.go @@ -61,9 +61,9 @@ type apiServer[T any] struct { apiDynamicPublicURLHeader string alwaysPaginate bool handleYAML bool - metricsEnabled bool + monitoringEnabled bool metricsPath string - metricsPublicURL string + monitoringPublicURL string mux *mux.Router APIServerOptions[T] @@ -72,10 +72,11 @@ type apiServer[T any] struct { type APIServerOptions[T any] struct { MetricsRegistry metric.MetricsRegistry Routes []*Route + MonitoringRoutes []*Route EnrichRequest func(r *APIRequest) (T, error) Description string APIConfig config.Section - MetricsConfig config.Section + MonitoringConfig config.Section CORSConfig config.Section FavIcon16 []byte FavIcon32 []byte @@ -99,8 +100,8 @@ func NewAPIServer[T any](ctx context.Context, options APIServerOptions[T]) APISe maxFilterSkip: options.APIConfig.GetUint64(ConfAPIMaxFilterSkip), requestTimeout: options.APIConfig.GetDuration(ConfAPIRequestTimeout), requestMaxTimeout: options.APIConfig.GetDuration(ConfAPIRequestMaxTimeout), - metricsEnabled: options.MetricsConfig.GetBool(ConfMetricsServerEnabled), - metricsPath: options.MetricsConfig.GetString(ConfMetricsServerPath), + monitoringEnabled: options.MonitoringConfig.GetBool(ConfMonitoringServerEnabled), + metricsPath: options.MonitoringConfig.GetString(ConfMonitoringServerMetricsPath), alwaysPaginate: options.APIConfig.GetBool(ConfAPIAlwaysPaginate), handleYAML: options.HandleYAML, apiDynamicPublicURLHeader: options.APIConfig.GetString(ConfAPIDynamicPublicURLHeader), @@ -142,7 +143,7 @@ func (as *apiServer[T]) Serve(ctx context.Context) (err error) { }() httpErrChan := make(chan error) - metricsErrChan := make(chan error) + monitoringErrChan := make(chan error) apiHTTPServer, err := httpserver.NewHTTPServer(ctx, "api", as.MuxRouter(ctx), httpErrChan, as.APIConfig, as.CORSConfig, &httpserver.ServerOptions{ MaximumRequestTimeout: as.requestMaxTimeout, @@ -153,20 +154,20 @@ func (as *apiServer[T]) Serve(ctx context.Context) (err error) { as.apiPublicURL = buildPublicURL(as.APIConfig, apiHTTPServer.Addr()) go apiHTTPServer.ServeHTTP(ctx) - if as.metricsEnabled { - metricsHTTPServer, err := httpserver.NewHTTPServer(ctx, "metrics", as.createMetricsMuxRouter(ctx), metricsErrChan, as.MetricsConfig, as.CORSConfig, &httpserver.ServerOptions{ + if as.monitoringEnabled { + monitoringHTTPServer, err := httpserver.NewHTTPServer(ctx, "monitoring", as.createMonitoringMuxRouter(ctx), monitoringErrChan, as.MonitoringConfig, as.CORSConfig, &httpserver.ServerOptions{ MaximumRequestTimeout: as.requestMaxTimeout, }) if err != nil { return err } - as.metricsPublicURL = buildPublicURL(as.MetricsConfig, apiHTTPServer.Addr()) - go metricsHTTPServer.ServeHTTP(ctx) + as.monitoringPublicURL = buildPublicURL(as.MonitoringConfig, apiHTTPServer.Addr()) + go monitoringHTTPServer.ServeHTTP(ctx) } started = true close(as.started) - return as.waitForServerStop(httpErrChan, metricsErrChan) + return as.waitForServerStop(httpErrChan, monitoringErrChan) } func (as *apiServer[T]) Started() <-chan struct{} { @@ -177,11 +178,11 @@ func (as *apiServer[T]) APIPublicURL() string { return as.apiPublicURL } -func (as *apiServer[T]) waitForServerStop(httpErrChan, metricsErrChan chan error) error { +func (as *apiServer[T]) waitForServerStop(httpErrChan, monitoringErrChan chan error) error { select { case err := <-httpErrChan: return err - case err := <-metricsErrChan: + case err := <-monitoringErrChan: return err } } @@ -242,7 +243,7 @@ func (as *apiServer[T]) createMuxRouter(ctx context.Context) *mux.Router { r := mux.NewRouter().UseEncodedPath() hf := as.handlerFactory() - if as.metricsEnabled { + if as.monitoringEnabled { h, _ := as.MetricsRegistry.GetHTTPMetricsInstrumentationsMiddlewareForSubsystem(ctx, APIServerMetricsSubSystemName) r.Use(h) } @@ -293,12 +294,20 @@ func (as *apiServer[T]) notFoundHandler(res http.ResponseWriter, req *http.Reque return 404, i18n.NewError(req.Context(), i18n.Msg404NotFound) } -func (as *apiServer[T]) createMetricsMuxRouter(ctx context.Context) *mux.Router { - r := mux.NewRouter() +func (as *apiServer[T]) createMonitoringMuxRouter(ctx context.Context) *mux.Router { + r := mux.NewRouter().UseEncodedPath() + hf := as.handlerFactory() // TODO separate factory for monitoring ?? + h, err := as.MetricsRegistry.HTTPHandler(ctx, promhttp.HandlerOpts{}) if err != nil { panic(err) } r.Path(as.metricsPath).Handler(h) + + for _, route := range as.MonitoringRoutes { + r.HandleFunc(route.Path, as.routeHandler(hf, route)).Methods(route.Method) + } + + r.NotFoundHandler = hf.APIWrapper(as.notFoundHandler) return r } diff --git a/pkg/ffapi/apiserver_config.go b/pkg/ffapi/apiserver_config.go index 80f997a4..369dadc3 100644 --- a/pkg/ffapi/apiserver_config.go +++ b/pkg/ffapi/apiserver_config.go @@ -22,8 +22,8 @@ import ( ) var ( - ConfMetricsServerEnabled = "enabled" - ConfMetricsServerPath = "/metrics" + ConfMonitoringServerEnabled = "enabled" + ConfMonitoringServerMetricsPath = "metricsPath" ConfAPIDefaultFilterLimit = "defaultFilterLimit" ConfAPIMaxFilterLimit = "maxFilterLimit" @@ -34,7 +34,7 @@ var ( ConfAPIDynamicPublicURLHeader = "dynamicPublicURLHeader" ) -func InitAPIServerConfig(apiConfig, metricsConfig, corsConfig config.Section) { +func InitAPIServerConfig(apiConfig, monitoringConfig, corsConfig config.Section) { httpserver.InitHTTPConfig(apiConfig, 5000) apiConfig.AddKnownKey(ConfAPIDefaultFilterLimit, 25) apiConfig.AddKnownKey(ConfAPIMaxFilterLimit, 100) @@ -46,7 +46,7 @@ func InitAPIServerConfig(apiConfig, metricsConfig, corsConfig config.Section) { httpserver.InitCORSConfig(corsConfig) - httpserver.InitHTTPConfig(metricsConfig, 6000) - metricsConfig.AddKnownKey(ConfMetricsServerEnabled, true) - metricsConfig.AddKnownKey(ConfMetricsServerPath, "/metrics") + httpserver.InitHTTPConfig(monitoringConfig, 6000) + monitoringConfig.AddKnownKey(ConfMonitoringServerEnabled, true) + monitoringConfig.AddKnownKey(ConfMonitoringServerMetricsPath, "/metrics") } diff --git a/pkg/ffapi/apiserver_test.go b/pkg/ffapi/apiserver_test.go index f91b5bd0..0821f9b8 100644 --- a/pkg/ffapi/apiserver_test.go +++ b/pkg/ffapi/apiserver_test.go @@ -114,17 +114,17 @@ var utAPIRoute2 = &Route{ func initUTConfig() (config.Section, config.Section, config.Section) { config.RootConfigReset() apiConfig := config.RootSection("ut.api") - metricsConfig := config.RootSection("ut.metrics") + monitoringConfig := config.RootSection("ut.monitoringConfig") corsConfig := config.RootSection("ut.cors") - InitAPIServerConfig(apiConfig, metricsConfig, corsConfig) + InitAPIServerConfig(apiConfig, monitoringConfig, corsConfig) apiConfig.Set(httpserver.HTTPConfPort, 0) - metricsConfig.Set(httpserver.HTTPConfPort, 0) - return apiConfig, metricsConfig, corsConfig + monitoringConfig.Set(httpserver.HTTPConfPort, 0) + return apiConfig, monitoringConfig, corsConfig } func newTestAPIServer(t *testing.T, start bool) (*utManager, *apiServer[*utManager], func()) { ctx, cancelCtx := context.WithCancel(context.Background()) - apiConfig, metricsConfig, corsConfig := initUTConfig() + apiConfig, monitoringConfig, corsConfig := initUTConfig() um := &utManager{t: t} as := NewAPIServer(ctx, APIServerOptions[*utManager]{ MetricsRegistry: metric.NewPrometheusMetricsRegistry("ut"), @@ -135,10 +135,10 @@ func newTestAPIServer(t *testing.T, start bool) (*utManager, *apiServer[*utManag // request and that's the "T" on the APIServer return um, um.mockEnrichErr }, - Description: "unit testing", - APIConfig: apiConfig, - MetricsConfig: metricsConfig, - CORSConfig: corsConfig, + Description: "unit testing", + APIConfig: apiConfig, + MonitoringConfig: monitoringConfig, + CORSConfig: corsConfig, }) done := make(chan struct{}) if start { @@ -382,11 +382,11 @@ func TestAPIServerFailServe(t *testing.T) { } -func TestAPIServerFailServeMetrics(t *testing.T) { +func TestAPIServerFailServeMonitoring(t *testing.T) { _, as, done := newTestAPIServer(t, false) defer done() - as.MetricsConfig.Set(httpserver.HTTPConfAddress, "!badness") + as.MonitoringConfig.Set(httpserver.HTTPConfAddress, "!badness") err := as.Serve(context.Background()) assert.Regexp(t, "FF00151", err) @@ -408,15 +408,15 @@ func TestWaitForServerStop(t *testing.T) { } func TestBadRoute(t *testing.T) { - apiConfig, metricsConfig, corsConfig := initUTConfig() + apiConfig, monitoringConfig, corsConfig := initUTConfig() as := NewAPIServer(context.Background(), APIServerOptions[*utManager]{ MetricsRegistry: metric.NewPrometheusMetricsRegistry("ut"), Routes: []*Route{{ Extensions: &APIServerRouteExt[string]{}, // T does not match *utManager }}, - APIConfig: apiConfig, - MetricsConfig: metricsConfig, - CORSConfig: corsConfig, + APIConfig: apiConfig, + MonitoringConfig: monitoringConfig, + CORSConfig: corsConfig, }) assert.Panics(t, func() { as.Serve(context.Background()) }) } @@ -425,5 +425,5 @@ func TestBadMetrics(t *testing.T) { _, as, done := newTestAPIServer(t, false) defer done() as.MetricsRegistry = metric.NewPrometheusMetricsRegistry("wrong") - assert.Panics(t, func() { as.createMetricsMuxRouter(context.Background()) }) + assert.Panics(t, func() { as.createMonitoringMuxRouter(context.Background()) }) } From 4903076fd74de7258b7c4f696010370995064dd4 Mon Sep 17 00:00:00 2001 From: hfuss Date: Sat, 15 Feb 2025 19:08:41 -0500 Subject: [PATCH 2/2] lint Signed-off-by: hfuss --- pkg/ffapi/apiserver.go | 2 +- pkg/ffapi/apiserver_config.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/ffapi/apiserver.go b/pkg/ffapi/apiserver.go index bd2d8a46..0433ad73 100644 --- a/pkg/ffapi/apiserver.go +++ b/pkg/ffapi/apiserver.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/pkg/ffapi/apiserver_config.go b/pkg/ffapi/apiserver_config.go index 369dadc3..099e3531 100644 --- a/pkg/ffapi/apiserver_config.go +++ b/pkg/ffapi/apiserver_config.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 //