storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/madmin/profiling-commands.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2017, 2018 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 18 package madmin 19 20 import ( 21 "context" 22 "encoding/json" 23 "errors" 24 "fmt" 25 "io" 26 "io/ioutil" 27 "net/http" 28 "net/url" 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 ProfilerMEM ProfilerType = "mem" // represents MEM profiler type 39 ProfilerBlock ProfilerType = "block" // represents Block profiler type 40 ProfilerMutex ProfilerType = "mutex" // represents Mutex profiler type 41 ProfilerTrace ProfilerType = "trace" // represents Trace profiler type 42 ProfilerThreads ProfilerType = "threads" // represents ThreadCreate profiler type 43 ProfilerGoroutines ProfilerType = "goroutines" // represents Goroutine dumps. 44 ) 45 46 // StartProfilingResult holds the result of starting 47 // profiler result in a given node. 48 type StartProfilingResult struct { 49 NodeName string `json:"nodeName"` 50 Success bool `json:"success"` 51 Error string `json:"error"` 52 } 53 54 // StartProfiling makes an admin call to remotely start profiling on a standalone 55 // server or the whole cluster in case of a distributed setup. 56 func (adm *AdminClient) StartProfiling(ctx context.Context, profiler ProfilerType) ([]StartProfilingResult, error) { 57 v := url.Values{} 58 v.Set("profilerType", string(profiler)) 59 resp, err := adm.executeMethod(ctx, 60 http.MethodPost, requestData{ 61 relPath: adminAPIPrefix + "/profiling/start", 62 queryValues: v, 63 }, 64 ) 65 defer closeResponse(resp) 66 if err != nil { 67 return nil, err 68 } 69 70 if resp.StatusCode != http.StatusOK { 71 return nil, httpRespToErrorResponse(resp) 72 } 73 74 jsonResult, err := ioutil.ReadAll(resp.Body) 75 if err != nil { 76 return nil, err 77 } 78 79 var startResults []StartProfilingResult 80 err = json.Unmarshal(jsonResult, &startResults) 81 if err != nil { 82 return nil, err 83 } 84 85 return startResults, nil 86 } 87 88 // DownloadProfilingData makes an admin call to download profiling data of a standalone 89 // server or of the whole cluster in case of a distributed setup. 90 func (adm *AdminClient) DownloadProfilingData(ctx context.Context) (io.ReadCloser, error) { 91 path := fmt.Sprintf(adminAPIPrefix + "/profiling/download") 92 resp, err := adm.executeMethod(ctx, 93 http.MethodGet, requestData{ 94 relPath: path, 95 }, 96 ) 97 98 if err != nil { 99 closeResponse(resp) 100 return nil, err 101 } 102 103 if resp.StatusCode != http.StatusOK { 104 return nil, httpRespToErrorResponse(resp) 105 } 106 107 if resp.Body == nil { 108 return nil, errors.New("body is nil") 109 } 110 111 return resp.Body, nil 112 }