registry.go 9.7 KB

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