gitlab.com/aquachain/aquachain@v1.17.16-rc3.0.20221018032414-e3ddf1e1c055/common/metrics/registry.go (about) 1 // Copyright 2018 The aquachain Authors 2 // This file is part of the aquachain library. 3 // 4 // The aquachain library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The aquachain library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the aquachain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package metrics 18 19 import ( 20 "fmt" 21 "reflect" 22 "strings" 23 "sync" 24 ) 25 26 // DuplicateMetric is the error returned by Registry.Register when a metric 27 // already exists. If you mean to Register that metric you must first 28 // Unregister the existing metric. 29 type DuplicateMetric string 30 31 func (err DuplicateMetric) Error() string { 32 return fmt.Sprintf("duplicate metric: %s", string(err)) 33 } 34 35 // A Registry holds references to a set of metrics by name and can iterate 36 // over them, calling callback functions provided by the user. 37 // 38 // This is an interface so as to encourage other structs to implement 39 // the Registry API as appropriate. 40 type Registry interface { 41 42 // Call the given function for each registered metric. 43 Each(func(string, interface{})) 44 45 // Get the metric by the given name or nil if none is registered. 46 Get(string) interface{} 47 48 // GetAll metrics in the Registry. 49 GetAll() map[string]map[string]interface{} 50 51 // Gets an existing metric or registers the given one. 52 // The interface can be the metric to register if not found in registry, 53 // or a function returning the metric for lazy instantiation. 54 GetOrRegister(string, interface{}) interface{} 55 56 // Register the given metric under the given name. 57 Register(string, interface{}) error 58 59 // Run all registered healthchecks. 60 RunHealthchecks() 61 62 // Unregister the metric with the given name. 63 Unregister(string) 64 65 // Unregister all metrics. (Mostly for testing.) 66 UnregisterAll() 67 } 68 69 // The standard implementation of a Registry is a mutex-protected map 70 // of names to metrics. 71 type StandardRegistry struct { 72 metrics map[string]interface{} 73 mutex sync.Mutex 74 } 75 76 // Create a new registry. 77 func NewRegistry() Registry { 78 return &StandardRegistry{metrics: make(map[string]interface{})} 79 } 80 81 // Call the given function for each registered metric. 82 func (r *StandardRegistry) Each(f func(string, interface{})) { 83 for name, i := range r.registered() { 84 f(name, i) 85 } 86 } 87 88 // Get the metric by the given name or nil if none is registered. 89 func (r *StandardRegistry) Get(name string) interface{} { 90 r.mutex.Lock() 91 defer r.mutex.Unlock() 92 return r.metrics[name] 93 } 94 95 // Gets an existing metric or creates and registers a new one. Threadsafe 96 // alternative to calling Get and Register on failure. 97 // The interface can be the metric to register if not found in registry, 98 // or a function returning the metric for lazy instantiation. 99 func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} { 100 r.mutex.Lock() 101 defer r.mutex.Unlock() 102 if metric, ok := r.metrics[name]; ok { 103 return metric 104 } 105 if v := reflect.ValueOf(i); v.Kind() == reflect.Func { 106 i = v.Call(nil)[0].Interface() 107 } 108 r.register(name, i) 109 return i 110 } 111 112 // Register the given metric under the given name. Returns a DuplicateMetric 113 // if a metric by the given name is already registered. 114 func (r *StandardRegistry) Register(name string, i interface{}) error { 115 r.mutex.Lock() 116 defer r.mutex.Unlock() 117 return r.register(name, i) 118 } 119 120 // Run all registered healthchecks. 121 func (r *StandardRegistry) RunHealthchecks() { 122 r.mutex.Lock() 123 defer r.mutex.Unlock() 124 for _, i := range r.metrics { 125 if h, ok := i.(Healthcheck); ok { 126 h.Check() 127 } 128 } 129 } 130 131 // GetAll metrics in the Registry 132 func (r *StandardRegistry) GetAll() map[string]map[string]interface{} { 133 data := make(map[string]map[string]interface{}) 134 r.Each(func(name string, i interface{}) { 135 values := make(map[string]interface{}) 136 switch metric := i.(type) { 137 case Counter: 138 values["count"] = metric.Count() 139 case Gauge: 140 values["value"] = metric.Value() 141 case GaugeFloat64: 142 values["value"] = metric.Value() 143 case Healthcheck: 144 values["error"] = nil 145 metric.Check() 146 if err := metric.Error(); nil != err { 147 values["error"] = metric.Error().Error() 148 } 149 case Histogram: 150 h := metric.Snapshot() 151 ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) 152 values["count"] = h.Count() 153 values["min"] = h.Min() 154 values["max"] = h.Max() 155 values["mean"] = h.Mean() 156 values["stddev"] = h.StdDev() 157 values["median"] = ps[0] 158 values["75%"] = ps[1] 159 values["95%"] = ps[2] 160 values["99%"] = ps[3] 161 values["99.9%"] = ps[4] 162 case Meter: 163 m := metric.Snapshot() 164 values["count"] = m.Count() 165 values["1m.rate"] = m.Rate1() 166 values["5m.rate"] = m.Rate5() 167 values["15m.rate"] = m.Rate15() 168 values["mean.rate"] = m.RateMean() 169 case Timer: 170 t := metric.Snapshot() 171 ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) 172 values["count"] = t.Count() 173 values["min"] = t.Min() 174 values["max"] = t.Max() 175 values["mean"] = t.Mean() 176 values["stddev"] = t.StdDev() 177 values["median"] = ps[0] 178 values["75%"] = ps[1] 179 values["95%"] = ps[2] 180 values["99%"] = ps[3] 181 values["99.9%"] = ps[4] 182 values["1m.rate"] = t.Rate1() 183 values["5m.rate"] = t.Rate5() 184 values["15m.rate"] = t.Rate15() 185 values["mean.rate"] = t.RateMean() 186 } 187 data[name] = values 188 }) 189 return data 190 } 191 192 // Unregister the metric with the given name. 193 func (r *StandardRegistry) Unregister(name string) { 194 r.mutex.Lock() 195 defer r.mutex.Unlock() 196 r.stop(name) 197 delete(r.metrics, name) 198 } 199 200 // Unregister all metrics. (Mostly for testing.) 201 func (r *StandardRegistry) UnregisterAll() { 202 r.mutex.Lock() 203 defer r.mutex.Unlock() 204 for name := range r.metrics { 205 r.stop(name) 206 delete(r.metrics, name) 207 } 208 } 209 210 func (r *StandardRegistry) register(name string, i interface{}) error { 211 if _, ok := r.metrics[name]; ok { 212 return DuplicateMetric(name) 213 } 214 switch i.(type) { 215 case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer, ResettingTimer: 216 r.metrics[name] = i 217 } 218 return nil 219 } 220 221 func (r *StandardRegistry) registered() map[string]interface{} { 222 r.mutex.Lock() 223 defer r.mutex.Unlock() 224 metrics := make(map[string]interface{}, len(r.metrics)) 225 for name, i := range r.metrics { 226 metrics[name] = i 227 } 228 return metrics 229 } 230 231 func (r *StandardRegistry) stop(name string) { 232 if i, ok := r.metrics[name]; ok { 233 if s, ok := i.(Stoppable); ok { 234 s.Stop() 235 } 236 } 237 } 238 239 // Stoppable defines the metrics which has to be stopped. 240 type Stoppable interface { 241 Stop() 242 } 243 244 type PrefixedRegistry struct { 245 underlying Registry 246 prefix string 247 } 248 249 func NewPrefixedRegistry(prefix string) Registry { 250 return &PrefixedRegistry{ 251 underlying: NewRegistry(), 252 prefix: prefix, 253 } 254 } 255 256 func NewPrefixedChildRegistry(parent Registry, prefix string) Registry { 257 return &PrefixedRegistry{ 258 underlying: parent, 259 prefix: prefix, 260 } 261 } 262 263 // Call the given function for each registered metric. 264 func (r *PrefixedRegistry) Each(fn func(string, interface{})) { 265 wrappedFn := func(prefix string) func(string, interface{}) { 266 return func(name string, iface interface{}) { 267 if strings.HasPrefix(name, prefix) { 268 fn(name, iface) 269 } else { 270 return 271 } 272 } 273 } 274 275 baseRegistry, prefix := findPrefix(r, "") 276 baseRegistry.Each(wrappedFn(prefix)) 277 } 278 279 func findPrefix(registry Registry, prefix string) (Registry, string) { 280 switch r := registry.(type) { 281 case *PrefixedRegistry: 282 return findPrefix(r.underlying, r.prefix+prefix) 283 case *StandardRegistry: 284 return r, prefix 285 } 286 return nil, "" 287 } 288 289 // Get the metric by the given name or nil if none is registered. 290 func (r *PrefixedRegistry) Get(name string) interface{} { 291 realName := r.prefix + name 292 return r.underlying.Get(realName) 293 } 294 295 // Gets an existing metric or registers the given one. 296 // The interface can be the metric to register if not found in registry, 297 // or a function returning the metric for lazy instantiation. 298 func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} { 299 realName := r.prefix + name 300 return r.underlying.GetOrRegister(realName, metric) 301 } 302 303 // Register the given metric under the given name. The name will be prefixed. 304 func (r *PrefixedRegistry) Register(name string, metric interface{}) error { 305 realName := r.prefix + name 306 return r.underlying.Register(realName, metric) 307 } 308 309 // Run all registered healthchecks. 310 func (r *PrefixedRegistry) RunHealthchecks() { 311 r.underlying.RunHealthchecks() 312 } 313 314 // GetAll metrics in the Registry 315 func (r *PrefixedRegistry) GetAll() map[string]map[string]interface{} { 316 return r.underlying.GetAll() 317 } 318 319 // Unregister the metric with the given name. The name will be prefixed. 320 func (r *PrefixedRegistry) Unregister(name string) { 321 realName := r.prefix + name 322 r.underlying.Unregister(realName) 323 } 324 325 // Unregister all metrics. (Mostly for testing.) 326 func (r *PrefixedRegistry) UnregisterAll() { 327 r.underlying.UnregisterAll() 328 } 329 330 var DefaultRegistry Registry = NewRegistry() 331 332 // Call the given function for each registered metric. 333 func Each(f func(string, interface{})) { 334 DefaultRegistry.Each(f) 335 } 336 337 // Get the metric by the given name or nil if none is registered. 338 func Get(name string) interface{} { 339 return DefaultRegistry.Get(name) 340 } 341 342 // Gets an existing metric or creates and registers a new one. Threadsafe 343 // alternative to calling Get and Register on failure. 344 func GetOrRegister(name string, i interface{}) interface{} { 345 return DefaultRegistry.GetOrRegister(name, i) 346 } 347 348 // Register the given metric under the given name. Returns a DuplicateMetric 349 // if a metric by the given name is already registered. 350 func Register(name string, i interface{}) error { 351 return DefaultRegistry.Register(name, i) 352 } 353 354 // Register the given metric under the given name. Panics if a metric by the 355 // given name is already registered. 356 func MustRegister(name string, i interface{}) { 357 if err := Register(name, i); err != nil { 358 panic(err) 359 } 360 } 361 362 // Run all registered healthchecks. 363 func RunHealthchecks() { 364 DefaultRegistry.RunHealthchecks() 365 } 366 367 // Unregister the metric with the given name. 368 func Unregister(name string) { 369 DefaultRegistry.Unregister(name) 370 }