registry.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package metrics
  2. import (
  3. "fmt"
  4. "reflect"
  5. "sync"
  6. )
  7. // DuplicateMetric is the error returned by Registry.Register when a metric
  8. // already exists. If you mean to Register that metric you must first
  9. // Unregister the existing metric.
  10. type DuplicateMetric string
  11. func (err DuplicateMetric) Error() string {
  12. return fmt.Sprintf("duplicate metric: %s", string(err))
  13. }
  14. type Registry interface {
  15. // Call the given function for each registered metric.
  16. Each(func(string, interface{}))
  17. // Get the metric by the given name or nil if none is registered.
  18. Get(string) interface{}
  19. // Gets an existing metric or registers the given one.
  20. // The interface can be the metric to register if not found in registry,
  21. // or a function returning the metric for lazy instantiation.
  22. GetOrRegister(string, interface{}) interface{}
  23. // Register the given metric under the given name.
  24. Register(string, interface{}) error
  25. }
  26. // The standard implementation of a Registry is a mutex-protected map
  27. // of names to metrics.
  28. type StandardRegistry struct {
  29. metrics map[string]interface{}
  30. mutex sync.Mutex
  31. }
  32. // Create a new registry.
  33. func NewRegistry() Registry {
  34. return &StandardRegistry{metrics: make(map[string]interface{})}
  35. }
  36. // Call the given function for each registered metric.
  37. func (r *StandardRegistry) Each(f func(string, interface{})) {
  38. for name, i := range r.registered() {
  39. f(name, i)
  40. }
  41. }
  42. // Get the metric by the given name or nil if none is registered.
  43. func (r *StandardRegistry) Get(name string) interface{} {
  44. r.mutex.Lock()
  45. defer r.mutex.Unlock()
  46. return r.metrics[name]
  47. }
  48. // Gets an existing metric or creates and registers a new one. Threadsafe
  49. // alternative to calling Get and Register on failure.
  50. // The interface can be the metric to register if not found in registry,
  51. // or a function returning the metric for lazy instantiation.
  52. func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} {
  53. r.mutex.Lock()
  54. defer r.mutex.Unlock()
  55. if metric, ok := r.metrics[name]; ok {
  56. return metric
  57. }
  58. if v := reflect.ValueOf(i); v.Kind() == reflect.Func {
  59. i = v.Call(nil)[0].Interface()
  60. }
  61. r.register(name, i)
  62. return i
  63. }
  64. // Register the given metric under the given name. Returns a DuplicateMetric
  65. // if a metric by the given name is already registered.
  66. func (r *StandardRegistry) Register(name string, i interface{}) error {
  67. r.mutex.Lock()
  68. defer r.mutex.Unlock()
  69. return r.register(name, i)
  70. }
  71. func (r *StandardRegistry) register(name string, i interface{}) error {
  72. if _, ok := r.metrics[name]; ok {
  73. return DuplicateMetric(name)
  74. }
  75. r.metrics[name] = i
  76. return nil
  77. }
  78. func (r *StandardRegistry) registered() map[string]interface{} {
  79. metrics := make(map[string]interface{}, len(r.metrics))
  80. r.mutex.Lock()
  81. defer r.mutex.Unlock()
  82. for name, i := range r.metrics {
  83. metrics[name] = i
  84. }
  85. return metrics
  86. }