storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/healthinfo.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2020 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 cmd 19 20 import ( 21 "context" 22 "fmt" 23 "net/http" 24 "os" 25 "sync" 26 "syscall" 27 28 cpuhw "github.com/shirou/gopsutil/v3/cpu" 29 memhw "github.com/shirou/gopsutil/v3/mem" 30 "github.com/shirou/gopsutil/v3/process" 31 32 "storj.io/minio/pkg/disk" 33 "storj.io/minio/pkg/madmin" 34 ) 35 36 func getLocalCPUInfo(ctx context.Context, r *http.Request) madmin.ServerCPUInfo { 37 addr := r.Host 38 if globalIsDistErasure { 39 addr = globalLocalNodeName 40 } 41 42 info, err := cpuhw.InfoWithContext(ctx) 43 if err != nil { 44 return madmin.ServerCPUInfo{ 45 Addr: addr, 46 Error: fmt.Sprintf("info: %v", err), 47 } 48 } 49 50 time, err := cpuhw.TimesWithContext(ctx, false) 51 if err != nil { 52 return madmin.ServerCPUInfo{ 53 Addr: addr, 54 Error: fmt.Sprintf("times: %v", err), 55 } 56 } 57 58 return madmin.ServerCPUInfo{ 59 Addr: addr, 60 CPUStat: info, 61 TimeStat: time, 62 } 63 64 } 65 66 func getLocalDrives(ctx context.Context, parallel bool, endpointServerPools EndpointServerPools, r *http.Request) madmin.ServerDrivesInfo { 67 var drivesPerfInfo []madmin.DrivePerfInfo 68 var wg sync.WaitGroup 69 for _, ep := range endpointServerPools { 70 for _, endpoint := range ep.Endpoints { 71 // Only proceed for local endpoints 72 if endpoint.IsLocal { 73 if _, err := os.Stat(endpoint.Path); err != nil { 74 // Since this drive is not available, add relevant details and proceed 75 drivesPerfInfo = append(drivesPerfInfo, madmin.DrivePerfInfo{ 76 Path: endpoint.Path, 77 Error: fmt.Sprintf("stat: %v", err), 78 }) 79 continue 80 } 81 measurePath := pathJoin(minioMetaTmpBucket, mustGetUUID()) 82 measure := func(path string) { 83 defer wg.Done() 84 driveInfo := madmin.DrivePerfInfo{ 85 Path: path, 86 } 87 latency, throughput, err := disk.GetHealthInfo(ctx, path, pathJoin(path, measurePath)) 88 if err != nil { 89 driveInfo.Error = fmt.Sprintf("health-info: %v", err) 90 } else { 91 driveInfo.Latency = latency 92 driveInfo.Throughput = throughput 93 } 94 drivesPerfInfo = append(drivesPerfInfo, driveInfo) 95 } 96 wg.Add(1) 97 98 if parallel { 99 go measure(endpoint.Path) 100 } else { 101 measure(endpoint.Path) 102 } 103 } 104 } 105 } 106 wg.Wait() 107 108 addr := r.Host 109 if globalIsDistErasure { 110 addr = globalLocalNodeName 111 } 112 if parallel { 113 return madmin.ServerDrivesInfo{ 114 Addr: addr, 115 Parallel: drivesPerfInfo, 116 } 117 } 118 return madmin.ServerDrivesInfo{ 119 Addr: addr, 120 Serial: drivesPerfInfo, 121 } 122 } 123 124 func getLocalMemInfo(ctx context.Context, r *http.Request) madmin.ServerMemInfo { 125 addr := r.Host 126 if globalIsDistErasure { 127 addr = globalLocalNodeName 128 } 129 130 swap, err := memhw.SwapMemoryWithContext(ctx) 131 if err != nil { 132 return madmin.ServerMemInfo{ 133 Addr: addr, 134 Error: fmt.Sprintf("swap: %v", err), 135 } 136 } 137 138 vm, err := memhw.VirtualMemoryWithContext(ctx) 139 if err != nil { 140 return madmin.ServerMemInfo{ 141 Addr: addr, 142 Error: fmt.Sprintf("virtual-mem: %v", err), 143 } 144 } 145 146 return madmin.ServerMemInfo{ 147 Addr: addr, 148 SwapMem: swap, 149 VirtualMem: vm, 150 } 151 } 152 153 func getLocalProcInfo(ctx context.Context, r *http.Request) madmin.ServerProcInfo { 154 addr := r.Host 155 if globalIsDistErasure { 156 addr = globalLocalNodeName 157 } 158 159 errProcInfo := func(tag string, err error) madmin.ServerProcInfo { 160 return madmin.ServerProcInfo{ 161 Addr: addr, 162 Error: fmt.Sprintf("%s: %v", tag, err), 163 } 164 } 165 166 selfPid := int32(syscall.Getpid()) 167 self, err := process.NewProcess(selfPid) 168 if err != nil { 169 return errProcInfo("new-process", err) 170 } 171 172 processes := []*process.Process{self} 173 174 sysProcs := []madmin.SysProcess{} 175 for _, proc := range processes { 176 sysProc := madmin.SysProcess{} 177 sysProc.Pid = proc.Pid 178 179 bg, err := proc.BackgroundWithContext(ctx) 180 if err != nil { 181 return errProcInfo("background", err) 182 } 183 sysProc.Background = bg 184 185 cpuPercent, err := proc.CPUPercentWithContext(ctx) 186 if err != nil { 187 return errProcInfo("cpu-percent", err) 188 } 189 sysProc.CPUPercent = cpuPercent 190 191 children, _ := proc.ChildrenWithContext(ctx) 192 193 for _, c := range children { 194 sysProc.Children = append(sysProc.Children, c.Pid) 195 } 196 cmdLine, err := proc.CmdlineWithContext(ctx) 197 if err != nil { 198 return errProcInfo("cmdline", err) 199 } 200 sysProc.CmdLine = cmdLine 201 202 conns, err := proc.ConnectionsWithContext(ctx) 203 if err != nil { 204 return errProcInfo("conns", err) 205 } 206 sysProc.ConnectionCount = len(conns) 207 208 createTime, err := proc.CreateTimeWithContext(ctx) 209 if err != nil { 210 return errProcInfo("create-time", err) 211 } 212 sysProc.CreateTime = createTime 213 214 cwd, err := proc.CwdWithContext(ctx) 215 if err != nil { 216 return errProcInfo("cwd", err) 217 } 218 sysProc.Cwd = cwd 219 220 exe, err := proc.ExeWithContext(ctx) 221 if err != nil { 222 return errProcInfo("exe", err) 223 } 224 sysProc.Exe = exe 225 226 gids, err := proc.GidsWithContext(ctx) 227 if err != nil { 228 return errProcInfo("gids", err) 229 } 230 sysProc.Gids = gids 231 232 ioCounters, err := proc.IOCountersWithContext(ctx) 233 if err != nil { 234 return errProcInfo("iocounters", err) 235 } 236 sysProc.IOCounters = ioCounters 237 238 isRunning, err := proc.IsRunningWithContext(ctx) 239 if err != nil { 240 return errProcInfo("is-running", err) 241 } 242 sysProc.IsRunning = isRunning 243 244 memInfo, err := proc.MemoryInfoWithContext(ctx) 245 if err != nil { 246 return errProcInfo("mem-info", err) 247 } 248 sysProc.MemInfo = memInfo 249 250 memMaps, err := proc.MemoryMapsWithContext(ctx, true) 251 if err != nil { 252 return errProcInfo("mem-maps", err) 253 } 254 sysProc.MemMaps = memMaps 255 256 memPercent, err := proc.MemoryPercentWithContext(ctx) 257 if err != nil { 258 return errProcInfo("mem-percent", err) 259 } 260 sysProc.MemPercent = memPercent 261 262 name, err := proc.NameWithContext(ctx) 263 if err != nil { 264 return errProcInfo("name", err) 265 } 266 sysProc.Name = name 267 268 // Refer for more information on NetIOCounters 269 // is useless https://github.com/shirou/gopsutil/issues/429 270 271 nice, err := proc.NiceWithContext(ctx) 272 if err != nil { 273 return errProcInfo("nice", err) 274 } 275 sysProc.Nice = nice 276 277 numCtxSwitches, err := proc.NumCtxSwitchesWithContext(ctx) 278 if err != nil { 279 return errProcInfo("num-ctx-switches", err) 280 } 281 sysProc.NumCtxSwitches = numCtxSwitches 282 283 numFds, err := proc.NumFDsWithContext(ctx) 284 if err != nil { 285 return errProcInfo("num-fds", err) 286 } 287 sysProc.NumFds = numFds 288 289 numThreads, err := proc.NumThreadsWithContext(ctx) 290 if err != nil { 291 return errProcInfo("num-threads", err) 292 } 293 sysProc.NumThreads = numThreads 294 295 pageFaults, err := proc.PageFaultsWithContext(ctx) 296 if err != nil { 297 return errProcInfo("page-faults", err) 298 } 299 sysProc.PageFaults = pageFaults 300 301 parent, err := proc.ParentWithContext(ctx) 302 if err == nil { 303 sysProc.Parent = parent.Pid 304 } 305 306 ppid, err := proc.PpidWithContext(ctx) 307 if err == nil { 308 sysProc.Ppid = ppid 309 } 310 311 status, err := proc.StatusWithContext(ctx) 312 if err != nil { 313 return errProcInfo("status", err) 314 } 315 sysProc.Status = status[0] 316 317 tgid, err := proc.Tgid() 318 if err != nil { 319 return errProcInfo("tgid", err) 320 } 321 sysProc.Tgid = tgid 322 323 times, err := proc.TimesWithContext(ctx) 324 if err != nil { 325 return errProcInfo("times", err) 326 } 327 sysProc.Times = times 328 329 uids, err := proc.UidsWithContext(ctx) 330 if err != nil { 331 return errProcInfo("uids", err) 332 } 333 sysProc.Uids = uids 334 335 username, err := proc.UsernameWithContext(ctx) 336 if err != nil { 337 return errProcInfo("username", err) 338 } 339 sysProc.Username = username 340 341 sysProcs = append(sysProcs, sysProc) 342 } 343 344 return madmin.ServerProcInfo{ 345 Addr: addr, 346 Processes: sysProcs, 347 } 348 }