github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/kv/metrics.go (about)

     1  package kv
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/prometheus/client_golang/prometheus"
     7  	"github.com/prometheus/client_golang/prometheus/promauto"
     8  )
     9  
    10  var (
    11  	requestDuration = promauto.NewHistogramVec(
    12  		prometheus.HistogramOpts{
    13  			Name:    "kv_request_duration_seconds",
    14  			Help:    "request durations for the kv Store",
    15  			Buckets: []float64{0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10},
    16  		},
    17  		[]string{"type", "operation"})
    18  
    19  	requestFailures = promauto.NewCounterVec(prometheus.CounterOpts{
    20  		Name: "kv_request_failures_total",
    21  		Help: "The total number of errors while working for kv store.",
    22  	}, []string{"type", "operation"})
    23  )
    24  
    25  // StoreMetricsWrapper wraps any Store with metrics
    26  type StoreMetricsWrapper struct {
    27  	Store
    28  	StoreType string
    29  }
    30  
    31  func (s *StoreMetricsWrapper) Get(ctx context.Context, partitionKey, key []byte) (*ValueWithPredicate, error) {
    32  	const operation = "Get"
    33  	timer := prometheus.NewTimer(requestDuration.WithLabelValues(s.StoreType, operation))
    34  	defer timer.ObserveDuration()
    35  	res, err := s.Store.Get(ctx, partitionKey, key)
    36  	if err != nil {
    37  		requestFailures.WithLabelValues(s.StoreType, operation).Inc()
    38  	}
    39  	return res, err
    40  }
    41  
    42  func (s *StoreMetricsWrapper) Set(ctx context.Context, partitionKey, key, value []byte) error {
    43  	const operation = "Set"
    44  	timer := prometheus.NewTimer(requestDuration.WithLabelValues(s.StoreType, operation))
    45  	defer timer.ObserveDuration()
    46  	err := s.Store.Set(ctx, partitionKey, key, value)
    47  	if err != nil {
    48  		requestFailures.WithLabelValues(s.StoreType, operation).Inc()
    49  	}
    50  	return err
    51  }
    52  
    53  func (s *StoreMetricsWrapper) SetIf(ctx context.Context, partitionKey, key, value []byte, valuePredicate Predicate) error {
    54  	const operation = "SetIf"
    55  	timer := prometheus.NewTimer(requestDuration.WithLabelValues(s.StoreType, operation))
    56  	defer timer.ObserveDuration()
    57  	err := s.Store.SetIf(ctx, partitionKey, key, value, valuePredicate)
    58  	if err != nil {
    59  		requestFailures.WithLabelValues(s.StoreType, operation).Inc()
    60  	}
    61  	return err
    62  }
    63  
    64  func (s *StoreMetricsWrapper) Delete(ctx context.Context, partitionKey, key []byte) error {
    65  	const operation = "Delete"
    66  	timer := prometheus.NewTimer(requestDuration.WithLabelValues(s.StoreType, operation))
    67  	defer timer.ObserveDuration()
    68  	err := s.Store.Delete(ctx, partitionKey, key)
    69  	if err != nil {
    70  		requestFailures.WithLabelValues(s.StoreType, operation).Inc()
    71  	}
    72  	return err
    73  }
    74  
    75  func (s *StoreMetricsWrapper) Scan(ctx context.Context, partitionKey []byte, options ScanOptions) (EntriesIterator, error) {
    76  	const operation = "Scan"
    77  	timer := prometheus.NewTimer(requestDuration.WithLabelValues(s.StoreType, operation))
    78  	defer timer.ObserveDuration()
    79  	res, err := s.Store.Scan(ctx, partitionKey, options)
    80  	if err != nil {
    81  		requestFailures.WithLabelValues(s.StoreType, operation).Inc()
    82  	}
    83  	return res, err
    84  }
    85  
    86  func (s *StoreMetricsWrapper) Close() {
    87  	timer := prometheus.NewTimer(requestDuration.WithLabelValues(s.StoreType, "Close"))
    88  	defer timer.ObserveDuration()
    89  	s.Store.Close()
    90  }
    91  
    92  func storeMetrics(store Store, storeType string) *StoreMetricsWrapper {
    93  	return &StoreMetricsWrapper{Store: store, StoreType: storeType}
    94  }