github.com/minio/madmin-go/v3@v3.0.51/perf-object.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 "net/http" 27 "net/url" 28 "strconv" 29 "time" 30 ) 31 32 // SpeedTestStatServer - stats of a server 33 type SpeedTestStatServer struct { 34 Endpoint string `json:"endpoint"` 35 ThroughputPerSec uint64 `json:"throughputPerSec"` 36 ObjectsPerSec uint64 `json:"objectsPerSec"` 37 Err string `json:"err"` 38 } 39 40 // SpeedTestStats - stats of all the servers 41 type SpeedTestStats struct { 42 ThroughputPerSec uint64 `json:"throughputPerSec"` 43 ObjectsPerSec uint64 `json:"objectsPerSec"` 44 Response Timings `json:"responseTime"` 45 TTFB Timings `json:"ttfb,omitempty"` 46 Servers []SpeedTestStatServer `json:"servers"` 47 } 48 49 // SpeedTestResult - result of the speedtest() call 50 type SpeedTestResult struct { 51 Version string `json:"version"` 52 Servers int `json:"servers"` 53 Disks int `json:"disks"` 54 Size int `json:"size"` 55 Concurrent int `json:"concurrent"` 56 PUTStats SpeedTestStats 57 GETStats SpeedTestStats 58 } 59 60 // SpeedtestOpts provide configurable options for speedtest 61 type SpeedtestOpts struct { 62 Size int // Object size used in speed test 63 Concurrency int // Concurrency used in speed test 64 Duration time.Duration // Total duration of the speed test 65 Autotune bool // Enable autotuning 66 StorageClass string // Choose type of storage-class to be used while performing I/O 67 Bucket string // Choose a custom bucket name while performing I/O 68 NoClear bool // Avoid cleanup after running an object speed test 69 EnableSha256 bool // Enable calculating sha256 for uploads 70 } 71 72 // Speedtest - perform speedtest on the MinIO servers 73 func (adm *AdminClient) Speedtest(ctx context.Context, opts SpeedtestOpts) (chan SpeedTestResult, error) { 74 if !opts.Autotune { 75 if opts.Duration <= time.Second { 76 return nil, errors.New("duration must be greater a second") 77 } 78 if opts.Size <= 0 { 79 return nil, errors.New("size must be greater than 0 bytes") 80 } 81 if opts.Concurrency <= 0 { 82 return nil, errors.New("concurrency must be greater than 0") 83 } 84 } 85 86 queryVals := make(url.Values) 87 if opts.Size > 0 { 88 queryVals.Set("size", strconv.Itoa(opts.Size)) 89 } 90 if opts.Duration > 0 { 91 queryVals.Set("duration", opts.Duration.String()) 92 } 93 if opts.Concurrency > 0 { 94 queryVals.Set("concurrent", strconv.Itoa(opts.Concurrency)) 95 } 96 if opts.Bucket != "" { 97 queryVals.Set("bucket", opts.Bucket) 98 } 99 if opts.Autotune { 100 queryVals.Set("autotune", "true") 101 } 102 if opts.NoClear { 103 queryVals.Set("noclear", "true") 104 } 105 if opts.EnableSha256 { 106 queryVals.Set("enableSha256", "true") 107 } 108 resp, err := adm.executeMethod(ctx, 109 http.MethodPost, requestData{ 110 relPath: adminAPIPrefix + "/speedtest", 111 queryValues: queryVals, 112 }) 113 if err != nil { 114 return nil, err 115 } 116 if resp.StatusCode != http.StatusOK { 117 return nil, httpRespToErrorResponse(resp) 118 } 119 ch := make(chan SpeedTestResult) 120 go func() { 121 defer closeResponse(resp) 122 defer close(ch) 123 dec := json.NewDecoder(resp.Body) 124 for { 125 var result SpeedTestResult 126 if err := dec.Decode(&result); err != nil { 127 return 128 } 129 select { 130 case ch <- result: 131 case <-ctx.Done(): 132 return 133 } 134 } 135 }() 136 return ch, nil 137 }