Add debug API. This can be used for profiling.

This commit is contained in:
Kleissner
2022-01-06 00:05:27 +01:00
parent 4b89138d36
commit adce6fee5c
7 changed files with 136 additions and 4 deletions

4
API.go
View File

@@ -44,6 +44,10 @@ func startAPI(backend *core.Backend, apiListen []string, apiKey uuid.UUID) {
api.AllowKeyInParam = append(api.AllowKeyInParam, "/console")
api.Router.HandleFunc("/console", apiConsole(backend)).Methods("GET")
api.Router.HandleFunc("/shutdown", apiShutdown(backend)).Methods("GET")
if config.DebugAPI {
attachDebugAPI(api)
}
}
// parseCmdParams parses the "-webapi", "-apikey", and "-watchpid" command line parameters.

11
Debug empty.go Normal file
View File

@@ -0,0 +1,11 @@
//go:build !debug
// +build !debug
package main
import (
"github.com/PeernetOfficial/core/webapi"
)
func attachDebugAPI(api *webapi.WebapiInstance) {
}

98
Debug.go Normal file
View File

@@ -0,0 +1,98 @@
//go:build debug
// +build debug
/*
File Name: Debug.go
Copyright: 2017 Kleissner Investments s.r.o.
Author: Peter Kleissner
Debug runtime functionality. The functions only work if the config setting DebugAPI is enabled.
*/
package main
import (
"net/http"
"net/http/pprof" // Warning: If the default HTTP handler is used, this installs handlers!
"runtime"
"github.com/PeernetOfficial/core/webapi"
)
// apiDebugBugcheck handles /debug/bugcheck
func apiDebugBugcheck(w http.ResponseWriter, r *http.Request) {
if !config.DebugAPI {
http.Error(w, "", http.StatusOK)
return
}
http.Error(w, "Executing immediate bugcheck", http.StatusOK)
panic("via /debug/bugcheck")
}
// apiDebugStack handles /debug/stack
func apiDebugStack(w http.ResponseWriter, r *http.Request) {
if !config.DebugAPI {
http.Error(w, "", http.StatusOK)
return
}
buffer := make([]byte, 1*1024*1024)
size := runtime.Stack(buffer, true)
http.Error(w, string(buffer[:size]), http.StatusOK)
}
func attachDebugAPI(api *webapi.WebapiInstance) {
api.AllowKeyInParam = append(api.AllowKeyInParam, []string{
"/debug/bugcheck",
"/debug/stack",
"/debug/pprof",
"/debug/pprof/cmdline",
"/debug/pprof/profile",
"/debug/pprof/symbol",
"/debug/pprof/trace",
"/debug/pprof/goroutine",
"/debug/pprof/heap",
"/debug/pprof/threadcreate",
"/debug/pprof/block",
"/debug/pprof/allocs",
"/debug/pprof/mutex",
}...)
api.Router.HandleFunc("/debug/bugcheck", apiDebugBugcheck)
api.Router.HandleFunc("/debug/stack", apiDebugStack)
api.Router.HandleFunc("/debug/pprof", pprof.Index)
api.Router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
api.Router.HandleFunc("/debug/pprof/profile", pprof.Profile)
api.Router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
api.Router.HandleFunc("/debug/pprof/trace", pprof.Trace)
// Manually add support for paths linked to by index page at /debug/pprof/
api.Router.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine"))
api.Router.Handle("/debug/pprof/heap", pprof.Handler("heap"))
api.Router.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate"))
api.Router.Handle("/debug/pprof/block", pprof.Handler("block"))
api.Router.Handle("/debug/pprof/allocs", pprof.Handler("allocs"))
api.Router.Handle("/debug/pprof/mutex", pprof.Handler("mutex"))
}
/*
To use the pprof functionality set DebugAPI in the config to true and then use the right endpoints.
For heap profiling:
* While running, download the file http://[IP:Port]/debug/pprof/heap
* Run "go tool pprof -http=127.0.0.1:80 [service].exe heap". The http parameter will open an interactive web-server.
* pprof supports the following options. Default is inuse_space.
-inuse_space Display in-use memory size
-inuse_objects Display in-use object counts
-alloc_space Display allocated memory size
-alloc_objects Display allocated object counts
* Instead of download the file in step 2, you can directly provide the full URL in step 3!
Enabling DebugAPI shall not have any performance impact; it just installs the handlers. Only once a profiler is actually used, it may impact the performance.
*/

View File

@@ -20,6 +20,7 @@ const appName = "Peernet Cmd"
var config struct {
// Log settings
ErrorOutput int `yaml:"ErrorOutput"` // 0 = Log file (default), 1 = Command line, 2 = Log file + command line, 3 = None
DebugAPI bool `yaml:"DebugAPI"` // Enables the debug API which allows profiling. Do not enable in production. Only available if compiled with debug tag.
// API settings
APIListen []string `yaml:"APIListen"` // WebListen is in format IP:Port and declares where the web-interface should listen on. IP can also be ommitted to listen on any.

View File

@@ -231,3 +231,21 @@ Use the parameter `-watchpid=[PID]` to specify a process ID to monitor for exit
```
Cmd -watchpid=1234
```
## Debug
### Compile Debug Version
A debug version that exposes multiple endpoints via `/debug` for profiling can be compiled by using the debug tag:
```
go build -tags debug
```
### Use the Profiler
Once started attach the profiler `go tool pprof`. Note that `/debug` endpoints are not excluded from API authentication. If an API key is used, it can be provided via the `&k=` parameter.
```
go tool pprof -http=127.0.0.1:80 Cmd.exe http://127.0.0.1:1337/debug/pprof/heap?k=a30c01eb-856c-4b79-bdde-3c56a248f71b
```

2
go.mod
View File

@@ -3,7 +3,7 @@ module github.com/PeernetOfficial/Cmd
go 1.16
require (
github.com/PeernetOfficial/core v0.0.0-20211231003743-0689543d432f
github.com/PeernetOfficial/core v0.0.0-20220103002105-a19bac19163f
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.4.3-0.20210424162022-e8629af678b7
)

4
go.sum
View File

@@ -1,7 +1,7 @@
github.com/IncSW/geoip2 v0.1.1 h1:afzzYF7n9JbdcPy8aiBSgBJuXi4mTWXZ3z6V3o6Vg34=
github.com/IncSW/geoip2 v0.1.1/go.mod h1:adcasR40vXiUBjtzdaTTKL/6wSf+fgO4M8Gve/XzPUk=
github.com/PeernetOfficial/core v0.0.0-20211231003743-0689543d432f h1:jlHQnoboaX8vEX6PQdt86SUeLM77qR8WN0EyeH8dv5Q=
github.com/PeernetOfficial/core v0.0.0-20211231003743-0689543d432f/go.mod h1:VNhfwAZqya5JDZTS/ffa8Shof0OmQCx025CQMieGB7o=
github.com/PeernetOfficial/core v0.0.0-20220103002105-a19bac19163f h1:nkMU/dzSA61anIeBJGfCsq1+Ek6VR+BNXi4FnFkVu8k=
github.com/PeernetOfficial/core v0.0.0-20220103002105-a19bac19163f/go.mod h1:VNhfwAZqya5JDZTS/ffa8Shof0OmQCx025CQMieGB7o=
github.com/akrylysov/pogreb v0.10.1 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK4w=
github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI=
github.com/enfipy/locker v1.1.0 h1:2zVJ0ky7cS1Vjs0x6OQWFiT2dSEiHrI5/O2KCz1fgGc=