github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/utilities/metrics/registry.go (about)

     1  package metrics
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"strings"
     7  	"sync"
     8  )
     9  
    10  type DuplicateMetric string
    11  
    12  func (err DuplicateMetric) Error() string {
    13  	return fmt.Sprintf("duplicate metric: %s", string(err))
    14  }
    15  
    16  type Registry interface {
    17  	Each(func(string, interface{}))
    18  
    19  	Get(string) interface{}
    20  
    21  	GetAll() map[string]map[string]interface{}
    22  
    23  	GetOrRegister(string, interface{}) interface{}
    24  
    25  	Register(string, interface{}) error
    26  
    27  	RunHealthchecks()
    28  
    29  	Unregister(string)
    30  
    31  	UnregisterAll()
    32  }
    33  
    34  type StandardRegistry struct {
    35  	metrics map[string]interface{}
    36  	mutex   sync.Mutex
    37  }
    38  
    39  func NewRegistry() Registry {
    40  	return &StandardRegistry{metrics: make(map[string]interface{})}
    41  }
    42  
    43  func (r *StandardRegistry) Each(f func(string, interface{})) {
    44  	for name, i := range r.registered() {
    45  		f(name, i)
    46  	}
    47  }
    48  
    49  func (r *StandardRegistry) Get(name string) interface{} {
    50  	r.mutex.Lock()
    51  	defer r.mutex.Unlock()
    52  	return r.metrics[name]
    53  }
    54  
    55  func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} {
    56  	r.mutex.Lock()
    57  	defer r.mutex.Unlock()
    58  	if metric, ok := r.metrics[name]; ok {
    59  		return metric
    60  	}
    61  	if v := reflect.ValueOf(i); v.Kind() == reflect.Func {
    62  		i = v.Call(nil)[0].Interface()
    63  	}
    64  	r.register(name, i)
    65  	return i
    66  }
    67  
    68  func (r *StandardRegistry) Register(name string, i interface{}) error {
    69  	r.mutex.Lock()
    70  	defer r.mutex.Unlock()
    71  	return r.register(name, i)
    72  }
    73  
    74  func (r *StandardRegistry) RunHealthchecks() {
    75  	r.mutex.Lock()
    76  	defer r.mutex.Unlock()
    77  	for _, i := range r.metrics {
    78  		if h, ok := i.(Healthcheck); ok {
    79  			h.Check()
    80  		}
    81  	}
    82  }
    83  
    84  func (r *StandardRegistry) GetAll() map[string]map[string]interface{} {
    85  	data := make(map[string]map[string]interface{})
    86  	r.Each(func(name string, i interface{}) {
    87  		values := make(map[string]interface{})
    88  		switch metric := i.(type) {
    89  		case Counter:
    90  			values["count"] = metric.Count()
    91  		case Gauge:
    92  			values["value"] = metric.Value()
    93  		case GaugeFloat64:
    94  			values["value"] = metric.Value()
    95  		case Healthcheck:
    96  			values["error"] = nil
    97  			metric.Check()
    98  			if err := metric.Error(); nil != err {
    99  				values["error"] = metric.Error().Error()
   100  			}
   101  		case Histogram:
   102  			h := metric.Snapshot()
   103  			ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
   104  			values["count"] = h.Count()
   105  			values["min"] = h.Min()
   106  			values["max"] = h.Max()
   107  			values["mean"] = h.Mean()
   108  			values["stddev"] = h.StdDev()
   109  			values["median"] = ps[0]
   110  			values["75%"] = ps[1]
   111  			values["95%"] = ps[2]
   112  			values["99%"] = ps[3]
   113  			values["99.9%"] = ps[4]
   114  		case Meter:
   115  			m := metric.Snapshot()
   116  			values["count"] = m.Count()
   117  			values["1m.rate"] = m.Rate1()
   118  			values["5m.rate"] = m.Rate5()
   119  			values["15m.rate"] = m.Rate15()
   120  			values["mean.rate"] = m.RateMean()
   121  		case Timer:
   122  			t := metric.Snapshot()
   123  			ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
   124  			values["count"] = t.Count()
   125  			values["min"] = t.Min()
   126  			values["max"] = t.Max()
   127  			values["mean"] = t.Mean()
   128  			values["stddev"] = t.StdDev()
   129  			values["median"] = ps[0]
   130  			values["75%"] = ps[1]
   131  			values["95%"] = ps[2]
   132  			values["99%"] = ps[3]
   133  			values["99.9%"] = ps[4]
   134  			values["1m.rate"] = t.Rate1()
   135  			values["5m.rate"] = t.Rate5()
   136  			values["15m.rate"] = t.Rate15()
   137  			values["mean.rate"] = t.RateMean()
   138  		}
   139  		data[name] = values
   140  	})
   141  	return data
   142  }
   143  
   144  func (r *StandardRegistry) Unregister(name string) {
   145  	r.mutex.Lock()
   146  	defer r.mutex.Unlock()
   147  	r.stop(name)
   148  	delete(r.metrics, name)
   149  }
   150  
   151  func (r *StandardRegistry) UnregisterAll() {
   152  	r.mutex.Lock()
   153  	defer r.mutex.Unlock()
   154  	for name := range r.metrics {
   155  		r.stop(name)
   156  		delete(r.metrics, name)
   157  	}
   158  }
   159  
   160  func (r *StandardRegistry) register(name string, i interface{}) error {
   161  	if _, ok := r.metrics[name]; ok {
   162  		return DuplicateMetric(name)
   163  	}
   164  	switch i.(type) {
   165  	case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer, ResettingTimer:
   166  		r.metrics[name] = i
   167  	}
   168  	return nil
   169  }
   170  
   171  func (r *StandardRegistry) registered() map[string]interface{} {
   172  	r.mutex.Lock()
   173  	defer r.mutex.Unlock()
   174  	metrics := make(map[string]interface{}, len(r.metrics))
   175  	for name, i := range r.metrics {
   176  		metrics[name] = i
   177  	}
   178  	return metrics
   179  }
   180  
   181  func (r *StandardRegistry) stop(name string) {
   182  	if i, ok := r.metrics[name]; ok {
   183  		if s, ok := i.(Stoppable); ok {
   184  			s.Stop()
   185  		}
   186  	}
   187  }
   188  
   189  type Stoppable interface {
   190  	Stop()
   191  }
   192  
   193  type PrefixedRegistry struct {
   194  	underlying Registry
   195  	prefix     string
   196  }
   197  
   198  func NewPrefixedRegistry(prefix string) Registry {
   199  	return &PrefixedRegistry{
   200  		underlying: NewRegistry(),
   201  		prefix:     prefix,
   202  	}
   203  }
   204  
   205  func NewPrefixedChildRegistry(parent Registry, prefix string) Registry {
   206  	return &PrefixedRegistry{
   207  		underlying: parent,
   208  		prefix:     prefix,
   209  	}
   210  }
   211  
   212  func (r *PrefixedRegistry) Each(fn func(string, interface{})) {
   213  	wrappedFn := func(prefix string) func(string, interface{}) {
   214  		return func(name string, iface interface{}) {
   215  			if strings.HasPrefix(name, prefix) {
   216  				fn(name, iface)
   217  			} else {
   218  				return
   219  			}
   220  		}
   221  	}
   222  
   223  	baseRegistry, prefix := findPrefix(r, "")
   224  	baseRegistry.Each(wrappedFn(prefix))
   225  }
   226  
   227  func findPrefix(registry Registry, prefix string) (Registry, string) {
   228  	switch r := registry.(type) {
   229  	case *PrefixedRegistry:
   230  		return findPrefix(r.underlying, r.prefix+prefix)
   231  	case *StandardRegistry:
   232  		return r, prefix
   233  	}
   234  	return nil, ""
   235  }
   236  
   237  func (r *PrefixedRegistry) Get(name string) interface{} {
   238  	realName := r.prefix + name
   239  	return r.underlying.Get(realName)
   240  }
   241  
   242  func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} {
   243  	realName := r.prefix + name
   244  	return r.underlying.GetOrRegister(realName, metric)
   245  }
   246  
   247  func (r *PrefixedRegistry) Register(name string, metric interface{}) error {
   248  	realName := r.prefix + name
   249  	return r.underlying.Register(realName, metric)
   250  }
   251  
   252  func (r *PrefixedRegistry) RunHealthchecks() {
   253  	r.underlying.RunHealthchecks()
   254  }
   255  
   256  func (r *PrefixedRegistry) GetAll() map[string]map[string]interface{} {
   257  	return r.underlying.GetAll()
   258  }
   259  
   260  func (r *PrefixedRegistry) Unregister(name string) {
   261  	realName := r.prefix + name
   262  	r.underlying.Unregister(realName)
   263  }
   264  
   265  func (r *PrefixedRegistry) UnregisterAll() {
   266  	r.underlying.UnregisterAll()
   267  }
   268  
   269  var DefaultRegistry Registry = NewRegistry()
   270  
   271  func Each(f func(string, interface{})) {
   272  	DefaultRegistry.Each(f)
   273  }
   274  
   275  func Get(name string) interface{} {
   276  	return DefaultRegistry.Get(name)
   277  }
   278  
   279  func GetOrRegister(name string, i interface{}) interface{} {
   280  	return DefaultRegistry.GetOrRegister(name, i)
   281  }
   282  
   283  func Register(name string, i interface{}) error {
   284  	return DefaultRegistry.Register(name, i)
   285  }
   286  
   287  func MustRegister(name string, i interface{}) {
   288  	if err := Register(name, i); err != nil {
   289  		panic(err)
   290  	}
   291  }
   292  
   293  func RunHealthchecks() {
   294  	DefaultRegistry.RunHealthchecks()
   295  }
   296  
   297  func Unregister(name string) {
   298  	DefaultRegistry.Unregister(name)
   299  }