| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | // Copyright (c) 2015-2022 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 05:46:50 +08:00
										 |  |  | 	"github.com/minio/madmin-go/v2" | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 	"github.com/minio/minio/internal/disk" | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | type collectMetricsOpts struct { | 
					
						
							|  |  |  | 	hosts map[string]struct{} | 
					
						
							|  |  |  | 	disks map[string]struct{} | 
					
						
							|  |  |  | 	jobID string | 
					
						
							| 
									
										
										
										
											2022-11-14 23:16:40 +08:00
										 |  |  | 	depID string | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func collectLocalMetrics(types madmin.MetricType, opts collectMetricsOpts) (m madmin.RealtimeMetrics) { | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 	if types == madmin.MetricsNone { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | 	if len(opts.hosts) > 0 { | 
					
						
							|  |  |  | 		if _, ok := opts.hosts[globalMinioAddr]; !ok { | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | 	if types.Contains(madmin.MetricsDisk) { | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 		m.ByDisk = make(map[string]madmin.DiskMetric) | 
					
						
							|  |  |  | 		aggr := madmin.DiskMetric{ | 
					
						
							|  |  |  | 			CollectedAt: time.Now(), | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | 		for name, disk := range collectLocalDisksMetrics(opts.disks) { | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 			m.ByDisk[name] = disk | 
					
						
							|  |  |  | 			aggr.Merge(&disk) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		m.Aggregated.Disk = &aggr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 	if types.Contains(madmin.MetricsScanner) { | 
					
						
							|  |  |  | 		metrics := globalScannerMetrics.report() | 
					
						
							|  |  |  | 		m.Aggregated.Scanner = &metrics | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if types.Contains(madmin.MetricsOS) { | 
					
						
							|  |  |  | 		metrics := globalOSMetrics.report() | 
					
						
							|  |  |  | 		m.Aggregated.OS = &metrics | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | 	if types.Contains(madmin.MetricsBatchJobs) { | 
					
						
							|  |  |  | 		m.Aggregated.BatchJobs = globalBatchJobsMetrics.report(opts.jobID) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-11-14 23:16:40 +08:00
										 |  |  | 	if types.Contains(madmin.MetricsSiteResync) { | 
					
						
							|  |  |  | 		m.Aggregated.SiteResync = globalSiteResyncMetrics.report(opts.depID) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 	// Add types...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// ByHost is a shallow reference, so careful about sharing.
 | 
					
						
							|  |  |  | 	m.ByHost = map[string]madmin.Metrics{globalMinioAddr: m.Aggregated} | 
					
						
							|  |  |  | 	m.Hosts = append(m.Hosts, globalMinioAddr) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return m | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | func collectLocalDisksMetrics(disks map[string]struct{}) map[string]madmin.DiskMetric { | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 	objLayer := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objLayer == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	metrics := make(map[string]madmin.DiskMetric) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procStats, procErr := disk.GetAllDrivesIOStats() | 
					
						
							|  |  |  | 	if procErr != nil { | 
					
						
							|  |  |  | 		return metrics | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 06:31:35 +08:00
										 |  |  | 	storageInfo := objLayer.LocalStorageInfo(GlobalContext) | 
					
						
							|  |  |  | 	for _, d := range storageInfo.Disks { | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 		if len(disks) != 0 { | 
					
						
							|  |  |  | 			_, ok := disks[d.Endpoint] | 
					
						
							|  |  |  | 			if !ok { | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 06:31:35 +08:00
										 |  |  | 		if d.State != madmin.DriveStateOk && d.State != madmin.DriveStateUnformatted { | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 			metrics[d.Endpoint] = madmin.DiskMetric{NDisks: 1, Offline: 1} | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		var dm madmin.DiskMetric | 
					
						
							|  |  |  | 		dm.NDisks = 1 | 
					
						
							|  |  |  | 		if d.Healing { | 
					
						
							|  |  |  | 			dm.Healing++ | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 		if d.Metrics != nil { | 
					
						
							|  |  |  | 			dm.LifeTimeOps = make(map[string]uint64, len(d.Metrics.APICalls)) | 
					
						
							|  |  |  | 			for k, v := range d.Metrics.APICalls { | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 				if v != 0 { | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 					dm.LifeTimeOps[k] = v | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 			dm.LastMinute.Operations = make(map[string]madmin.TimedAction, len(d.Metrics.APICalls)) | 
					
						
							|  |  |  | 			for k, v := range d.Metrics.LastMinute { | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 				if v.Count != 0 { | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 					dm.LastMinute.Operations[k] = v | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// get disk
 | 
					
						
							|  |  |  | 		if procErr == nil { | 
					
						
							|  |  |  | 			st := procStats[disk.DevID{Major: d.Major, Minor: d.Minor}] | 
					
						
							|  |  |  | 			dm.IOStats = madmin.DiskIOStats{ | 
					
						
							|  |  |  | 				ReadIOs:        st.ReadIOs, | 
					
						
							|  |  |  | 				ReadMerges:     st.ReadMerges, | 
					
						
							|  |  |  | 				ReadSectors:    st.ReadSectors, | 
					
						
							|  |  |  | 				ReadTicks:      st.ReadTicks, | 
					
						
							|  |  |  | 				WriteIOs:       st.WriteIOs, | 
					
						
							|  |  |  | 				WriteMerges:    st.WriteMerges, | 
					
						
							|  |  |  | 				WriteSectors:   st.WriteSectors, | 
					
						
							|  |  |  | 				WriteTicks:     st.WriteTicks, | 
					
						
							|  |  |  | 				CurrentIOs:     st.CurrentIOs, | 
					
						
							|  |  |  | 				TotalTicks:     st.TotalTicks, | 
					
						
							|  |  |  | 				ReqTicks:       st.ReqTicks, | 
					
						
							|  |  |  | 				DiscardIOs:     st.DiscardIOs, | 
					
						
							|  |  |  | 				DiscardMerges:  st.DiscardMerges, | 
					
						
							|  |  |  | 				DiscardSectors: st.DiscardSectors, | 
					
						
							|  |  |  | 				DiscardTicks:   st.DiscardTicks, | 
					
						
							|  |  |  | 				FlushIOs:       st.FlushIOs, | 
					
						
							|  |  |  | 				FlushTicks:     st.FlushTicks, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		metrics[d.Endpoint] = dm | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 	return metrics | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | func collectRemoteMetrics(ctx context.Context, types madmin.MetricType, opts collectMetricsOpts) (m madmin.RealtimeMetrics) { | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 	if !globalIsDistErasure { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-03 17:10:15 +08:00
										 |  |  | 	all := globalNotificationSys.GetMetrics(ctx, types, opts) | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 	for _, remote := range all { | 
					
						
							|  |  |  | 		m.Merge(&remote) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return m | 
					
						
							|  |  |  | } |