registry.go 9.4 KB

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