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 }