From ca014c065d24972e975cf7f3649d86b468275b39 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 26 Sep 2018 21:10:51 +0200 Subject: [PATCH] pprof: create HTTP endpoint for setting MutexProfileFraction Allows to dynamically change the MutexProfileFraction to enable and disable mutex profiling. It should be very useful for detecting deadlocks, lock contention and general concurrency problems. How to use: To enable run: curl -X POST -v 'localhost:5001/debug/pprof-mutex/?fraction=10 To disable: curl -X POST -v 'localhost:5001/debug/pprof-mutex/?fraction=0' Fraction defines which fraction of events will be profiled. Higher it is the lower performance impact but less reliable the result. To fetch the result use: go tool pprof $PATH_TO_IPFS_BIN http://localhost:5001/debug/pprof/mutex License: MIT Signed-off-by: Jakub Sztandera --- cmd/ipfs/daemon.go | 1 + core/corehttp/mutex_profile.go | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 core/corehttp/mutex_profile.go diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 9d2ca22696e8..01c111935ced 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -448,6 +448,7 @@ func serveHTTPApi(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, error corehttp.VersionOption(), defaultMux("/debug/vars"), defaultMux("/debug/pprof/"), + corehttp.MutexFractionOption("/debug/pprof-mutex/"), corehttp.MetricsScrapingOption("/debug/metrics/prometheus"), corehttp.LogOption(), } diff --git a/core/corehttp/mutex_profile.go b/core/corehttp/mutex_profile.go new file mode 100644 index 000000000000..6f629746e95a --- /dev/null +++ b/core/corehttp/mutex_profile.go @@ -0,0 +1,43 @@ +package corehttp + +import ( + "net" + "net/http" + "runtime" + "strconv" + + core "github.com/ipfs/go-ipfs/core" +) + +func MutexFractionOption(path string) ServeOption { + return func(_ *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) { + mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + if err := r.ParseForm(); err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + asfr := r.Form.Get("fraction") + if len(asfr) == 0 { + w.WriteHeader(http.StatusBadRequest) + return + } + + fr, err := strconv.Atoi(asfr) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + log.Infof("Setting MutexProfileFraction to %d", fr) + runtime.SetMutexProfileFraction(fr) + }) + + return mux, nil + } +}