From 6ae7bdd85be232f857033667cf15ea86b8d10db6 Mon Sep 17 00:00:00 2001 From: Jonathan Chappelow Date: Sat, 24 Feb 2018 14:30:53 -0800 Subject: [PATCH] http profiling: fix mount of default http mux as a subroute (#359) This adds a new config option --httpprofprefix to specify the URL path prefix for the HTTP profiler. For example, given -p --httpprofprefix "/pp", the http hander will be available at: /pp/debug/pprof/ Note that the "/debug/pprof/ part is not changeable, and the trailing slash is required. But this path may be hidden via the prefix. --- config.go | 26 +++++++++++++++++--------- main.go | 12 ++++++++---- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/config.go b/config.go index 7afef8c77..de5baa1d4 100644 --- a/config.go +++ b/config.go @@ -39,6 +39,7 @@ var ( defaultConfigFile = filepath.Join(curDir, defaultConfigFilename) defaultLogDir = filepath.Join(curDir, defaultLogDirname) defaultHost = "localhost" + defaultHTTPProfPath = "/p" defaultAPIProto = "http" defaultAPIListen = "127.0.0.1:7777" @@ -60,15 +61,16 @@ var ( type config struct { // General application behavior - ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` - ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` - TestNet bool `long:"testnet" description:"Use the test network (default mainnet)"` - SimNet bool `long:"simnet" description:"Use the simulation test network (default mainnet)"` - DebugLevel string `short:"d" long:"debuglevel" description:"Logging level {trace, debug, info, warn, error, critical}"` - Quiet bool `short:"q" long:"quiet" description:"Easy way to set debuglevel to error"` - LogDir string `long:"logdir" description:"Directory to log output"` - HTTPProfile bool `long:"httpprof" short:"p" description:"Start HTTP profiler."` - CPUProfile string `long:"cpuprofile" description:"File for CPU profiling."` + ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` + ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` + TestNet bool `long:"testnet" description:"Use the test network (default mainnet)"` + SimNet bool `long:"simnet" description:"Use the simulation test network (default mainnet)"` + DebugLevel string `short:"d" long:"debuglevel" description:"Logging level {trace, debug, info, warn, error, critical}"` + Quiet bool `short:"q" long:"quiet" description:"Easy way to set debuglevel to error"` + LogDir string `long:"logdir" description:"Directory to log output"` + HTTPProfile bool `long:"httpprof" short:"p" description:"Start HTTP profiler."` + HTTPProfPath string `long:"httpprofprefix" description:"URL path prefix for the HTTP profiler."` + CPUProfile string `long:"cpuprofile" description:"File for CPU profiling."` // API APIProto string `long:"apiproto" description:"Protocol for API (http or https)"` @@ -119,6 +121,7 @@ var ( DebugLevel: defaultLogLevel, ConfigFile: defaultConfigFile, LogDir: defaultLogDir, + HTTPProfPath: defaultHTTPProfPath, APIProto: defaultAPIProto, APIListen: defaultAPIListen, IndentJSON: defaultIndentJSON, @@ -352,6 +355,11 @@ func loadConfig() (*config, error) { os.Exit(0) } + // Ensure HTTP profiler is mounted with a valid path prefix + if cfg.HTTPProfile && (cfg.HTTPProfPath == "/" || len(defaultHTTPProfPath) == 0) { + return loadConfigError(fmt.Errorf("httpprofprefix must not be \"\" or \"/\"")) + } + // Initialize log rotation. After log rotation has been initialized, the // logger variables may be used. initLogRotator(filepath.Join(cfg.LogDir, defaultLogFilename)) diff --git a/main.go b/main.go index 3025c0cbe..2df3c77c9 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "fmt" "net" "net/http" + _ "net/http/pprof" "os" "os/signal" "runtime/pprof" @@ -426,8 +427,11 @@ func mainCore() error { // HTTP profiler if cfg.HTTPProfile { - http.Handle("/", http.RedirectHandler("/debug/pprof", http.StatusSeeOther)) - webMux.Mount("/p", http.DefaultServeMux) + profPath := cfg.HTTPProfPath + log.Warnf("Starting the HTTP profiler on path %s.", profPath) + // http pprof uses http.DefaultServeMux + http.Handle("/", http.RedirectHandler(profPath+"/debug/pprof/", http.StatusSeeOther)) + webMux.Mount(profPath, http.StripPrefix(profPath, http.DefaultServeMux)) } if err = listenAndServeProto(cfg.APIListen, cfg.APIProto, webMux); err != nil { @@ -475,8 +479,8 @@ func listenAndServeProto(listen, proto string, mux http.Handler) error { case err := <-errChan: return fmt.Errorf("Failed to bind web server: %v", err) case <-t.C: - expLog.Infof("Now serving on %s://%v/", proto, listen) - apiLog.Infof("Now serving on %s://%v/", proto, listen) + expLog.Infof("Now serving explorer on %s://%v/", proto, listen) + apiLog.Infof("Now serving API on %s://%v/", proto, listen) return nil } }