mirror of
https://github.com/PeernetOfficial/Cmd.git
synced 2026-07-16 18:37:51 +01:00
Add debug API. This can be used for profiling.
This commit is contained in:
4
API.go
4
API.go
@@ -44,6 +44,10 @@ func startAPI(backend *core.Backend, apiListen []string, apiKey uuid.UUID) {
|
|||||||
api.AllowKeyInParam = append(api.AllowKeyInParam, "/console")
|
api.AllowKeyInParam = append(api.AllowKeyInParam, "/console")
|
||||||
api.Router.HandleFunc("/console", apiConsole(backend)).Methods("GET")
|
api.Router.HandleFunc("/console", apiConsole(backend)).Methods("GET")
|
||||||
api.Router.HandleFunc("/shutdown", apiShutdown(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.
|
// parseCmdParams parses the "-webapi", "-apikey", and "-watchpid" command line parameters.
|
||||||
|
|||||||
11
Debug empty.go
Normal file
11
Debug empty.go
Normal 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
98
Debug.go
Normal 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.
|
||||||
|
*/
|
||||||
3
Main.go
3
Main.go
@@ -19,7 +19,8 @@ const appName = "Peernet Cmd"
|
|||||||
|
|
||||||
var config struct {
|
var config struct {
|
||||||
// Log settings
|
// Log settings
|
||||||
ErrorOutput int `yaml:"ErrorOutput"` // 0 = Log file (default), 1 = Command line, 2 = Log file + command line, 3 = None
|
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
|
// 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.
|
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.
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -231,3 +231,21 @@ Use the parameter `-watchpid=[PID]` to specify a process ID to monitor for exit
|
|||||||
```
|
```
|
||||||
Cmd -watchpid=1234
|
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
2
go.mod
@@ -3,7 +3,7 @@ module github.com/PeernetOfficial/Cmd
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
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/google/uuid v1.3.0
|
||||||
github.com/gorilla/websocket v1.4.3-0.20210424162022-e8629af678b7
|
github.com/gorilla/websocket v1.4.3-0.20210424162022-e8629af678b7
|
||||||
)
|
)
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -1,7 +1,7 @@
|
|||||||
github.com/IncSW/geoip2 v0.1.1 h1:afzzYF7n9JbdcPy8aiBSgBJuXi4mTWXZ3z6V3o6Vg34=
|
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/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-20220103002105-a19bac19163f h1:nkMU/dzSA61anIeBJGfCsq1+Ek6VR+BNXi4FnFkVu8k=
|
||||||
github.com/PeernetOfficial/core v0.0.0-20211231003743-0689543d432f/go.mod h1:VNhfwAZqya5JDZTS/ffa8Shof0OmQCx025CQMieGB7o=
|
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 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK4w=
|
||||||
github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI=
|
github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI=
|
||||||
github.com/enfipy/locker v1.1.0 h1:2zVJ0ky7cS1Vjs0x6OQWFiT2dSEiHrI5/O2KCz1fgGc=
|
github.com/enfipy/locker v1.1.0 h1:2zVJ0ky7cS1Vjs0x6OQWFiT2dSEiHrI5/O2KCz1fgGc=
|
||||||
|
|||||||
Reference in New Issue
Block a user