github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/lsmkv/metrics.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  package lsmkv
    13  
    14  import (
    15  	"time"
    16  
    17  	"github.com/prometheus/client_golang/prometheus"
    18  	"github.com/weaviate/weaviate/usecases/monitoring"
    19  )
    20  
    21  type (
    22  	NsObserver   func(ns int64)
    23  	Setter       func(val uint64)
    24  	TimeObserver func(start time.Time)
    25  )
    26  
    27  type Metrics struct {
    28  	CompactionReplace    *prometheus.GaugeVec
    29  	CompactionSet        *prometheus.GaugeVec
    30  	CompactionMap        *prometheus.GaugeVec
    31  	CompactionRoaringSet *prometheus.GaugeVec
    32  	ActiveSegments       *prometheus.GaugeVec
    33  	bloomFilters         prometheus.ObserverVec
    34  	SegmentObjects       *prometheus.GaugeVec
    35  	SegmentSize          *prometheus.GaugeVec
    36  	SegmentCount         *prometheus.GaugeVec
    37  	startupDurations     prometheus.ObserverVec
    38  	startupDiskIO        prometheus.ObserverVec
    39  	objectCount          prometheus.Gauge
    40  	memtableDurations    prometheus.ObserverVec
    41  	memtableSize         *prometheus.GaugeVec
    42  	DimensionSum         *prometheus.GaugeVec
    43  
    44  	groupClasses bool
    45  }
    46  
    47  func NewMetrics(promMetrics *monitoring.PrometheusMetrics, className,
    48  	shardName string,
    49  ) *Metrics {
    50  	if promMetrics.Group {
    51  		className = "n/a"
    52  		shardName = "n/a"
    53  	}
    54  
    55  	replace := promMetrics.AsyncOperations.MustCurryWith(prometheus.Labels{
    56  		"operation":  "compact_lsm_segments_stratreplace",
    57  		"class_name": className,
    58  		"shard_name": shardName,
    59  	})
    60  
    61  	set := promMetrics.AsyncOperations.MustCurryWith(prometheus.Labels{
    62  		"operation":  "compact_lsm_segments_stratset",
    63  		"class_name": className,
    64  		"shard_name": shardName,
    65  	})
    66  
    67  	roaringSet := promMetrics.AsyncOperations.MustCurryWith(prometheus.Labels{
    68  		"operation":  "compact_lsm_segments_stratroaringset",
    69  		"class_name": className,
    70  		"shard_name": shardName,
    71  	})
    72  
    73  	stratMap := promMetrics.AsyncOperations.MustCurryWith(prometheus.Labels{
    74  		"operation":  "compact_lsm_segments_stratmap",
    75  		"class_name": className,
    76  		"shard_name": shardName,
    77  	})
    78  
    79  	return &Metrics{
    80  		groupClasses:         promMetrics.Group,
    81  		CompactionReplace:    replace,
    82  		CompactionSet:        set,
    83  		CompactionMap:        stratMap,
    84  		CompactionRoaringSet: roaringSet,
    85  		ActiveSegments: promMetrics.LSMSegmentCount.MustCurryWith(prometheus.Labels{
    86  			"class_name": className,
    87  			"shard_name": shardName,
    88  		}),
    89  		bloomFilters: promMetrics.LSMBloomFilters.MustCurryWith(prometheus.Labels{
    90  			"class_name": className,
    91  			"shard_name": shardName,
    92  		}),
    93  		SegmentObjects: promMetrics.LSMSegmentObjects.MustCurryWith(prometheus.Labels{
    94  			"class_name": className,
    95  			"shard_name": shardName,
    96  		}),
    97  		SegmentSize: promMetrics.LSMSegmentSize.MustCurryWith(prometheus.Labels{
    98  			"class_name": className,
    99  			"shard_name": shardName,
   100  		}),
   101  		SegmentCount: promMetrics.LSMSegmentCountByLevel.MustCurryWith(prometheus.Labels{
   102  			"class_name": className,
   103  			"shard_name": shardName,
   104  		}),
   105  		startupDiskIO: promMetrics.StartupDiskIO.MustCurryWith(prometheus.Labels{
   106  			"class_name": className,
   107  			"shard_name": shardName,
   108  		}),
   109  		startupDurations: promMetrics.StartupDurations.MustCurryWith(prometheus.Labels{
   110  			"class_name": className,
   111  			"shard_name": shardName,
   112  		}),
   113  		objectCount: promMetrics.ObjectCount.With(prometheus.Labels{
   114  			"class_name": className,
   115  			"shard_name": shardName,
   116  		}),
   117  		memtableDurations: promMetrics.LSMMemtableDurations.MustCurryWith(prometheus.Labels{
   118  			"class_name": className,
   119  			"shard_name": shardName,
   120  		}),
   121  		memtableSize: promMetrics.LSMMemtableSize.MustCurryWith(prometheus.Labels{
   122  			"class_name": className,
   123  			"shard_name": shardName,
   124  		}),
   125  		DimensionSum: promMetrics.VectorDimensionsSum.MustCurryWith(prometheus.Labels{
   126  			"class_name": className,
   127  			"shard_name": shardName,
   128  		}),
   129  	}
   130  }
   131  
   132  func noOpTimeObserver(start time.Time) {
   133  	// do nothing
   134  }
   135  
   136  func noOpNsObserver(startNs int64) {
   137  	// do nothing
   138  }
   139  
   140  func noOpSetter(val uint64) {
   141  	// do nothing
   142  }
   143  
   144  func (m *Metrics) MemtableOpObserver(path, strategy, op string) NsObserver {
   145  	if m == nil {
   146  		return noOpNsObserver
   147  	}
   148  
   149  	if m.groupClasses {
   150  		path = "n/a"
   151  	}
   152  
   153  	curried := m.memtableDurations.With(prometheus.Labels{
   154  		"operation": op,
   155  		"path":      path,
   156  		"strategy":  strategy,
   157  	})
   158  
   159  	return func(startNs int64) {
   160  		took := float64(time.Now().UnixNano()-startNs) / float64(time.Millisecond)
   161  		curried.Observe(took)
   162  	}
   163  }
   164  
   165  func (m *Metrics) MemtableSizeSetter(path, strategy string) Setter {
   166  	if m == nil || m.groupClasses {
   167  		// this metric would set absolute values, that's not possible in
   168  		// grouped mode, each call would essentially overwrite the last
   169  		return noOpSetter
   170  	}
   171  
   172  	curried := m.memtableSize.With(prometheus.Labels{
   173  		"path":     path,
   174  		"strategy": strategy,
   175  	})
   176  
   177  	return func(size uint64) {
   178  		curried.Set(float64(size))
   179  	}
   180  }
   181  
   182  func (m *Metrics) BloomFilterObserver(strategy, operation string) TimeObserver {
   183  	if m == nil {
   184  		return noOpTimeObserver
   185  	}
   186  
   187  	curried := m.bloomFilters.With(prometheus.Labels{
   188  		"strategy":  strategy,
   189  		"operation": operation,
   190  	})
   191  
   192  	return func(before time.Time) {
   193  		curried.Observe(float64(time.Since(before)) / float64(time.Millisecond))
   194  	}
   195  }
   196  
   197  func (m *Metrics) TrackStartupReadWALDiskIO(read int64, nanoseconds int64) {
   198  	if m == nil {
   199  		return
   200  	}
   201  
   202  	seconds := float64(nanoseconds) / float64(time.Second)
   203  	throughput := float64(read) / float64(seconds)
   204  	m.startupDiskIO.With(prometheus.Labels{"operation": "lsm_recover_wal"}).Observe(throughput)
   205  }
   206  
   207  func (m *Metrics) TrackStartupBucket(start time.Time) {
   208  	if m == nil {
   209  		return
   210  	}
   211  
   212  	took := float64(time.Since(start)) / float64(time.Millisecond)
   213  	m.startupDurations.With(prometheus.Labels{"operation": "lsm_startup_bucket"}).Observe(took)
   214  }
   215  
   216  func (m *Metrics) TrackStartupBucketRecovery(start time.Time) {
   217  	if m == nil {
   218  		return
   219  	}
   220  
   221  	took := float64(time.Since(start)) / float64(time.Millisecond)
   222  	m.startupDurations.With(prometheus.Labels{"operation": "lsm_startup_bucket_recovery"}).Observe(took)
   223  }
   224  
   225  func (m *Metrics) ObjectCount(count int) {
   226  	if m == nil {
   227  		return
   228  	}
   229  
   230  	m.objectCount.Set(float64(count))
   231  }