diff --git a/cmd/run.go b/cmd/run.go index e384e9048b..cfd5a0da24 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -145,6 +145,7 @@ the data document with the following syntax: runCommand.Flags().StringVarP(¶ms.OutputFormat, "format", "f", "pretty", "set shell output format, i.e, pretty, json") runCommand.Flags().BoolVarP(¶ms.Watch, "watch", "w", false, "watch command line files for changes") setMaxErrors(runCommand.Flags(), ¶ms.ErrorLimit) + runCommand.Flags().BoolVarP(¶ms.PprofEnabled, "pprof", "", false, "enables pprof endpoints") runCommand.Flags().IntVarP(&serverDiagnosticsBufferSize, "server-diagnostics-buffer-size", "", defaultServerDiagnosticsBufferSize, "set the size of the server's diagnostics buffer") runCommand.Flags().MarkDeprecated("server-diagnostics-buffer-size", "use decision logging instead") runCommand.Flags().StringVarP(&tlsCertFile, "tls-cert-file", "", "", "set path of TLS certificate file") diff --git a/runtime/runtime.go b/runtime/runtime.go index 02238c6ba7..bfa467beb3 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -102,6 +102,9 @@ type Params struct { // exiting early. ErrorLimit int + // PprofEnabled flag controls whether pprof endpoints are enabled + PprofEnabled bool + // DecisionIDFactory generates decision IDs to include in API responses // sent by the server (in response to Data API queries.) DecisionIDFactory func() string @@ -242,6 +245,7 @@ func (rt *Runtime) StartServer(ctx context.Context) { WithStore(rt.Store). WithManager(rt.Manager). WithCompilerErrorLimit(rt.Params.ErrorLimit). + WithPprofEnabled(rt.Params.PprofEnabled). WithAddresses(*rt.Params.Addrs). WithInsecureAddress(rt.Params.InsecureAddr). WithCertificate(rt.Params.Certificate). diff --git a/server/server.go b/server/server.go index 25caa8e323..bbec5b545b 100644 --- a/server/server.go +++ b/server/server.go @@ -17,6 +17,7 @@ import ( "net" "net/http" "net/http/httputil" + "net/http/pprof" "net/url" "os" "strconv" @@ -101,6 +102,7 @@ type Server struct { revision string logger func(context.Context, *Info) error errLimit int + pprofEnabled bool runtime *ast.Term } @@ -219,6 +221,12 @@ func (s *Server) WithCompilerErrorLimit(limit int) *Server { return s } +// WithPprofEnabled sets whether pprof endpoints are enabled +func (s *Server) WithPprofEnabled(pprofEnabled bool) *Server { + s.pprofEnabled = pprofEnabled + return s +} + // WithDiagnosticsBuffer sets the diagnostics buffer used by the server. DEPRECATED. func (s *Server) WithDiagnosticsBuffer(buf Buffer) *Server { s.diagnostics = buf @@ -379,6 +387,17 @@ func (s *Server) initRouter() { router.StrictSlash(true) router.Handle("/metrics", promhttp.HandlerFor(promRegistry, promhttp.HandlerOpts{})).Methods(http.MethodGet) router.Handle("/health", promhttp.InstrumentHandlerDuration(GetHealthDur, http.HandlerFunc(s.unversionedGetHealth))).Methods(http.MethodGet) + if s.pprofEnabled { + router.HandleFunc("/debug/pprof/", pprof.Index) + router.Handle("/debug/pprof/allocs", pprof.Handler("allocs")) + router.Handle("/debug/pprof/block", pprof.Handler("block")) + router.Handle("/debug/pprof/heap", pprof.Handler("heap")) + router.Handle("/debug/pprof/mutex", pprof.Handler("mutex")) + router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) + router.HandleFunc("/debug/pprof/profile", pprof.Profile) + router.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + router.HandleFunc("/debug/pprof/trace", pprof.Trace) + } s.registerHandler(router, 0, "/data/{path:.+}", http.MethodPost, promhttp.InstrumentHandlerDuration(v0DataDur, http.HandlerFunc(s.v0DataPost))) s.registerHandler(router, 0, "/data", http.MethodPost, promhttp.InstrumentHandlerDuration(v0DataDur, http.HandlerFunc(s.v0DataPost))) s.registerHandler(router, 1, "/data/system/diagnostics", http.MethodGet, promhttp.InstrumentHandlerDuration(v1DataDur, http.HandlerFunc(s.v1DiagnosticsGet)))