diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index f72f2bd6c..81097f1ef 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -286,9 +286,9 @@ type StartProfilingResult struct { Error string `json:"error"` } -// StartProfilingHandler - POST /minio/admin/v1/profiling/start/{profiler} +// StartProfilingHandler - POST /minio/admin/v1/profiling/start?profilerType={profilerType} // ---------- -// Enable profiling information +// Enable server profiling func (a adminAPIHandlers) StartProfilingHandler(w http.ResponseWriter, r *http.Request) { adminAPIErr := checkAdminRequestAuthType(r, "") if adminAPIErr != ErrNone { @@ -297,7 +297,7 @@ func (a adminAPIHandlers) StartProfilingHandler(w http.ResponseWriter, r *http.R } vars := mux.Vars(r) - profiler := vars["profiler"] + profiler := vars["profilerType"] startProfilingResult := make([]StartProfilingResult, len(globalAdminPeers)) diff --git a/cmd/admin-router.go b/cmd/admin-router.go index 70cb093c6..a8ad08b9d 100644 --- a/cmd/admin-router.go +++ b/cmd/admin-router.go @@ -61,7 +61,8 @@ func registerAdminRouter(router *mux.Router) { adminV1Router.Methods(http.MethodPost).Path("/heal/{bucket}/{prefix:.*}").HandlerFunc(httpTraceAll(adminAPI.HealHandler)) // Profiling operations - adminV1Router.Methods(http.MethodPost).Path("/profiling/start/{profiler}").HandlerFunc(httpTraceAll(adminAPI.StartProfilingHandler)) + adminV1Router.Methods(http.MethodPost).Path("/profiling/start").HandlerFunc(httpTraceAll(adminAPI.StartProfilingHandler)). + Queries("profilerType", "{profilerType:.*}") adminV1Router.Methods(http.MethodGet).Path("/profiling/download").HandlerFunc(httpTraceAll(adminAPI.DownloadProfilingHandler)) /// Config operations diff --git a/cmd/utils.go b/cmd/utils.go index 950cd670a..726b7113a 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -226,6 +226,10 @@ func startProfiler(profilerType, dirPath string) (interface { profiler = profile.Start(profile.MemProfile, profile.NoShutdownHook, profile.ProfilePath(dirPath)) case "block": profiler = profile.Start(profile.BlockProfile, profile.NoShutdownHook, profile.ProfilePath(dirPath)) + case "mutex": + profiler = profile.Start(profile.MutexProfile, profile.NoShutdownHook, profile.ProfilePath(dirPath)) + case "trace": + profiler = profile.Start(profile.TraceProfile, profile.NoShutdownHook, profile.ProfilePath(dirPath)) default: return nil, errors.New("profiler type unknown") } diff --git a/pkg/madmin/api.go b/pkg/madmin/api.go index 6c95f6d6e..6ed79d808 100644 --- a/pkg/madmin/api.go +++ b/pkg/madmin/api.go @@ -176,7 +176,7 @@ func (c *AdminClient) TraceOff() { type requestData struct { customHeaders http.Header queryValues url.Values - relPath string // Url path relative to admin API base endpoint + relPath string // URL path relative to admin API base endpoint content []byte } diff --git a/pkg/madmin/profiling-commands.go b/pkg/madmin/profiling-commands.go index 6639665af..ab686a1cf 100644 --- a/pkg/madmin/profiling-commands.go +++ b/pkg/madmin/profiling-commands.go @@ -24,20 +24,20 @@ import ( "io" "io/ioutil" "net/http" + "net/url" ) // ProfilerType represents the profiler type -// passed to the profiler subsystem, currently -// it can be only "cpu", "mem" or "block" +// passed to the profiler subsystem. type ProfilerType string +// Different supported profiler types. const ( - // ProfilerCPU represents CPU profiler type - ProfilerCPU = ProfilerType("cpu") - // ProfilerMEM represents MEM profiler type - ProfilerMEM = ProfilerType("mem") - // ProfilerBlock represents Block profiler type - ProfilerBlock = ProfilerType("block") + ProfilerCPU ProfilerType = "cpu" // represents CPU profiler type + ProfilerMEM = "mem" // represents MEM profiler type + ProfilerBlock = "block" // represents Block profiler type + ProfilerMutex = "mutex" // represents Mutex profiler type + ProfilerTrace = "trace" // represents Trace profiler type ) // StartProfilingResult holds the result of starting @@ -51,9 +51,11 @@ type StartProfilingResult struct { // StartProfiling makes an admin call to remotely start profiling on a standalone // server or the whole cluster in case of a distributed setup. func (adm *AdminClient) StartProfiling(profiler ProfilerType) ([]StartProfilingResult, error) { - path := fmt.Sprintf("/v1/profiling/start/%s", profiler) + v := url.Values{} + v.Set("profilerType", string(profiler)) resp, err := adm.executeMethod("POST", requestData{ - relPath: path, + relPath: "/v1/profiling/start", + queryValues: v, }) defer closeResponse(resp) if err != nil {