github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/rcrowley/go-metrics/registry.go (about)

     1  package metrics
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"sync"
     7  )
     8  
     9  // DuplicateMetric is the error returned by Registry.Register when a metric
    10  // already exists.  If you mean to Register that metric you must first
    11  // Unregister the existing metric.
    12  type DuplicateMetric string
    13  
    14  func (err DuplicateMetric) Error() string {
    15  	return fmt.Sprintf("duplicate metric: %s", string(err))
    16  }
    17  
    18  // A Registry holds references to a set of metrics by name and can iterate
    19  // over them, calling callback functions provided by the user.
    20  //
    21  // This is an interface so as to encourage other structs to implement
    22  // the Registry API as appropriate.
    23  type Registry interface {
    24  
    25  	// Call the given function for each registered metric.
    26  	Each(func(string, interface{}))
    27  
    28  	// Get the metric by the given name or nil if none is registered.
    29  	Get(string) interface{}
    30  
    31  	// Gets an existing metric or registers the given one.
    32  	// The interface can be the metric to register if not found in registry,
    33  	// or a function returning the metric for lazy instantiation.
    34  	GetOrRegister(string, interface{}) interface{}
    35  
    36  	// Register the given metric under the given name.
    37  	Register(string, interface{}) error
    38  
    39  	// Run all registered healthchecks.
    40  	RunHealthchecks()
    41  
    42  	// Unregister the metric with the given name.
    43  	Unregister(string)
    44  
    45  	// Unregister all metrics.  (Mostly for testing.)
    46  	UnregisterAll()
    47  }
    48  
    49  // The standard implementation of a Registry is a mutex-protected map
    50  // of names to metrics.
    51  type StandardRegistry struct {
    52  	metrics map[string]interface{}
    53  	mutex   sync.Mutex
    54  }
    55  
    56  // Create a new registry.
    57  func NewRegistry() Registry {
    58  	return &StandardRegistry{metrics: make(map[string]interface{})}
    59  }
    60  
    61  // Call the given function for each registered metric.
    62  func (r *StandardRegistry) Each(f func(string, interface{})) {
    63  	for name, i := range r.registered() {
    64  		f(name, i)
    65  	}
    66  }
    67  
    68  // Get the metric by the given name or nil if none is registered.
    69  func (r *StandardRegistry) Get(name string) interface{} {
    70  	r.mutex.Lock()
    71  	defer r.mutex.Unlock()
    72  	return r.metrics[name]
    73  }
    74  
    75  // Gets an existing metric or creates and registers a new one. Threadsafe
    76  // alternative to calling Get and Register on failure.
    77  // The interface can be the metric to register if not found in registry,
    78  // or a function returning the metric for lazy instantiation.
    79  func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} {
    80  	r.mutex.Lock()
    81  	defer r.mutex.Unlock()
    82  	if metric, ok := r.metrics[name]; ok {
    83  		return metric
    84  	}
    85  	if v := reflect.ValueOf(i); v.Kind() == reflect.Func {
    86  		i = v.Call(nil)[0].Interface()
    87  	}
    88  	r.register(name, i)
    89  	return i
    90  }
    91  
    92  // Register the given metric under the given name.  Returns a DuplicateMetric
    93  // if a metric by the given name is already registered.
    94  func (r *StandardRegistry) Register(name string, i interface{}) error {
    95  	r.mutex.Lock()
    96  	defer r.mutex.Unlock()
    97  	return r.register(name, i)
    98  }
    99  
   100  // Run all registered healthchecks.
   101  func (r *StandardRegistry) RunHealthchecks() {
   102  	r.mutex.Lock()
   103  	defer r.mutex.Unlock()
   104  	for _, i := range r.metrics {
   105  		if h, ok := i.(Healthcheck); ok {
   106  			h.Check()
   107  		}
   108  	}
   109  }
   110  
   111  // Unregister the metric with the given name.
   112  func (r *StandardRegistry) Unregister(name string) {
   113  	r.mutex.Lock()
   114  	defer r.mutex.Unlock()
   115  	delete(r.metrics, name)
   116  }
   117  
   118  // Unregister all metrics.  (Mostly for testing.)
   119  func (r *StandardRegistry) UnregisterAll() {
   120  	r.mutex.Lock()
   121  	defer r.mutex.Unlock()
   122  	for name, _ := range r.metrics {
   123  		delete(r.metrics, name)
   124  	}
   125  }
   126  
   127  func (r *StandardRegistry) register(name string, i interface{}) error {
   128  	if _, ok := r.metrics[name]; ok {
   129  		return DuplicateMetric(name)
   130  	}
   131  	switch i.(type) {
   132  	case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer:
   133  		r.metrics[name] = i
   134  	}
   135  	return nil
   136  }
   137  
   138  func (r *StandardRegistry) registered() map[string]interface{} {
   139  	r.mutex.Lock()
   140  	defer r.mutex.Unlock()
   141  	metrics := make(map[string]interface{}, len(r.metrics))
   142  	for name, i := range r.metrics {
   143  		metrics[name] = i
   144  	}
   145  	return metrics
   146  }
   147  
   148  type PrefixedRegistry struct {
   149  	underlying Registry
   150  	prefix     string
   151  }
   152  
   153  func NewPrefixedRegistry(prefix string) Registry {
   154  	return &PrefixedRegistry{
   155  		underlying: NewRegistry(),
   156  		prefix:     prefix,
   157  	}
   158  }
   159  
   160  func NewPrefixedChildRegistry(parent Registry, prefix string) Registry {
   161  	return &PrefixedRegistry{
   162  		underlying: parent,
   163  		prefix:     prefix,
   164  	}
   165  }
   166  
   167  // Call the given function for each registered metric.
   168  func (r *PrefixedRegistry) Each(fn func(string, interface{})) {
   169  	r.underlying.Each(fn)
   170  }
   171  
   172  // Get the metric by the given name or nil if none is registered.
   173  func (r *PrefixedRegistry) Get(name string) interface{} {
   174  	return r.underlying.Get(name)
   175  }
   176  
   177  // Gets an existing metric or registers the given one.
   178  // The interface can be the metric to register if not found in registry,
   179  // or a function returning the metric for lazy instantiation.
   180  func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} {
   181  	realName := r.prefix + name
   182  	return r.underlying.GetOrRegister(realName, metric)
   183  }
   184  
   185  // Register the given metric under the given name. The name will be prefixed.
   186  func (r *PrefixedRegistry) Register(name string, metric interface{}) error {
   187  	realName := r.prefix + name
   188  	return r.underlying.Register(realName, metric)
   189  }
   190  
   191  // Run all registered healthchecks.
   192  func (r *PrefixedRegistry) RunHealthchecks() {
   193  	r.underlying.RunHealthchecks()
   194  }
   195  
   196  // Unregister the metric with the given name. The name will be prefixed.
   197  func (r *PrefixedRegistry) Unregister(name string) {
   198  	realName := r.prefix + name
   199  	r.underlying.Unregister(realName)
   200  }
   201  
   202  // Unregister all metrics.  (Mostly for testing.)
   203  func (r *PrefixedRegistry) UnregisterAll() {
   204  	r.underlying.UnregisterAll()
   205  }
   206  
   207  var DefaultRegistry Registry = NewRegistry()
   208  
   209  // Call the given function for each registered metric.
   210  func Each(f func(string, interface{})) {
   211  	DefaultRegistry.Each(f)
   212  }
   213  
   214  // Get the metric by the given name or nil if none is registered.
   215  func Get(name string) interface{} {
   216  	return DefaultRegistry.Get(name)
   217  }
   218  
   219  // Gets an existing metric or creates and registers a new one. Threadsafe
   220  // alternative to calling Get and Register on failure.
   221  func GetOrRegister(name string, i interface{}) interface{} {
   222  	return DefaultRegistry.GetOrRegister(name, i)
   223  }
   224  
   225  // Register the given metric under the given name.  Returns a DuplicateMetric
   226  // if a metric by the given name is already registered.
   227  func Register(name string, i interface{}) error {
   228  	return DefaultRegistry.Register(name, i)
   229  }
   230  
   231  // Register the given metric under the given name.  Panics if a metric by the
   232  // given name is already registered.
   233  func MustRegister(name string, i interface{}) {
   234  	if err := Register(name, i); err != nil {
   235  		panic(err)
   236  	}
   237  }
   238  
   239  // Run all registered healthchecks.
   240  func RunHealthchecks() {
   241  	DefaultRegistry.RunHealthchecks()
   242  }
   243  
   244  // Unregister the metric with the given name.
   245  func Unregister(name string) {
   246  	DefaultRegistry.Unregister(name)
   247  }