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