mirror of https://github.com/minio/minio.git
				
				
				
			
		
			
	
	
		
			146 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
		
		
			
		
	
	
			146 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
|  | // Copyright (c) 2015-2024 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 ( | ||
|  | 	"time" | ||
|  | 
 | ||
|  | 	"github.com/minio/madmin-go/v3" | ||
|  | 	"github.com/minio/minio/internal/cachevalue" | ||
|  | ) | ||
|  | 
 | ||
|  | // metricsCache - cache for metrics.
 | ||
|  | //
 | ||
|  | // When serving metrics, this cache is passed to the MetricsLoaderFn.
 | ||
|  | //
 | ||
|  | // This cache is used for metrics that would result in network/storage calls.
 | ||
|  | type metricsCache struct { | ||
|  | 	dataUsageInfo       *cachevalue.Cache[DataUsageInfo] | ||
|  | 	esetHealthResult    *cachevalue.Cache[HealthResult] | ||
|  | 	driveMetrics        *cachevalue.Cache[storageMetrics] | ||
|  | 	clusterDriveMetrics *cachevalue.Cache[storageMetrics] | ||
|  | 	nodesUpDown         *cachevalue.Cache[nodesOnline] | ||
|  | } | ||
|  | 
 | ||
|  | func newMetricsCache() *metricsCache { | ||
|  | 	return &metricsCache{ | ||
|  | 		dataUsageInfo:       newDataUsageInfoCache(), | ||
|  | 		esetHealthResult:    newESetHealthResultCache(), | ||
|  | 		driveMetrics:        newDriveMetricsCache(), | ||
|  | 		clusterDriveMetrics: newClusterStorageInfoCache(), | ||
|  | 		nodesUpDown:         newNodesUpDownCache(), | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | type nodesOnline struct { | ||
|  | 	Online, Offline int | ||
|  | } | ||
|  | 
 | ||
|  | func newNodesUpDownCache() *cachevalue.Cache[nodesOnline] { | ||
|  | 	loadNodesUpDown := func() (v nodesOnline, err error) { | ||
|  | 		v.Online, v.Offline = globalNotificationSys.GetPeerOnlineCount() | ||
|  | 		return | ||
|  | 	} | ||
|  | 	return cachevalue.NewFromFunc(1*time.Minute, | ||
|  | 		cachevalue.Opts{ReturnLastGood: true}, | ||
|  | 		loadNodesUpDown) | ||
|  | } | ||
|  | 
 | ||
|  | type storageMetrics struct { | ||
|  | 	storageInfo                              madmin.StorageInfo | ||
|  | 	onlineDrives, offlineDrives, totalDrives int | ||
|  | } | ||
|  | 
 | ||
|  | func newDataUsageInfoCache() *cachevalue.Cache[DataUsageInfo] { | ||
|  | 	loadDataUsage := func() (u DataUsageInfo, err error) { | ||
|  | 		objLayer := newObjectLayerFn() | ||
|  | 		if objLayer == nil { | ||
|  | 			return | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Collect cluster level object metrics.
 | ||
|  | 		u, err = loadDataUsageFromBackend(GlobalContext, objLayer) | ||
|  | 		return | ||
|  | 	} | ||
|  | 	return cachevalue.NewFromFunc(1*time.Minute, | ||
|  | 		cachevalue.Opts{ReturnLastGood: true}, | ||
|  | 		loadDataUsage) | ||
|  | } | ||
|  | 
 | ||
|  | func newESetHealthResultCache() *cachevalue.Cache[HealthResult] { | ||
|  | 	loadHealth := func() (r HealthResult, err error) { | ||
|  | 		objLayer := newObjectLayerFn() | ||
|  | 		if objLayer == nil { | ||
|  | 			return | ||
|  | 		} | ||
|  | 
 | ||
|  | 		r = objLayer.Health(GlobalContext, HealthOptions{}) | ||
|  | 		return | ||
|  | 	} | ||
|  | 	return cachevalue.NewFromFunc(1*time.Minute, | ||
|  | 		cachevalue.Opts{ReturnLastGood: true}, | ||
|  | 		loadHealth, | ||
|  | 	) | ||
|  | } | ||
|  | 
 | ||
|  | func newDriveMetricsCache() *cachevalue.Cache[storageMetrics] { | ||
|  | 	loadDriveMetrics := func() (v storageMetrics, err error) { | ||
|  | 		objLayer := newObjectLayerFn() | ||
|  | 		if objLayer == nil { | ||
|  | 			return | ||
|  | 		} | ||
|  | 
 | ||
|  | 		storageInfo := objLayer.LocalStorageInfo(GlobalContext, true) | ||
|  | 		onlineDrives, offlineDrives := getOnlineOfflineDisksStats(storageInfo.Disks) | ||
|  | 		totalDrives := onlineDrives.Merge(offlineDrives) | ||
|  | 		v = storageMetrics{ | ||
|  | 			storageInfo:   storageInfo, | ||
|  | 			onlineDrives:  onlineDrives.Sum(), | ||
|  | 			offlineDrives: offlineDrives.Sum(), | ||
|  | 			totalDrives:   totalDrives.Sum(), | ||
|  | 		} | ||
|  | 		return | ||
|  | 	} | ||
|  | 	return cachevalue.NewFromFunc(1*time.Minute, | ||
|  | 		cachevalue.Opts{ReturnLastGood: true}, | ||
|  | 		loadDriveMetrics) | ||
|  | } | ||
|  | 
 | ||
|  | func newClusterStorageInfoCache() *cachevalue.Cache[storageMetrics] { | ||
|  | 	loadStorageInfo := func() (v storageMetrics, err error) { | ||
|  | 		objLayer := newObjectLayerFn() | ||
|  | 		if objLayer == nil { | ||
|  | 			return storageMetrics{}, nil | ||
|  | 		} | ||
|  | 		storageInfo := objLayer.StorageInfo(GlobalContext, true) | ||
|  | 		onlineDrives, offlineDrives := getOnlineOfflineDisksStats(storageInfo.Disks) | ||
|  | 		totalDrives := onlineDrives.Merge(offlineDrives) | ||
|  | 		v = storageMetrics{ | ||
|  | 			storageInfo:   storageInfo, | ||
|  | 			onlineDrives:  onlineDrives.Sum(), | ||
|  | 			offlineDrives: offlineDrives.Sum(), | ||
|  | 			totalDrives:   totalDrives.Sum(), | ||
|  | 		} | ||
|  | 		return | ||
|  | 	} | ||
|  | 	return cachevalue.NewFromFunc(1*time.Minute, | ||
|  | 		cachevalue.Opts{ReturnLastGood: true}, | ||
|  | 		loadStorageInfo, | ||
|  | 	) | ||
|  | } |