From 79829dd836df32810ca19ec5ad982dfdc708a676 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 22 Feb 2019 18:22:49 +0200 Subject: [PATCH] Added http_pprof_path in cgr-engine for exosing debug URL. fixes#1427 --- cmd/cgr-engine/cgr-engine.go | 7 ++++-- utils/server.go | 43 ++++++++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index 5bd69fe40..04037b0f9 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -64,6 +64,7 @@ var ( cfgDir = flag.String("config_dir", utils.CONFIG_DIR, "Configuration directory path.") version = flag.Bool("version", false, "Prints the application version.") pidFile = flag.String("pid", "", "Write pid file") + httpPprofPath = flag.String("http_pprof_path", "", "http address used for program profiling") cpuProfDir = flag.String("cpuprof_dir", "", "write cpu profile to files") memProfDir = flag.String("memprof_dir", "", "write memory profile to file") memProfInterval = flag.Duration("memprof_interval", 5*time.Second, "Time betwen memory profile saves") @@ -1138,7 +1139,6 @@ func schedCDRsConns(internalCDRSChan chan rpcclient.RpcClientConnection, exitCha engine.SetSchedCdrsConns(cdrsConn) } - func memProfFile(memProfPath string) bool { f, err := os.Create(memProfPath) if err != nil { @@ -1299,7 +1299,7 @@ func main() { stopHandled := false // Rpc/http server - server := new(utils.Server) + server := utils.NewServer() // init cache cacheS := engine.NewCacheS(cfg, dm) @@ -1314,6 +1314,9 @@ func main() { } }() + if *httpPprofPath != "" { + go server.RegisterProfiler(*httpPprofPath) + } // Async starts here, will follow cgrates.json start order // Define internal connections via channels diff --git a/utils/server.go b/utils/server.go index eb7adbf49..d6699d34b 100644 --- a/utils/server.go +++ b/utils/server.go @@ -28,7 +28,7 @@ import ( "log" "net" "net/http" - _ "net/http/pprof" + "net/http/pprof" "net/rpc" "net/rpc/jsonrpc" "reflect" @@ -38,15 +38,21 @@ import ( "github.com/cenkalti/rpc2" rpc2_jsonrpc "github.com/cenkalti/rpc2/jsonrpc" "golang.org/x/net/websocket" - _ "net/http/pprof" ) +func NewServer() (s *Server) { + s = new(Server) + s.httpMux = http.NewServeMux() + return s +} + type Server struct { rpcEnabled bool httpEnabled bool birpcSrv *rpc2.Server sync.RWMutex httpsMux *http.ServeMux + httpMux *http.ServeMux } func (s *Server) RpcRegister(rcvr interface{}) { @@ -64,7 +70,9 @@ func (s *Server) RpcRegisterName(name string, rcvr interface{}) { } func (s *Server) RegisterHttpFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) { - http.HandleFunc(pattern, handler) + if s.httpMux != nil { + s.httpMux.HandleFunc(pattern, handler) + } if s.httpsMux != nil { s.httpsMux.HandleFunc(pattern, handler) } @@ -74,7 +82,9 @@ func (s *Server) RegisterHttpFunc(pattern string, handler func(http.ResponseWrit } func (s *Server) RegisterHttpHandler(pattern string, handler http.Handler) { - http.Handle(pattern, handler) + if s.httpMux != nil { + s.httpMux.Handle(pattern, handler) + } if s.httpsMux != nil { s.httpsMux.Handle(pattern, handler) } @@ -192,6 +202,20 @@ func handleRequest(w http.ResponseWriter, r *http.Request) { io.Copy(w, res) } +func (s *Server) RegisterProfiler(addr string) { + s.httpMux.HandleFunc(addr, pprof.Index) + s.httpMux.HandleFunc(addr+"cmdline", pprof.Cmdline) + s.httpMux.HandleFunc(addr+"profile", pprof.Profile) + s.httpMux.HandleFunc(addr+"symbol", pprof.Symbol) + s.httpMux.HandleFunc(addr+"trace", pprof.Trace) + s.httpMux.Handle(addr+"goroutine", pprof.Handler("goroutine")) + s.httpMux.Handle(addr+"heap", pprof.Handler("heap")) + s.httpMux.Handle(addr+"threadcreate", pprof.Handler("threadcreate")) + s.httpMux.Handle(addr+"block", pprof.Handler("block")) + s.httpMux.Handle(addr+"allocs", pprof.Handler("allocs")) + s.httpMux.Handle(addr+"mutex", pprof.Handler("mutex")) +} + func (s *Server) ServeHTTP(addr string, jsonRPCURL string, wsRPCURL string, useBasicAuth bool, userList map[string]string, exitChan chan bool) { s.RLock() @@ -200,6 +224,7 @@ func (s *Server) ServeHTTP(addr string, jsonRPCURL string, wsRPCURL string, if !enabled { return } + // s.httpMux = http.NewServeMux() if enabled && jsonRPCURL != "" { s.Lock() s.httpEnabled = true @@ -207,9 +232,9 @@ func (s *Server) ServeHTTP(addr string, jsonRPCURL string, wsRPCURL string, Logger.Info(" enabling handler for JSON-RPC") if useBasicAuth { - http.HandleFunc(jsonRPCURL, use(handleRequest, basicAuth(userList))) + s.httpMux.HandleFunc(jsonRPCURL, use(handleRequest, basicAuth(userList))) } else { - http.HandleFunc(jsonRPCURL, handleRequest) + s.httpMux.HandleFunc(jsonRPCURL, handleRequest) } } if enabled && wsRPCURL != "" { @@ -221,11 +246,11 @@ func (s *Server) ServeHTTP(addr string, jsonRPCURL string, wsRPCURL string, jsonrpc.ServeConn(ws) }) if useBasicAuth { - http.HandleFunc(wsRPCURL, use(func(w http.ResponseWriter, r *http.Request) { + s.httpMux.HandleFunc(wsRPCURL, use(func(w http.ResponseWriter, r *http.Request) { wsHandler.ServeHTTP(w, r) }, basicAuth(userList))) } else { - http.Handle(wsRPCURL, wsHandler) + s.httpMux.Handle(wsRPCURL, wsHandler) } } if !s.httpEnabled { @@ -235,7 +260,7 @@ func (s *Server) ServeHTTP(addr string, jsonRPCURL string, wsRPCURL string, Logger.Info(" enabling basic auth") } Logger.Info(fmt.Sprintf(" start listening at <%s>", addr)) - http.ListenAndServe(addr, nil) + http.ListenAndServe(addr, s.httpMux) exitChan <- true }