github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/support-diag-spinner-v3.go (about) 1 // Copyright (c) 2015-2023 MinIO, Inc. 2 // 3 // # This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "errors" 22 "fmt" 23 "io" 24 "sync" 25 "time" 26 27 json "github.com/minio/colorjson" 28 "github.com/minio/madmin-go/v3" 29 "github.com/vbauerster/mpb/v8" 30 "github.com/vbauerster/mpb/v8/decor" 31 ) 32 33 func receiveHealthInfo(decoder *json.Decoder) (info madmin.HealthInfo, e error) { 34 var wg sync.WaitGroup 35 pg := mpb.New(mpb.WithWaitGroup(&wg), mpb.WithWidth(16)) 36 37 spinnerStyle := mpb.SpinnerStyle().Meta(func(s string) string { 38 return infoText(s) 39 }).PositionLeft() 40 41 type progressSpinner struct { 42 name string 43 spinner *mpb.Bar 44 cond func(madmin.HealthInfo) bool 45 } 46 spinners := []progressSpinner{} 47 48 createSpinner := func(name string, cond func(madmin.HealthInfo) bool) { 49 caption := fmt.Sprintf("%s %s ...", dot, name) 50 wip := mpb.PrependDecorators(decor.Name(greenText(caption))) 51 done := mpb.BarFillerOnComplete(greenText(check)) 52 spinner := pg.New(1, spinnerStyle, wip, done) 53 spinners = append(spinners, progressSpinner{ 54 name: name, 55 cond: cond, 56 spinner: spinner, 57 }) 58 } 59 60 createSpinner("CPU Info", func(info madmin.HealthInfo) bool { return len(info.Sys.CPUInfo) > 0 }) 61 createSpinner("Disk Info", func(info madmin.HealthInfo) bool { return len(info.Sys.Partitions) > 0 }) 62 createSpinner("Net Info", func(info madmin.HealthInfo) bool { return len(info.Sys.NetInfo) > 0 }) 63 createSpinner("OS Info", func(info madmin.HealthInfo) bool { return len(info.Sys.OSInfo) > 0 }) 64 createSpinner("Mem Info", func(info madmin.HealthInfo) bool { return len(info.Sys.MemInfo) > 0 }) 65 createSpinner("Process Info", func(info madmin.HealthInfo) bool { return len(info.Sys.ProcInfo) > 0 }) 66 createSpinner("Server Config", func(info madmin.HealthInfo) bool { return info.Minio.Config.Config != nil }) 67 createSpinner("System Errors", func(info madmin.HealthInfo) bool { return len(info.Sys.SysErrs) > 0 }) 68 createSpinner("System Services", func(info madmin.HealthInfo) bool { return len(info.Sys.SysServices) > 0 }) 69 createSpinner("System Config", func(info madmin.HealthInfo) bool { return len(info.Sys.SysConfig) > 0 }) 70 createSpinner("Admin Info", func(info madmin.HealthInfo) bool { return len(info.Minio.Info.Servers) > 0 }) 71 72 wg.Add(len(spinners)) 73 start := time.Now() 74 75 markDone := func(bar *mpb.Bar) { 76 if bar.Current() == 0 { 77 bar.EwmaIncrement(time.Since(start)) 78 wg.Done() 79 } 80 } 81 82 receivedLast := false 83 progress := func(info madmin.HealthInfo) { 84 receivedLast = len(info.Minio.Info.Servers) > 0 85 86 for _, bar := range spinners { 87 if receivedLast || bar.cond(info) { 88 markDone(bar.spinner) 89 } 90 } 91 } 92 93 go func() { 94 for { 95 if e = decoder.Decode(&info); e != nil { 96 if errors.Is(e, io.EOF) { 97 e = nil 98 } 99 100 break 101 } 102 103 progress(info) 104 } 105 }() 106 pg.Wait() 107 return 108 }