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 }