| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // Copyright (c) 2015-2021 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/>.
 | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 	"github.com/minio/madmin-go" | 
					
						
							| 
									
										
										
										
											2021-06-02 05:59:40 +08:00
										 |  |  | 	"github.com/minio/minio/internal/disk" | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | //go:generate stringer -type=osMetric -trimprefix=osMetric $GOFILE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type osMetric uint8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	osMetricRemoveAll osMetric = iota | 
					
						
							|  |  |  | 	osMetricMkdirAll | 
					
						
							|  |  |  | 	osMetricRename | 
					
						
							|  |  |  | 	osMetricOpenFile | 
					
						
							|  |  |  | 	osMetricOpen | 
					
						
							|  |  |  | 	osMetricOpenFileDirectIO | 
					
						
							|  |  |  | 	osMetricLstat | 
					
						
							|  |  |  | 	osMetricRemove | 
					
						
							|  |  |  | 	osMetricStat | 
					
						
							| 
									
										
										
										
											2021-03-29 23:07:23 +08:00
										 |  |  | 	osMetricAccess | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	// .... add more
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	osMetricLast | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | func osTrace(s osMetric, startTime time.Time, duration time.Duration, path string) madmin.TraceInfo { | 
					
						
							|  |  |  | 	return madmin.TraceInfo{ | 
					
						
							|  |  |  | 		TraceType: madmin.TraceOS, | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 		Time:      startTime, | 
					
						
							|  |  |  | 		NodeName:  globalLocalNodeName, | 
					
						
							| 
									
										
										
										
											2021-03-28 01:07:07 +08:00
										 |  |  | 		FuncName:  "os." + s.String(), | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 		OSStats: madmin.TraceOSStats{ | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 			Duration: duration, | 
					
						
							|  |  |  | 			Path:     path, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | func updateOSMetrics(s osMetric, paths ...string) func() { | 
					
						
							|  |  |  | 	if globalTrace.NumSubscribers() == 0 { | 
					
						
							|  |  |  | 		return func() {} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	startTime := time.Now() | 
					
						
							|  |  |  | 	return func() { | 
					
						
							|  |  |  | 		duration := time.Since(startTime) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 04:19:14 +08:00
										 |  |  | 		globalTrace.Publish(osTrace(s, startTime, duration, strings.Join(paths, " -> "))) | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RemoveAll captures time taken to call the underlying os.RemoveAll
 | 
					
						
							|  |  |  | func RemoveAll(dirPath string) error { | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	defer updateOSMetrics(osMetricRemoveAll, dirPath)() | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 	return os.RemoveAll(dirPath) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MkdirAll captures time taken to call os.MkdirAll
 | 
					
						
							|  |  |  | func MkdirAll(dirPath string, mode os.FileMode) error { | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	defer updateOSMetrics(osMetricMkdirAll, dirPath)() | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 	return os.MkdirAll(dirPath, mode) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Rename captures time taken to call os.Rename
 | 
					
						
							|  |  |  | func Rename(src, dst string) error { | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	defer updateOSMetrics(osMetricRename, src, dst)() | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 	return os.Rename(src, dst) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // OpenFile captures time taken to call os.OpenFile
 | 
					
						
							|  |  |  | func OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) { | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	defer updateOSMetrics(osMetricOpenFile, name)() | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 	return os.OpenFile(name, flag, perm) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 23:07:23 +08:00
										 |  |  | // Access captures time taken to call syscall.Access()
 | 
					
						
							|  |  |  | // on windows, plan9 and solaris syscall.Access uses
 | 
					
						
							|  |  |  | // os.Lstat()
 | 
					
						
							|  |  |  | func Access(name string) error { | 
					
						
							|  |  |  | 	defer updateOSMetrics(osMetricAccess, name)() | 
					
						
							|  |  |  | 	return access(name) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | // Open captures time taken to call os.Open
 | 
					
						
							|  |  |  | func Open(name string) (*os.File, error) { | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	defer updateOSMetrics(osMetricOpen, name)() | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 	return os.Open(name) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // OpenFileDirectIO captures time taken to call disk.OpenFileDirectIO
 | 
					
						
							|  |  |  | func OpenFileDirectIO(name string, flag int, perm os.FileMode) (*os.File, error) { | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	defer updateOSMetrics(osMetricOpenFileDirectIO, name)() | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 	return disk.OpenFileDirectIO(name, flag, perm) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Lstat captures time taken to call os.Lstat
 | 
					
						
							|  |  |  | func Lstat(name string) (os.FileInfo, error) { | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	defer updateOSMetrics(osMetricLstat, name)() | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 	return os.Lstat(name) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Remove captures time taken to call os.Remove
 | 
					
						
							|  |  |  | func Remove(deletePath string) error { | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	defer updateOSMetrics(osMetricRemove, deletePath)() | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 	return os.Remove(deletePath) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Stat captures time taken to call os.Stat
 | 
					
						
							|  |  |  | func Stat(name string) (os.FileInfo, error) { | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	defer updateOSMetrics(osMetricStat, name)() | 
					
						
							| 
									
										
										
										
											2021-03-24 05:51:27 +08:00
										 |  |  | 	return os.Stat(name) | 
					
						
							|  |  |  | } |