diff --git a/core/config/config.go b/core/config/config.go index 96adf9291..be4975d70 100644 --- a/core/config/config.go +++ b/core/config/config.go @@ -55,6 +55,14 @@ func GetDefaultConfig() *Config { Archive: ArchiveConfig{ PrintStatsPeriod: 10 * time.Second, }, + DebugEndpoints: DebugEndpointsConfig{ + Cache: true, + Memory: true, + PProf: false, + Stacks: true, + StacksMaxSizeKb: 5 * 1024, + TxPool: true, + }, } } @@ -149,8 +157,11 @@ type Config struct { // EnableTestAPIs enables additional APIs used for testing. EnableTestAPIs bool - // Enables go profiler, gc and so on enpoints on /debug + // EnableDebugEndpoints is a legacy setting, enables all debug endpoints. + // Per endpoint configuration is in DebugEndpoints. EnableDebugEndpoints bool + + DebugEndpoints DebugEndpointsConfig } type TLSConfig struct { @@ -330,6 +341,15 @@ type MetricsConfig struct { Interface string } +type DebugEndpointsConfig struct { + Cache bool + Memory bool + PProf bool + Stacks bool + StacksMaxSizeKb int + TxPool bool +} + func (ac *ArchiveConfig) GetReadMiniblocksSize() uint64 { if ac.ReadMiniblocksSize <= 0 { return 100 diff --git a/core/node/events/stream.go b/core/node/events/stream.go index 18a2585ec..aec66bc48 100644 --- a/core/node/events/stream.go +++ b/core/node/events/stream.go @@ -392,6 +392,7 @@ func (s *streamImpl) addEventImpl(ctx context.Context, event *ParsedEvent) error return err } + prevSyncCookie := s.view.SyncCookie(s.params.Wallet.Address) s.view = newSV newSyncCookie := s.view.SyncCookie(s.params.Wallet.Address) diff --git a/core/node/rpc/archive.go b/core/node/rpc/archive.go index b3df12a38..3966783af 100644 --- a/core/node/rpc/archive.go +++ b/core/node/rpc/archive.go @@ -53,7 +53,7 @@ func (s *Service) startArchiveMode(once bool) error { s.riverChain.StartChainMonitor(s.serverCtx) - s.registerDebugHandlers(s.config.EnableDebugEndpoints) + s.registerDebugHandlers(s.config.EnableDebugEndpoints, s.config.DebugEndpoints) s.SetStatus("OK") diff --git a/core/node/rpc/debug.go b/core/node/rpc/debug.go index 7ad34146c..fe7872361 100644 --- a/core/node/rpc/debug.go +++ b/core/node/rpc/debug.go @@ -12,6 +12,7 @@ import ( "strings" "time" + "github.com/river-build/river/core/config" "github.com/river-build/river/core/node/crypto" "github.com/river-build/river/core/node/dlog" . "github.com/river-build/river/core/node/events" @@ -57,7 +58,7 @@ type httpMux interface { Handle(pattern string, handler http.Handler) } -func (s *Service) registerDebugHandlers(enableDebugEndpoints bool) { +func (s *Service) registerDebugHandlers(enableDebugEndpoints bool, cfg config.DebugEndpointsConfig) { mux := s.mux handler := debugHandler{} mux.HandleFunc("/debug", handler.ServeHTTP) @@ -65,23 +66,44 @@ func (s *Service) registerDebugHandlers(enableDebugEndpoints bool) { handler.HandleFunc(mux, "/debug/multi/json", s.handleDebugMultiJson) handler.Handle(mux, "/debug/config", &onChainConfigHandler{onChainConfig: s.chainConfig}) - if enableDebugEndpoints { + if cfg.Cache || enableDebugEndpoints { handler.Handle(mux, "/debug/cache", &cacheHandler{cache: s.cache}) - handler.Handle(mux, "/debug/txpool", &txpoolHandler{riverTxPool: s.riverChain.TxPool}) + } + + if cfg.Memory || enableDebugEndpoints { handler.HandleFunc(mux, "/debug/memory", MemoryHandler) + } + + if cfg.PProf || enableDebugEndpoints { handler.HandleFunc(mux, "/debug/pprof/", pprof.Index) mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) mux.HandleFunc("/debug/pprof/profile", pprof.Profile) mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) mux.HandleFunc("/debug/pprof/trace", pprof.Trace) - handler.HandleFunc(mux, "/debug/stacks", HandleStacksHandler) + } + + if cfg.Stacks || enableDebugEndpoints { + handler.Handle(mux, "/debug/stacks", &stacksHandler{maxSizeKb: cfg.StacksMaxSizeKb}) + } + + if cfg.TxPool || enableDebugEndpoints { + handler.Handle(mux, "/debug/txpool", &txpoolHandler{riverTxPool: s.riverChain.TxPool}) } } -func HandleStacksHandler(w http.ResponseWriter, r *http.Request) { +type stacksHandler struct { + maxSizeKb int +} + +func (h *stacksHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + stacksSize := h.maxSizeKb * 1024 + if stacksSize == 0 { + stacksSize = 1024 * 1024 + } + var ( ctx = r.Context() - buf = make([]byte, 1024*1024) + buf = make([]byte, stacksSize) stackSize = runtime.Stack(buf, true) traceScanner = bufio.NewScanner(bytes.NewReader((buf[:stackSize]))) reply render.GoRoutineData diff --git a/core/node/rpc/info_mode.go b/core/node/rpc/info_mode.go index 89ba18848..dcd0018e4 100644 --- a/core/node/rpc/info_mode.go +++ b/core/node/rpc/info_mode.go @@ -39,7 +39,7 @@ func (s *Service) startInfoMode() error { s.riverChain.StartChainMonitor(s.serverCtx) - s.registerDebugHandlers(s.config.EnableDebugEndpoints) + s.registerDebugHandlers(s.config.EnableDebugEndpoints, s.config.DebugEndpoints) s.SetStatus("OK") diff --git a/core/node/rpc/server.go b/core/node/rpc/server.go index d494bd572..40225a263 100644 --- a/core/node/rpc/server.go +++ b/core/node/rpc/server.go @@ -582,7 +582,7 @@ func (s *Service) initHandlers() { nodeServicePattern, nodeServiceHandler := protocolconnect.NewNodeToNodeHandler(s, interceptors) s.mux.Handle(nodeServicePattern, newHttpHandler(nodeServiceHandler, s.defaultLogger)) - s.registerDebugHandlers(s.config.EnableDebugEndpoints) + s.registerDebugHandlers(s.config.EnableDebugEndpoints, s.config.DebugEndpoints) } // StartServer starts the server with the given configuration.