registry.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. package metrics
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. "sync"
  7. )
  8. // DuplicateMetric is the error returned by Registry.Register when a metric
  9. // already exists. If you mean to Register that metric you must first
  10. // Unregister the existing metric.
  11. type DuplicateMetric string
  12. func (err DuplicateMetric) Error() string {
  13. return fmt.Sprintf("duplicate metric: %s", string(err))
  14. }
  15. // A Registry holds references to a set of metrics by name and can iterate
  16. // over them, calling callback functions provided by the user.
  17. //
  18. // This is an interface so as to encourage other structs to implement
  19. // the Registry API as appropriate.
  20. type Registry interface {
  21. // Call the given function for each registered metric.
  22. Each(func(string, interface{}))
  23. // Get the metric by the given name or nil if none is registered.
  24. Get(string) interface{}
  25. // GetAll metrics in the Registry.
  26. GetAll() map[string]map[string]interface{}
  27. // Gets an existing metric or registers the given one.
  28. // The interface can be the metric to register if not found in registry,
  29. // or a function returning the metric for lazy instantiation.
  30. GetOrRegister(string, interface{}) interface{}
  31. // Register the given metric under the given name.
  32. Register(string, interface{}) error
  33. // Run all registered healthchecks.
  34. RunHealthchecks()
  35. // Unregister the metric with the given name.
  36. Unregister(string)
  37. // Unregister all metrics. (Mostly for testing.)
  38. UnregisterAll()
  39. }
  40. // The standard implementation of a Registry is a mutex-protected map
  41. // of names to metrics.
  42. type StandardRegistry struct {
  43. metrics map[string]interface{}
  44. mutex sync.RWMutex
  45. }
  46. // Create a new registry.
  47. func NewRegistry() Registry {
  48. return &StandardRegistry{metrics: make(map[string]interface{})}
  49. }
  50. // Call the given function for each registered metric.
  51. func (r *StandardRegistry) Each(f func(string, interface{})) {
  52. metrics := r.registered()
  53. for i := range metrics {
  54. kv := &metrics[i]
  55. f(kv.name, kv.value)
  56. }
  57. }
  58. // Get the metric by the given name or nil if none is registered.
  59. func (r *StandardRegistry) Get(name string) interface{} {
  60. r.mutex.RLock()
  61. defer r.mutex.RUnlock()
  62. return r.metrics[name]
  63. }
  64. // Gets an existing metric or creates and registers a new one. Threadsafe
  65. // alternative to calling Get and Register on failure.
  66. // The interface can be the metric to register if not found in registry,
  67. // or a function returning the metric for lazy instantiation.
  68. func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} {
  69. // access the read lock first which should be re-entrant
  70. r.mutex.RLock()
  71. metric, ok := r.metrics[name]
  72. r.mutex.RUnlock()
  73. if ok {
  74. return metric
  75. }
  76. // only take the write lock if we'll be modifying the metrics map
  77. r.mutex.Lock()
  78. defer r.mutex.Unlock()
  79. if metric, ok := r.metrics[name]; ok {
  80. return metric
  81. }
  82. if v := reflect.ValueOf(i); v.Kind() == reflect.Func {
  83. i = v.Call(nil)[0].Interface()
  84. }
  85. r.register(name, i)
  86. return i
  87. }
  88. // Register the given metric under the given name. Returns a DuplicateMetric
  89. // if a metric by the given name is already registered.
  90. func (r *StandardRegistry) Register(name string, i interface{}) error {
  91. r.mutex.Lock()
  92. defer r.mutex.Unlock()
  93. return r.register(name, i)
  94. }
  95. // Run all registered healthchecks.
  96. func (r *StandardRegistry) RunHealthchecks() {
  97. r.mutex.RLock()
  98. defer r.mutex.RUnlock()
  99. for _, i := range r.metrics {
  100. if h, ok := i.(Healthcheck); ok {
  101. h.Check()
  102. }
  103. }
  104. }
  105. // GetAll metrics in the Registry
  106. func (r *StandardRegistry) GetAll() map[string]map[string]interface{} {
  107. data := make(map[string]map[string]interface{})
  108. r.Each(func(name string, i interface{}) {
  109. values := make(map[string]interface{})
  110. switch metric := i.(type) {
  111. case Counter:
  112. values["count"] = metric.Count()
  113. case Gauge:
  114. values["value"] = metric.Value()
  115. case GaugeFloat64:
  116. values["value"] = metric.Value()
  117. case Healthcheck:
  118. values["error"] = nil
  119. metric.Check()
  120. if err := metric.Error(); nil != err {
  121. values["error"] = metric.Error().Error()
  122. }
  123. case Histogram:
  124. h := metric.Snapshot()
  125. ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
  126. values["count"] = h.Count()
  127. values["min"] = h.Min()
  128. values["max"] = h.Max()
  129. values["mean"] = h.Mean()
  130. values["stddev"] = h.StdDev()
  131. values["median"] = ps[0]
  132. values["75%"] = ps[1]
  133. values["95%"] = ps[2]
  134. values["99%"] = ps[3]
  135. values["99.9%"] = ps[4]
  136. case Meter:
  137. m := metric.Snapshot()
  138. values["count"] = m.Count()
  139. values["1m.rate"] = m.Rate1()
  140. values["5m.rate"] = m.Rate5()
  141. values["15m.rate"] = m.Rate15()
  142. values["mean.rate"] = m.RateMean()
  143. case Timer:
  144. t := metric.Snapshot()
  145. ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
  146. values["count"] = t.Count()
  147. values["min"] = t.Min()
  148. values["max"] = t.Max()
  149. values["mean"] = t.Mean()
  150. values["stddev"] = t.StdDev()
  151. values["median"] = ps[0]
  152. values["75%"] = ps[1]
  153. values["95%"] = ps[2]
  154. values["99%"] = ps[3]
  155. values["99.9%"] = ps[4]
  156. values["1m.rate"] = t.Rate1()
  157. values["5m.rate"] = t.Rate5()
  158. values["15m.rate"] = t.Rate15()
  159. values["mean.rate"] = t.RateMean()
  160. }
  161. data[name] = values
  162. })
  163. return data
  164. }
  165. // Unregister the metric with the given name.
  166. func (r *StandardRegistry) Unregister(name string) {
  167. r.mutex.Lock()
  168. defer r.mutex.Unlock()
  169. r.stop(name)
  170. delete(r.metrics, name)
  171. }
  172. // Unregister all metrics. (Mostly for testing.)
  173. func (r *StandardRegistry) UnregisterAll() {
  174. r.mutex.Lock()
  175. defer r.mutex.Unlock()
  176. for name, _ := range r.metrics {
  177. r.stop(name)
  178. delete(r.metrics, name)
  179. }
  180. }
  181. func (r *StandardRegistry) register(name string, i interface{}) error {
  182. if _, ok := r.metrics[name]; ok {
  183. return DuplicateMetric(name)
  184. }
  185. switch i.(type) {
  186. case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer:
  187. r.metrics[name] = i
  188. }
  189. return nil
  190. }
  191. type metricKV struct {
  192. name string
  193. value interface{}
  194. }
  195. func (r *StandardRegistry) registered() []metricKV {
  196. r.mutex.RLock()
  197. defer r.mutex.RUnlock()
  198. metrics := make([]metricKV, 0, len(r.metrics))
  199. for name, i := range r.metrics {
  200. metrics = append(metrics, metricKV{
  201. name: name,
  202. value: i,
  203. })
  204. }
  205. return metrics
  206. }
  207. func (r *StandardRegistry) stop(name string) {
  208. if i, ok := r.metrics[name]; ok {
  209. if s, ok := i.(Stoppable); ok {
  210. s.Stop()
  211. }
  212. }
  213. }
  214. // Stoppable defines the metrics which has to be stopped.
  215. type Stoppable interface {
  216. Stop()
  217. }
  218. type PrefixedRegistry struct {
  219. underlying Registry
  220. prefix string
  221. }
  222. func NewPrefixedRegistry(prefix string) Registry {
  223. return &PrefixedRegistry{
  224. underlying: NewRegistry(),
  225. prefix: prefix,
  226. }
  227. }
  228. func NewPrefixedChildRegistry(parent Registry, prefix string) Registry {
  229. return &PrefixedRegistry{
  230. underlying: parent,
  231. prefix: prefix,
  232. }
  233. }
  234. // Call the given function for each registered metric.
  235. func (r *PrefixedRegistry) Each(fn func(string, interface{})) {
  236. wrappedFn := func(prefix string) func(string, interface{}) {
  237. return func(name string, iface interface{}) {
  238. if strings.HasPrefix(name, prefix) {
  239. fn(name, iface)
  240. } else {
  241. return
  242. }
  243. }
  244. }
  245. baseRegistry, prefix := findPrefix(r, "")
  246. baseRegistry.Each(wrappedFn(prefix))
  247. }
  248. func findPrefix(registry Registry, prefix string) (Registry, string) {
  249. switch r := registry.(type) {
  250. case *PrefixedRegistry:
  251. return findPrefix(r.underlying, r.prefix+prefix)
  252. case *StandardRegistry:
  253. return r, prefix
  254. }
  255. return nil, ""
  256. }
  257. // Get the metric by the given name or nil if none is registered.
  258. func (r *PrefixedRegistry) Get(name string) interface{} {
  259. realName := r.prefix + name
  260. return r.underlying.Get(realName)
  261. }
  262. // Gets an existing metric or registers the given one.
  263. // The interface can be the metric to register if not found in registry,
  264. // or a function returning the metric for lazy instantiation.
  265. func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} {
  266. realName := r.prefix + name
  267. return r.underlying.GetOrRegister(realName, metric)
  268. }
  269. // Register the given metric under the given name. The name will be prefixed.
  270. func (r *PrefixedRegistry) Register(name string, metric interface{}) error {
  271. realName := r.prefix + name
  272. return r.underlying.Register(realName, metric)
  273. }
  274. // Run all registered healthchecks.
  275. func (r *PrefixedRegistry) RunHealthchecks() {
  276. r.underlying.RunHealthchecks()
  277. }
  278. // GetAll metrics in the Registry
  279. func (r *PrefixedRegistry) GetAll() map[string]map[string]interface{} {
  280. return r.underlying.GetAll()
  281. }
  282. // Unregister the metric with the given name. The name will be prefixed.
  283. func (r *PrefixedRegistry) Unregister(name string) {
  284. realName := r.prefix + name
  285. r.underlying.Unregister(realName)
  286. }
  287. // Unregister all metrics. (Mostly for testing.)
  288. func (r *PrefixedRegistry) UnregisterAll() {
  289. r.underlying.UnregisterAll()
  290. }
  291. var DefaultRegistry Registry = NewRegistry()
  292. // Call the given function for each registered metric.
  293. func Each(f func(string, interface{})) {
  294. DefaultRegistry.Each(f)
  295. }
  296. // Get the metric by the given name or nil if none is registered.
  297. func Get(name string) interface{} {
  298. return DefaultRegistry.Get(name)
  299. }
  300. // Gets an existing metric or creates and registers a new one. Threadsafe
  301. // alternative to calling Get and Register on failure.
  302. func GetOrRegister(name string, i interface{}) interface{} {
  303. return DefaultRegistry.GetOrRegister(name, i)
  304. }
  305. // Register the given metric under the given name. Returns a DuplicateMetric
  306. // if a metric by the given name is already registered.
  307. func Register(name string, i interface{}) error {
  308. return DefaultRegistry.Register(name, i)
  309. }
  310. // Register the given metric under the given name. Panics if a metric by the
  311. // given name is already registered.
  312. func MustRegister(name string, i interface{}) {
  313. if err := Register(name, i); err != nil {
  314. panic(err)
  315. }
  316. }
  317. // Run all registered healthchecks.
  318. func RunHealthchecks() {
  319. DefaultRegistry.RunHealthchecks()
  320. }
  321. // Unregister the metric with the given name.
  322. func Unregister(name string) {
  323. DefaultRegistry.Unregister(name)
  324. }