| 
									
										
										
										
											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-04-05 06:34:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | import ( | 
					
						
							| 
									
										
										
										
											2022-09-13 03:40:02 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2021-11-18 04:10:57 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | //go:generate msgp -file $GOFILE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-18 04:10:57 +08:00
										 |  |  | // ReplicationLatency holds information of bucket operations latency, such us uploads
 | 
					
						
							|  |  |  | type ReplicationLatency struct { | 
					
						
							|  |  |  | 	// Single & Multipart PUTs latency
 | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 	UploadHistogram LastMinuteHistogram | 
					
						
							| 
									
										
										
										
											2021-11-18 04:10:57 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Merge two replication latency into a new one
 | 
					
						
							|  |  |  | func (rl ReplicationLatency) merge(other ReplicationLatency) (newReplLatency ReplicationLatency) { | 
					
						
							|  |  |  | 	newReplLatency.UploadHistogram = rl.UploadHistogram.Merge(other.UploadHistogram) | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Get upload latency of each object size range
 | 
					
						
							|  |  |  | func (rl ReplicationLatency) getUploadLatency() (ret map[string]uint64) { | 
					
						
							|  |  |  | 	ret = make(map[string]uint64) | 
					
						
							| 
									
										
										
										
											2022-01-26 08:31:44 +08:00
										 |  |  | 	avg := rl.UploadHistogram.GetAvgData() | 
					
						
							| 
									
										
										
										
											2021-11-18 04:10:57 +08:00
										 |  |  | 	for k, v := range avg { | 
					
						
							|  |  |  | 		// Convert nanoseconds to milliseconds
 | 
					
						
							| 
									
										
										
										
											2022-07-06 05:45:49 +08:00
										 |  |  | 		ret[sizeTagToString(k)] = uint64(v.avg() / time.Millisecond) | 
					
						
							| 
									
										
										
										
											2021-11-18 04:10:57 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Update replication upload latency with a new value
 | 
					
						
							|  |  |  | func (rl *ReplicationLatency) update(size int64, duration time.Duration) { | 
					
						
							|  |  |  | 	rl.UploadHistogram.Add(size, duration) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-24 00:15:30 +08:00
										 |  |  | // BucketStatsMap captures bucket statistics for all buckets
 | 
					
						
							| 
									
										
										
										
											2022-09-13 03:40:02 +08:00
										 |  |  | type BucketStatsMap struct { | 
					
						
							|  |  |  | 	Stats     map[string]BucketStats | 
					
						
							|  |  |  | 	Timestamp time.Time | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-05-24 00:15:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | // BucketStats bucket statistics
 | 
					
						
							|  |  |  | type BucketStats struct { | 
					
						
							|  |  |  | 	ReplicationStats BucketReplicationStats | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // BucketReplicationStats represents inline replication statistics
 | 
					
						
							|  |  |  | // such as pending, failed and completed bytes in total for a bucket
 | 
					
						
							|  |  |  | type BucketReplicationStats struct { | 
					
						
							| 
									
										
										
										
											2022-09-17 08:09:45 +08:00
										 |  |  | 	Stats map[string]*BucketReplicationStat `json:",omitempty"` | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | 	// Pending size in bytes
 | 
					
						
							|  |  |  | 	PendingSize int64 `json:"pendingReplicationSize"` | 
					
						
							|  |  |  | 	// Completed size in bytes
 | 
					
						
							|  |  |  | 	ReplicatedSize int64 `json:"completedReplicationSize"` | 
					
						
							|  |  |  | 	// Total Replica size in bytes
 | 
					
						
							|  |  |  | 	ReplicaSize int64 `json:"replicaSize"` | 
					
						
							|  |  |  | 	// Failed size in bytes
 | 
					
						
							|  |  |  | 	FailedSize int64 `json:"failedReplicationSize"` | 
					
						
							|  |  |  | 	// Total number of pending operations including metadata updates
 | 
					
						
							|  |  |  | 	PendingCount int64 `json:"pendingReplicationCount"` | 
					
						
							|  |  |  | 	// Total number of failed operations including metadata updates
 | 
					
						
							|  |  |  | 	FailedCount int64 `json:"failedReplicationCount"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Empty returns true if there are no target stats
 | 
					
						
							|  |  |  | func (brs *BucketReplicationStats) Empty() bool { | 
					
						
							|  |  |  | 	return len(brs.Stats) == 0 && brs.ReplicaSize == 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Clone creates a new BucketReplicationStats copy
 | 
					
						
							| 
									
										
										
										
											2021-12-18 07:33:13 +08:00
										 |  |  | func (brs BucketReplicationStats) Clone() (c BucketReplicationStats) { | 
					
						
							|  |  |  | 	// This is called only by replicationStats cache and already holds a
 | 
					
						
							|  |  |  | 	// read lock before calling Clone()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c = brs | 
					
						
							|  |  |  | 	// We need to copy the map, so we do not reference the one in `brs`.
 | 
					
						
							|  |  |  | 	c.Stats = make(map[string]*BucketReplicationStat, len(brs.Stats)) | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | 	for arn, st := range brs.Stats { | 
					
						
							| 
									
										
										
										
											2021-12-18 07:33:13 +08:00
										 |  |  | 		// make a copy of `*st`
 | 
					
						
							|  |  |  | 		s := *st | 
					
						
							|  |  |  | 		c.Stats[arn] = &s | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return c | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // BucketReplicationStat represents inline replication statistics
 | 
					
						
							|  |  |  | // such as pending, failed and completed bytes in total for a bucket
 | 
					
						
							|  |  |  | // remote target
 | 
					
						
							|  |  |  | type BucketReplicationStat struct { | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	// Pending size in bytes
 | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | 	PendingSize int64 `json:"pendingReplicationSize"` | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	// Completed size in bytes
 | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | 	ReplicatedSize int64 `json:"completedReplicationSize"` | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	// Total Replica size in bytes
 | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | 	ReplicaSize int64 `json:"replicaSize"` | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	// Failed size in bytes
 | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | 	FailedSize int64 `json:"failedReplicationSize"` | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	// Total number of pending operations including metadata updates
 | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | 	PendingCount int64 `json:"pendingReplicationCount"` | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	// Total number of failed operations including metadata updates
 | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | 	FailedCount int64 `json:"failedReplicationCount"` | 
					
						
							| 
									
										
										
										
											2021-11-18 04:10:57 +08:00
										 |  |  | 	// Replication latency information
 | 
					
						
							|  |  |  | 	Latency ReplicationLatency `json:"replicationLatency"` | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (bs *BucketReplicationStat) hasReplicationUsage() bool { | 
					
						
							|  |  |  | 	return bs.FailedSize > 0 || | 
					
						
							|  |  |  | 		bs.ReplicatedSize > 0 || | 
					
						
							|  |  |  | 		bs.ReplicaSize > 0 || | 
					
						
							|  |  |  | 		bs.FailedCount > 0 || | 
					
						
							|  |  |  | 		bs.PendingCount > 0 || | 
					
						
							|  |  |  | 		bs.PendingSize > 0 | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-09-13 03:40:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (brs BucketReplicationStats) String() string { | 
					
						
							|  |  |  | 	s := "ReplicatedSize=" + fmt.Sprintf("%d", brs.ReplicatedSize) + "+\n ReplicaSize=" + fmt.Sprintf("%d", brs.ReplicaSize) | 
					
						
							|  |  |  | 	for arn, st := range brs.Stats { | 
					
						
							|  |  |  | 		s += "\n arn: " + arn + " ReplicatedSize=" + fmt.Sprintf("%d", st.ReplicatedSize) + "  +::ReplicaSize=" + fmt.Sprintf("%d", st.ReplicaSize) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return s | 
					
						
							|  |  |  | } |