registry.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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. delete(r.metrics, name)
  160. }
  161. // Unregister all metrics. (Mostly for testing.)
  162. func (r *StandardRegistry) UnregisterAll() {
  163. r.mutex.Lock()
  164. defer r.mutex.Unlock()
  165. for name, _ := range r.metrics {
  166. delete(r.metrics, name)
  167. }
  168. }
  169. func (r *StandardRegistry) register(name string, i interface{}) error {
  170. if _, ok := r.metrics[name]; ok {
  171. return DuplicateMetric(name)
  172. }
  173. switch i.(type) {
  174. case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer:
  175. r.metrics[name] = i
  176. }
  177. return nil
  178. }
  179. func (r *StandardRegistry) registered() map[string]interface{} {
  180. r.mutex.Lock()
  181. defer r.mutex.Unlock()
  182. metrics := make(map[string]interface{}, len(r.metrics))
  183. for name, i := range r.metrics {
  184. metrics[name] = i
  185. }
  186. return metrics
  187. }
  188. type PrefixedRegistry struct {
  189. underlying Registry
  190. prefix string
  191. }
  192. func NewPrefixedRegistry(prefix string) Registry {
  193. return &PrefixedRegistry{
  194. underlying: NewRegistry(),
  195. prefix: prefix,
  196. }
  197. }
  198. func NewPrefixedChildRegistry(parent Registry, prefix string) Registry {
  199. return &PrefixedRegistry{
  200. underlying: parent,
  201. prefix: prefix,
  202. }
  203. }
  204. // Call the given function for each registered metric.
  205. func (r *PrefixedRegistry) Each(fn func(string, interface{})) {
  206. wrappedFn := func(prefix string) func(string, interface{}) {
  207. return func(name string, iface interface{}) {
  208. if strings.HasPrefix(name, prefix) {
  209. fn(name, iface)
  210. } else {
  211. return
  212. }
  213. }
  214. }
  215. baseRegistry, prefix := findPrefix(r, "")
  216. baseRegistry.Each(wrappedFn(prefix))
  217. }
  218. func findPrefix(registry Registry, prefix string) (Registry, string) {
  219. switch r := registry.(type) {
  220. case *PrefixedRegistry:
  221. return findPrefix(r.underlying, r.prefix+prefix)
  222. case *StandardRegistry:
  223. return r, prefix
  224. }
  225. return nil, ""
  226. }
  227. // Get the metric by the given name or nil if none is registered.
  228. func (r *PrefixedRegistry) Get(name string) interface{} {
  229. realName := r.prefix + name
  230. return r.underlying.Get(realName)
  231. }
  232. // Gets an existing metric or registers the given one.
  233. // The interface can be the metric to register if not found in registry,
  234. // or a function returning the metric for lazy instantiation.
  235. func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} {
  236. realName := r.prefix + name
  237. return r.underlying.GetOrRegister(realName, metric)
  238. }
  239. // Register the given metric under the given name. The name will be prefixed.
  240. func (r *PrefixedRegistry) Register(name string, metric interface{}) error {
  241. realName := r.prefix + name
  242. return r.underlying.Register(realName, metric)
  243. }
  244. // Run all registered healthchecks.
  245. func (r *PrefixedRegistry) RunHealthchecks() {
  246. r.underlying.RunHealthchecks()
  247. }
  248. // GetAll metrics in the Registry
  249. func (r *PrefixedRegistry) GetAll() map[string]map[string]interface{} {
  250. return r.underlying.GetAll()
  251. }
  252. // Unregister the metric with the given name. The name will be prefixed.
  253. func (r *PrefixedRegistry) Unregister(name string) {
  254. realName := r.prefix + name
  255. r.underlying.Unregister(realName)
  256. }
  257. // Unregister all metrics. (Mostly for testing.)
  258. func (r *PrefixedRegistry) UnregisterAll() {
  259. r.underlying.UnregisterAll()
  260. }
  261. var DefaultRegistry Registry = NewRegistry()
  262. // Call the given function for each registered metric.
  263. func Each(f func(string, interface{})) {
  264. DefaultRegistry.Each(f)
  265. }
  266. // Get the metric by the given name or nil if none is registered.
  267. func Get(name string) interface{} {
  268. return DefaultRegistry.Get(name)
  269. }
  270. // Gets an existing metric or creates and registers a new one. Threadsafe
  271. // alternative to calling Get and Register on failure.
  272. func GetOrRegister(name string, i interface{}) interface{} {
  273. return DefaultRegistry.GetOrRegister(name, i)
  274. }
  275. // Register the given metric under the given name. Returns a DuplicateMetric
  276. // if a metric by the given name is already registered.
  277. func Register(name string, i interface{}) error {
  278. return DefaultRegistry.Register(name, i)
  279. }
  280. // Register the given metric under the given name. Panics if a metric by the
  281. // given name is already registered.
  282. func MustRegister(name string, i interface{}) {
  283. if err := Register(name, i); err != nil {
  284. panic(err)
  285. }
  286. }
  287. // Run all registered healthchecks.
  288. func RunHealthchecks() {
  289. DefaultRegistry.RunHealthchecks()
  290. }
  291. // Unregister the metric with the given name.
  292. func Unregister(name string) {
  293. DefaultRegistry.Unregister(name)
  294. }