github.com/MetalBlockchain/metalgo@v1.11.9/x/merkledb/metrics.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package merkledb
     5  
     6  import (
     7  	"errors"
     8  	"sync"
     9  
    10  	"github.com/prometheus/client_golang/prometheus"
    11  )
    12  
    13  const (
    14  	ioType    = "type"
    15  	readType  = "read"
    16  	writeType = "write"
    17  
    18  	lookupType                = "type"
    19  	valueNodeCacheType        = "valueNodeCache"
    20  	intermediateNodeCacheType = "intermediateNodeCache"
    21  	viewChangesValueType      = "viewChangesValue"
    22  	viewChangesNodeType       = "viewChangesNode"
    23  
    24  	lookupResult = "result"
    25  	hitResult    = "hit"
    26  	missResult   = "miss"
    27  )
    28  
    29  var (
    30  	_ metrics = (*prometheusMetrics)(nil)
    31  	_ metrics = (*mockMetrics)(nil)
    32  
    33  	ioLabels     = []string{ioType}
    34  	ioReadLabels = prometheus.Labels{
    35  		ioType: readType,
    36  	}
    37  	ioWriteLabels = prometheus.Labels{
    38  		ioType: writeType,
    39  	}
    40  
    41  	lookupLabels            = []string{lookupType, lookupResult}
    42  	valueNodeCacheHitLabels = prometheus.Labels{
    43  		lookupType:   valueNodeCacheType,
    44  		lookupResult: hitResult,
    45  	}
    46  	valueNodeCacheMissLabels = prometheus.Labels{
    47  		lookupType:   valueNodeCacheType,
    48  		lookupResult: missResult,
    49  	}
    50  	intermediateNodeCacheHitLabels = prometheus.Labels{
    51  		lookupType:   intermediateNodeCacheType,
    52  		lookupResult: hitResult,
    53  	}
    54  	intermediateNodeCacheMissLabels = prometheus.Labels{
    55  		lookupType:   intermediateNodeCacheType,
    56  		lookupResult: missResult,
    57  	}
    58  	viewChangesValueHitLabels = prometheus.Labels{
    59  		lookupType:   viewChangesValueType,
    60  		lookupResult: hitResult,
    61  	}
    62  	viewChangesValueMissLabels = prometheus.Labels{
    63  		lookupType:   viewChangesValueType,
    64  		lookupResult: missResult,
    65  	}
    66  	viewChangesNodeHitLabels = prometheus.Labels{
    67  		lookupType:   viewChangesNodeType,
    68  		lookupResult: hitResult,
    69  	}
    70  	viewChangesNodeMissLabels = prometheus.Labels{
    71  		lookupType:   viewChangesNodeType,
    72  		lookupResult: missResult,
    73  	}
    74  )
    75  
    76  type metrics interface {
    77  	HashCalculated()
    78  	DatabaseNodeRead()
    79  	DatabaseNodeWrite()
    80  	ValueNodeCacheHit()
    81  	ValueNodeCacheMiss()
    82  	IntermediateNodeCacheHit()
    83  	IntermediateNodeCacheMiss()
    84  	ViewChangesValueHit()
    85  	ViewChangesValueMiss()
    86  	ViewChangesNodeHit()
    87  	ViewChangesNodeMiss()
    88  }
    89  
    90  type prometheusMetrics struct {
    91  	hashes prometheus.Counter
    92  	io     *prometheus.CounterVec
    93  	lookup *prometheus.CounterVec
    94  }
    95  
    96  func newMetrics(namespace string, reg prometheus.Registerer) (metrics, error) {
    97  	// TODO: Should we instead return an error if reg is nil?
    98  	if reg == nil {
    99  		return &mockMetrics{}, nil
   100  	}
   101  	m := prometheusMetrics{
   102  		hashes: prometheus.NewCounter(prometheus.CounterOpts{
   103  			Namespace: namespace,
   104  			Name:      "hashes",
   105  			Help:      "cumulative number of nodes hashed",
   106  		}),
   107  		io: prometheus.NewCounterVec(prometheus.CounterOpts{
   108  			Namespace: namespace,
   109  			Name:      "io",
   110  			Help:      "cumulative number of operations performed to the db",
   111  		}, ioLabels),
   112  		lookup: prometheus.NewCounterVec(prometheus.CounterOpts{
   113  			Namespace: namespace,
   114  			Name:      "lookup",
   115  			Help:      "cumulative number of in-memory lookups performed",
   116  		}, lookupLabels),
   117  	}
   118  	err := errors.Join(
   119  		reg.Register(m.hashes),
   120  		reg.Register(m.io),
   121  		reg.Register(m.lookup),
   122  	)
   123  	return &m, err
   124  }
   125  
   126  func (m *prometheusMetrics) HashCalculated() {
   127  	m.hashes.Inc()
   128  }
   129  
   130  func (m *prometheusMetrics) DatabaseNodeRead() {
   131  	m.io.With(ioReadLabels).Inc()
   132  }
   133  
   134  func (m *prometheusMetrics) DatabaseNodeWrite() {
   135  	m.io.With(ioWriteLabels).Inc()
   136  }
   137  
   138  func (m *prometheusMetrics) ValueNodeCacheHit() {
   139  	m.lookup.With(valueNodeCacheHitLabels).Inc()
   140  }
   141  
   142  func (m *prometheusMetrics) ValueNodeCacheMiss() {
   143  	m.lookup.With(valueNodeCacheMissLabels).Inc()
   144  }
   145  
   146  func (m *prometheusMetrics) IntermediateNodeCacheHit() {
   147  	m.lookup.With(intermediateNodeCacheHitLabels).Inc()
   148  }
   149  
   150  func (m *prometheusMetrics) IntermediateNodeCacheMiss() {
   151  	m.lookup.With(intermediateNodeCacheMissLabels).Inc()
   152  }
   153  
   154  func (m *prometheusMetrics) ViewChangesValueHit() {
   155  	m.lookup.With(viewChangesValueHitLabels).Inc()
   156  }
   157  
   158  func (m *prometheusMetrics) ViewChangesValueMiss() {
   159  	m.lookup.With(viewChangesValueMissLabels).Inc()
   160  }
   161  
   162  func (m *prometheusMetrics) ViewChangesNodeHit() {
   163  	m.lookup.With(viewChangesNodeHitLabels).Inc()
   164  }
   165  
   166  func (m *prometheusMetrics) ViewChangesNodeMiss() {
   167  	m.lookup.With(viewChangesNodeMissLabels).Inc()
   168  }
   169  
   170  type mockMetrics struct {
   171  	lock                      sync.Mutex
   172  	hashCount                 int64
   173  	nodeReadCount             int64
   174  	nodeWriteCount            int64
   175  	valueNodeCacheHit         int64
   176  	valueNodeCacheMiss        int64
   177  	intermediateNodeCacheHit  int64
   178  	intermediateNodeCacheMiss int64
   179  	viewChangesValueHit       int64
   180  	viewChangesValueMiss      int64
   181  	viewChangesNodeHit        int64
   182  	viewChangesNodeMiss       int64
   183  }
   184  
   185  func (m *mockMetrics) HashCalculated() {
   186  	m.lock.Lock()
   187  	defer m.lock.Unlock()
   188  
   189  	m.hashCount++
   190  }
   191  
   192  func (m *mockMetrics) DatabaseNodeRead() {
   193  	m.lock.Lock()
   194  	defer m.lock.Unlock()
   195  
   196  	m.nodeReadCount++
   197  }
   198  
   199  func (m *mockMetrics) DatabaseNodeWrite() {
   200  	m.lock.Lock()
   201  	defer m.lock.Unlock()
   202  
   203  	m.nodeWriteCount++
   204  }
   205  
   206  func (m *mockMetrics) ValueNodeCacheHit() {
   207  	m.lock.Lock()
   208  	defer m.lock.Unlock()
   209  
   210  	m.valueNodeCacheHit++
   211  }
   212  
   213  func (m *mockMetrics) ValueNodeCacheMiss() {
   214  	m.lock.Lock()
   215  	defer m.lock.Unlock()
   216  
   217  	m.valueNodeCacheMiss++
   218  }
   219  
   220  func (m *mockMetrics) IntermediateNodeCacheHit() {
   221  	m.lock.Lock()
   222  	defer m.lock.Unlock()
   223  
   224  	m.intermediateNodeCacheHit++
   225  }
   226  
   227  func (m *mockMetrics) IntermediateNodeCacheMiss() {
   228  	m.lock.Lock()
   229  	defer m.lock.Unlock()
   230  
   231  	m.intermediateNodeCacheMiss++
   232  }
   233  
   234  func (m *mockMetrics) ViewChangesValueHit() {
   235  	m.lock.Lock()
   236  	defer m.lock.Unlock()
   237  
   238  	m.viewChangesValueHit++
   239  }
   240  
   241  func (m *mockMetrics) ViewChangesValueMiss() {
   242  	m.lock.Lock()
   243  	defer m.lock.Unlock()
   244  
   245  	m.viewChangesValueMiss++
   246  }
   247  
   248  func (m *mockMetrics) ViewChangesNodeHit() {
   249  	m.lock.Lock()
   250  	defer m.lock.Unlock()
   251  
   252  	m.viewChangesNodeHit++
   253  }
   254  
   255  func (m *mockMetrics) ViewChangesNodeMiss() {
   256  	m.lock.Lock()
   257  	defer m.lock.Unlock()
   258  
   259  	m.viewChangesNodeMiss++
   260  }