frostfs-node/pkg/metrics/writecache.go
Dmitrii Stepanov 85deb12f4d [#424] writecache: Drop metrics when close
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-06-14 14:52:40 +03:00

175 lines
4.9 KiB
Go

package metrics
import (
"fmt"
"sync"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-observability/metrics"
"github.com/prometheus/client_golang/prometheus"
)
const (
wcSubsystem = "writecache"
wcShardID = "shard_id"
wcSuccess = "success"
wcStorage = "storage"
wcMode = "mode"
wcMethod = "method"
wcOperation = "operation"
)
type shardIDMode struct {
shardID, mode string
}
type WriteCacheMetrics interface {
AddMethodDuration(shardID string, method string, success bool, d time.Duration, storageType string)
IncActualCount(shardID string, storageType string)
DecActualCount(shardID string, storageType string)
SetActualCount(shardID string, count uint64, storageType string)
SetEstimateSize(shardID string, size uint64, storageType string)
SetMode(shardID string, mode string)
IncOperationCounter(shardID string, operation string, success NullBool, storageType string)
Close(shardID string)
}
type writeCacheMetrics struct {
methodDuration *prometheus.HistogramVec
operationCounter *prometheus.CounterVec
actualCount *prometheus.GaugeVec
estimatedSize *prometheus.GaugeVec
modeMetrics map[shardIDMode]prometheus.GaugeFunc
modeValues map[string]string
modeMtx sync.RWMutex
}
func newWriteCacheMetrics() *writeCacheMetrics {
return &writeCacheMetrics{
methodDuration: metrics.NewHistogramVec(prometheus.HistogramOpts{
Namespace: namespace,
Subsystem: wcSubsystem,
Name: "request_duration_seconds",
Help: "Writecache request process duration",
}, []string{wcShardID, wcSuccess, wcStorage, wcMethod}),
operationCounter: metrics.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Subsystem: wcSubsystem,
Name: "operation_count",
Help: "The number of writecache operations processed",
}, []string{wcShardID, wcStorage, wcSuccess, wcOperation}),
actualCount: newWCGaugeVec("actual_objects_count", "Actual objects count in writecache", []string{wcShardID, wcStorage}),
estimatedSize: newWCGaugeVec("estimated_size_bytes", "Estimated writecache size", []string{wcShardID, wcStorage}),
modeMtx: sync.RWMutex{},
modeMetrics: make(map[shardIDMode]prometheus.GaugeFunc),
modeValues: make(map[string]string),
}
}
func (m *writeCacheMetrics) AddMethodDuration(shardID string, method string, success bool, d time.Duration, storageType string) {
m.methodDuration.With(
prometheus.Labels{
wcShardID: shardID,
wcSuccess: fmt.Sprintf("%v", success),
wcStorage: storageType,
wcMethod: method,
},
).Observe(d.Seconds())
}
func (m *writeCacheMetrics) IncActualCount(shardID string, storageType string) {
m.actualCount.With(prometheus.Labels{
wcShardID: shardID,
wcStorage: storageType,
}).Inc()
}
func (m *writeCacheMetrics) DecActualCount(shardID string, storageType string) {
m.actualCount.With(prometheus.Labels{
wcShardID: shardID,
wcStorage: storageType,
}).Dec()
}
func (m *writeCacheMetrics) SetActualCount(shardID string, count uint64, storageType string) {
m.actualCount.With(prometheus.Labels{
wcShardID: shardID,
wcStorage: storageType,
}).Set(float64(count))
}
func (m *writeCacheMetrics) SetEstimateSize(shardID string, size uint64, storageType string) {
m.estimatedSize.With(prometheus.Labels{
wcShardID: shardID,
wcStorage: storageType,
}).Set(float64(size))
}
func (m *writeCacheMetrics) SetMode(shardID string, mode string) {
m.modeMtx.Lock()
defer m.modeMtx.Unlock()
m.modeValues[shardID] = mode
key := shardIDMode{
shardID: shardID,
mode: mode,
}
if _, found := m.modeMetrics[key]; found {
return
}
metric := metrics.NewGaugeFunc(
prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: wcSubsystem,
Name: "writecache_mode",
Help: "Writecache mode value",
ConstLabels: prometheus.Labels{
wcShardID: shardID,
wcMode: mode,
},
}, func() float64 {
m.modeMtx.RLock()
defer m.modeMtx.RUnlock()
value := m.modeValues[shardID]
if value == mode {
return 1
}
return 0
})
m.modeMetrics[key] = metric
}
func (m *writeCacheMetrics) IncOperationCounter(shardID string, operation string, success NullBool, storageType string) {
m.operationCounter.With(prometheus.Labels{
wcShardID: shardID,
wcStorage: storageType,
wcOperation: operation,
wcSuccess: success.String(),
}).Inc()
}
func (m *writeCacheMetrics) Close(shardID string) {
m.SetMode(shardID, "CLOSED")
m.methodDuration.DeletePartialMatch(prometheus.Labels{wcShardID: shardID})
m.operationCounter.DeletePartialMatch(prometheus.Labels{wcShardID: shardID})
m.actualCount.DeletePartialMatch(prometheus.Labels{wcShardID: shardID})
m.estimatedSize.DeletePartialMatch(prometheus.Labels{wcShardID: shardID})
}
func newWCGaugeVec(name, help string, labels []string) *prometheus.GaugeVec {
return metrics.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: wcSubsystem,
Name: name,
Help: help,
}, labels)
}