github.com/minio/madmin-go/v2@v2.2.1/profiling-commands.go (about) 1 // 2 // Copyright (c) 2015-2022 MinIO, Inc. 3 // 4 // This file is part of MinIO Object Storage stack 5 // 6 // This program is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU Affero General Public License as 8 // published by the Free Software Foundation, either version 3 of the 9 // License, or (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU Affero General Public License for more details. 15 // 16 // You should have received a copy of the GNU Affero General Public License 17 // along with this program. If not, see <http://www.gnu.org/licenses/>. 18 // 19 20 package madmin 21 22 import ( 23 "context" 24 "encoding/json" 25 "errors" 26 "fmt" 27 "io" 28 "io/ioutil" 29 "net/http" 30 "net/url" 31 "time" 32 ) 33 34 // ProfilerType represents the profiler type 35 // passed to the profiler subsystem. 36 type ProfilerType string 37 38 // Different supported profiler types. 39 const ( 40 ProfilerCPU ProfilerType = "cpu" // represents CPU profiler type 41 ProfilerCPUIO ProfilerType = "cpuio" // represents CPU with IO (fgprof) profiler type 42 ProfilerMEM ProfilerType = "mem" // represents MEM profiler type 43 ProfilerBlock ProfilerType = "block" // represents Block profiler type 44 ProfilerMutex ProfilerType = "mutex" // represents Mutex profiler type 45 ProfilerTrace ProfilerType = "trace" // represents Trace profiler type 46 ProfilerThreads ProfilerType = "threads" // represents ThreadCreate profiler type 47 ProfilerGoroutines ProfilerType = "goroutines" // represents Goroutine dumps. 48 ) 49 50 // StartProfilingResult holds the result of starting 51 // profiler result in a given node. 52 type StartProfilingResult struct { 53 NodeName string `json:"nodeName"` 54 Success bool `json:"success"` 55 Error string `json:"error"` 56 } 57 58 // StartProfiling makes an admin call to remotely start profiling on a standalone 59 // server or the whole cluster in case of a distributed setup. 60 // Deprecated: use Profile API instead 61 func (adm *AdminClient) StartProfiling(ctx context.Context, profiler ProfilerType) ([]StartProfilingResult, error) { 62 v := url.Values{} 63 v.Set("profilerType", string(profiler)) 64 resp, err := adm.executeMethod(ctx, 65 http.MethodPost, requestData{ 66 relPath: adminAPIPrefix + "/profiling/start", 67 queryValues: v, 68 }, 69 ) 70 defer closeResponse(resp) 71 if err != nil { 72 return nil, err 73 } 74 75 if resp.StatusCode != http.StatusOK { 76 return nil, httpRespToErrorResponse(resp) 77 } 78 79 jsonResult, err := ioutil.ReadAll(resp.Body) 80 if err != nil { 81 return nil, err 82 } 83 84 var startResults []StartProfilingResult 85 err = json.Unmarshal(jsonResult, &startResults) 86 if err != nil { 87 return nil, err 88 } 89 90 return startResults, nil 91 } 92 93 // DownloadProfilingData makes an admin call to download profiling data of a standalone 94 // server or of the whole cluster in case of a distributed setup. 95 // Deprecated: use Profile API instead 96 func (adm *AdminClient) DownloadProfilingData(ctx context.Context) (io.ReadCloser, error) { 97 path := fmt.Sprintf(adminAPIPrefix + "/profiling/download") 98 resp, err := adm.executeMethod(ctx, 99 http.MethodGet, requestData{ 100 relPath: path, 101 }, 102 ) 103 if err != nil { 104 closeResponse(resp) 105 return nil, err 106 } 107 108 if resp.StatusCode != http.StatusOK { 109 return nil, httpRespToErrorResponse(resp) 110 } 111 112 if resp.Body == nil { 113 return nil, errors.New("body is nil") 114 } 115 116 return resp.Body, nil 117 } 118 119 // Profile makes an admin call to remotely start profiling on a standalone 120 // server or the whole cluster in case of a distributed setup for a specified duration. 121 func (adm *AdminClient) Profile(ctx context.Context, profiler ProfilerType, duration time.Duration) (io.ReadCloser, error) { 122 v := url.Values{} 123 v.Set("profilerType", string(profiler)) 124 v.Set("duration", duration.String()) 125 resp, err := adm.executeMethod(ctx, 126 http.MethodPost, requestData{ 127 relPath: adminAPIPrefix + "/profile", 128 queryValues: v, 129 }, 130 ) 131 if err != nil { 132 closeResponse(resp) 133 return nil, err 134 } 135 136 if resp.StatusCode != http.StatusOK { 137 return nil, httpRespToErrorResponse(resp) 138 } 139 140 if resp.Body == nil { 141 return nil, errors.New("body is nil") 142 } 143 return resp.Body, nil 144 }