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  }