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,
|
||
|
)
|
||
|
}
|