github.com/minio/madmin-go@v1.7.5/profiling-commands.go (about) 1 // 2 // MinIO Object Storage (c) 2021 MinIO, Inc. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 package madmin 18 19 import ( 20 "context" 21 "encoding/json" 22 "errors" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "net/http" 27 "net/url" 28 "time" 29 ) 30 31 // ProfilerType represents the profiler type 32 // passed to the profiler subsystem. 33 type ProfilerType string 34 35 // Different supported profiler types. 36 const ( 37 ProfilerCPU ProfilerType = "cpu" // represents CPU profiler type 38 ProfilerCPUIO ProfilerType = "cpuio" // represents CPU with IO (fgprof) profiler type 39 ProfilerMEM ProfilerType = "mem" // represents MEM profiler type 40 ProfilerBlock ProfilerType = "block" // represents Block profiler type 41 ProfilerMutex ProfilerType = "mutex" // represents Mutex profiler type 42 ProfilerTrace ProfilerType = "trace" // represents Trace profiler type 43 ProfilerThreads ProfilerType = "threads" // represents ThreadCreate profiler type 44 ProfilerGoroutines ProfilerType = "goroutines" // represents Goroutine dumps. 45 ) 46 47 // StartProfilingResult holds the result of starting 48 // profiler result in a given node. 49 type StartProfilingResult struct { 50 NodeName string `json:"nodeName"` 51 Success bool `json:"success"` 52 Error string `json:"error"` 53 } 54 55 // StartProfiling makes an admin call to remotely start profiling on a standalone 56 // server or the whole cluster in case of a distributed setup. 57 // Deprecated: use Profile API instead 58 func (adm *AdminClient) StartProfiling(ctx context.Context, profiler ProfilerType) ([]StartProfilingResult, error) { 59 v := url.Values{} 60 v.Set("profilerType", string(profiler)) 61 resp, err := adm.executeMethod(ctx, 62 http.MethodPost, requestData{ 63 relPath: adminAPIPrefix + "/profiling/start", 64 queryValues: v, 65 }, 66 ) 67 defer closeResponse(resp) 68 if err != nil { 69 return nil, err 70 } 71 72 if resp.StatusCode != http.StatusOK { 73 return nil, httpRespToErrorResponse(resp) 74 } 75 76 jsonResult, err := ioutil.ReadAll(resp.Body) 77 if err != nil { 78 return nil, err 79 } 80 81 var startResults []StartProfilingResult 82 err = json.Unmarshal(jsonResult, &startResults) 83 if err != nil { 84 return nil, err 85 } 86 87 return startResults, nil 88 } 89 90 // DownloadProfilingData makes an admin call to download profiling data of a standalone 91 // server or of the whole cluster in case of a distributed setup. 92 // Deprecated: use Profile API instead 93 func (adm *AdminClient) DownloadProfilingData(ctx context.Context) (io.ReadCloser, error) { 94 path := fmt.Sprintf(adminAPIPrefix + "/profiling/download") 95 resp, err := adm.executeMethod(ctx, 96 http.MethodGet, requestData{ 97 relPath: path, 98 }, 99 ) 100 if err != nil { 101 closeResponse(resp) 102 return nil, err 103 } 104 105 if resp.StatusCode != http.StatusOK { 106 return nil, httpRespToErrorResponse(resp) 107 } 108 109 if resp.Body == nil { 110 return nil, errors.New("body is nil") 111 } 112 113 return resp.Body, nil 114 } 115 116 // Profile makes an admin call to remotely start profiling on a standalone 117 // server or the whole cluster in case of a distributed setup for a specified duration. 118 func (adm *AdminClient) Profile(ctx context.Context, profiler ProfilerType, duration time.Duration) (io.ReadCloser, error) { 119 v := url.Values{} 120 v.Set("profilerType", string(profiler)) 121 v.Set("duration", duration.String()) 122 resp, err := adm.executeMethod(ctx, 123 http.MethodPost, requestData{ 124 relPath: adminAPIPrefix + "/profile", 125 queryValues: v, 126 }, 127 ) 128 if err != nil { 129 closeResponse(resp) 130 return nil, err 131 } 132 133 if resp.StatusCode != http.StatusOK { 134 return nil, httpRespToErrorResponse(resp) 135 } 136 137 if resp.Body == nil { 138 return nil, errors.New("body is nil") 139 } 140 return resp.Body, nil 141 }