diff --git a/api/grpcserver/grpcserver_test.go b/api/grpcserver/grpcserver_test.go index c434396896..516f190892 100644 --- a/api/grpcserver/grpcserver_test.go +++ b/api/grpcserver/grpcserver_test.go @@ -439,7 +439,8 @@ func TestNewServersConfig(t *testing.T) { require.NoError(t, err, "Should be able to establish a connection on a port") grpcService := New(fmt.Sprintf(":%d", port1), zaptest.NewLogger(t).Named("grpc"), DefaultTestConfig()) - jsonService := NewJSONHTTPServer(zaptest.NewLogger(t).Named("grpc.JSON"), fmt.Sprintf(":%d", port2), []string{}) + jsonService := NewJSONHTTPServer(zaptest.NewLogger(t).Named("grpc.JSON"), fmt.Sprintf(":%d", port2), + []string{}, false) require.Contains(t, grpcService.listener, strconv.Itoa(port1), "Expected same port") require.Contains(t, jsonService.listener, strconv.Itoa(port2), "Expected same port") diff --git a/api/grpcserver/http_server.go b/api/grpcserver/http_server.go index f7e4058eeb..e529f517e3 100644 --- a/api/grpcserver/http_server.go +++ b/api/grpcserver/http_server.go @@ -10,15 +10,21 @@ import ( "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/rs/cors" + metricsProm "github.com/slok/go-http-metrics/metrics/prometheus" + "github.com/slok/go-http-metrics/middleware" + "github.com/slok/go-http-metrics/middleware/std" "go.uber.org/zap" "golang.org/x/sync/errgroup" + + "github.com/spacemeshos/go-spacemesh/metrics" ) // JSONHTTPServer is a JSON http server providing the Spacemesh API. // It is implemented using a grpc-gateway. See https://github.com/grpc-ecosystem/grpc-gateway . type JSONHTTPServer struct { - listener string - logger *zap.Logger + listener string + collectMetrics bool + logger *zap.Logger // BoundAddress contains the address that the server bound to, useful if // the server uses a dynamic port. It is set during startup and can be @@ -37,11 +43,13 @@ func NewJSONHTTPServer( lg *zap.Logger, listener string, corsAllowedOrigins []string, + collectMetrics bool, ) *JSONHTTPServer { return &JSONHTTPServer{ - logger: lg, - listener: listener, - origins: corsAllowedOrigins, + logger: lg, + listener: listener, + origins: corsAllowedOrigins, + collectMetrics: collectMetrics, } } @@ -89,6 +97,17 @@ func (s *JSONHTTPServer) StartService( AllowedOrigins: s.origins, }) + // mdlw is the middleware stack for the http server + handler := c.Handler(mux) + if s.collectMetrics { + mdlw := middleware.New(middleware.Config{ + Recorder: metricsProm.NewRecorder(metricsProm.Config{ + Prefix: metrics.Namespace + "_api", + }), + }) + handler = c.Handler(std.Handler("", mdlw, mux)) + } + s.logger.Info("starting grpc gateway server", zap.String("address", s.listener)) lis, err := net.Listen("tcp", s.listener) if err != nil { @@ -99,7 +118,7 @@ func (s *JSONHTTPServer) StartService( MaxHeaderBytes: 1 << 21, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, - Handler: c.Handler(mux), + Handler: handler, } s.eg.Go(func() error { if err := s.server.Serve(lis); err != nil { diff --git a/api/grpcserver/http_server_test.go b/api/grpcserver/http_server_test.go index 06cb018b53..46f75a5bd2 100644 --- a/api/grpcserver/http_server_test.go +++ b/api/grpcserver/http_server_test.go @@ -25,7 +25,8 @@ func launchJsonServer(tb testing.TB, services ...ServiceAPI) (Config, func()) { cfg := DefaultTestConfig() // run on random port - jsonService := NewJSONHTTPServer(zaptest.NewLogger(tb).Named("grpc.JSON"), "127.0.0.1:0", []string{}) + jsonService := NewJSONHTTPServer(zaptest.NewLogger(tb).Named("grpc.JSON"), "127.0.0.1:0", + []string{}, false) // start json server require.NoError(tb, jsonService.StartService(context.Background(), services...)) diff --git a/cmd/bootstrapper/generator_test.go b/cmd/bootstrapper/generator_test.go index 7b1d4153e7..a0e96e72e4 100644 --- a/cmd/bootstrapper/generator_test.go +++ b/cmd/bootstrapper/generator_test.go @@ -62,7 +62,8 @@ func createAtxs(tb testing.TB, db sql.Executor, epoch types.EpochID, atxids []ty func launchServer(tb testing.TB, cdb *datastore.CachedDB) (grpcserver.Config, func()) { cfg := grpcserver.DefaultTestConfig() grpcService := grpcserver.New("127.0.0.1:0", zaptest.NewLogger(tb).Named("grpc"), cfg) - jsonService := grpcserver.NewJSONHTTPServer(zaptest.NewLogger(tb).Named("grpc.JSON"), "127.0.0.1:0", []string{}) + jsonService := grpcserver.NewJSONHTTPServer(zaptest.NewLogger(tb).Named("grpc.JSON"), "127.0.0.1:0", + []string{}, false) s := grpcserver.NewMeshService(cdb, grpcserver.NewMockmeshAPI(gomock.NewController(tb)), nil, nil, 0, types.Hash20{}, 0, 0, 0) diff --git a/go.mod b/go.mod index 5b5a7b2e9f..058bd38f9e 100644 --- a/go.mod +++ b/go.mod @@ -38,6 +38,7 @@ require ( github.com/rs/cors v1.11.0 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 github.com/seehuhn/mt19937 v1.0.0 + github.com/slok/go-http-metrics v0.12.0 github.com/spacemeshos/api/release/go v1.49.0 github.com/spacemeshos/economics v0.1.3 github.com/spacemeshos/fixed v0.1.1 @@ -90,7 +91,7 @@ require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/emicklei/go-restful/v3 v3.12.0 // indirect github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/go.sum b/go.sum index 7e396cef1f..72de7ff0ed 100644 --- a/go.sum +++ b/go.sum @@ -98,8 +98,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk= +github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -592,6 +592,8 @@ github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYED github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/slok/go-http-metrics v0.12.0 h1:mAb7hrX4gB4ItU6NkFoKYdBslafg3o60/HbGBRsKaG8= +github.com/slok/go-http-metrics v0.12.0/go.mod h1:Ee/mdT9BYvGrlGzlClkK05pP2hRHmVbRF9dtUVS8LNA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= @@ -634,6 +636,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/node/node.go b/node/node.go index bbd457f3b7..fec57fd80f 100644 --- a/node/node.go +++ b/node/node.go @@ -1765,6 +1765,7 @@ func (app *App) startAPIServices(ctx context.Context) error { logger.Zap().Named("JSON"), app.Config.API.JSONListener, app.Config.API.JSONCorsAllowedOrigins, + app.Config.CollectMetrics, ) if err := app.jsonAPIServer.StartService(ctx, maps.Values(publicSvcs)...); err != nil {