collectors.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /*
  2. Copyright 2019 The Vitess Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package prometheusbackend
  14. import (
  15. "strings"
  16. "github.com/prometheus/client_golang/prometheus"
  17. "git.nspix.com/golang/micro/stats"
  18. )
  19. type metricFuncCollector struct {
  20. // f returns the floating point value of the metric.
  21. f func() float64
  22. desc *prometheus.Desc
  23. vt prometheus.ValueType
  24. }
  25. func newMetricFuncCollector(v stats.Variable, name string, vt prometheus.ValueType, f func() float64) {
  26. collector := &metricFuncCollector{
  27. f: f,
  28. desc: prometheus.NewDesc(
  29. name,
  30. v.Help(),
  31. nil,
  32. nil),
  33. vt: vt}
  34. // Will panic if it fails
  35. prometheus.MustRegister(collector)
  36. }
  37. // Describe implements Collector.
  38. func (mc *metricFuncCollector) Describe(ch chan<- *prometheus.Desc) {
  39. ch <- mc.desc
  40. }
  41. // Collect implements Collector.
  42. func (mc *metricFuncCollector) Collect(ch chan<- prometheus.Metric) {
  43. metric, err := prometheus.NewConstMetric(mc.desc, mc.vt, float64(mc.f()))
  44. if err == nil {
  45. ch <- metric
  46. }
  47. }
  48. // countersWithSingleLabelCollector collects stats.CountersWithSingleLabel.
  49. type countersWithSingleLabelCollector struct {
  50. counters *stats.CountersWithSingleLabel
  51. desc *prometheus.Desc
  52. vt prometheus.ValueType
  53. }
  54. func newCountersWithSingleLabelCollector(c *stats.CountersWithSingleLabel, name string, labelName string, vt prometheus.ValueType) {
  55. collector := &countersWithSingleLabelCollector{
  56. counters: c,
  57. desc: prometheus.NewDesc(
  58. name,
  59. c.Help(),
  60. []string{labelName},
  61. nil),
  62. vt: vt}
  63. prometheus.MustRegister(collector)
  64. }
  65. // Describe implements Collector.
  66. func (c *countersWithSingleLabelCollector) Describe(ch chan<- *prometheus.Desc) {
  67. ch <- c.desc
  68. }
  69. // Collect implements Collector.
  70. func (c *countersWithSingleLabelCollector) Collect(ch chan<- prometheus.Metric) {
  71. for tag, val := range c.counters.Counts() {
  72. metric, err := prometheus.NewConstMetric(c.desc, c.vt, float64(val), tag)
  73. if err == nil {
  74. ch <- metric
  75. }
  76. }
  77. }
  78. // gaugesWithSingleLabelCollector collects stats.GaugesWithSingleLabel.
  79. type gaugesWithSingleLabelCollector struct {
  80. gauges *stats.GaugesWithSingleLabel
  81. desc *prometheus.Desc
  82. vt prometheus.ValueType
  83. }
  84. func newGaugesWithSingleLabelCollector(g *stats.GaugesWithSingleLabel, name string, labelName string, vt prometheus.ValueType) {
  85. collector := &gaugesWithSingleLabelCollector{
  86. gauges: g,
  87. desc: prometheus.NewDesc(
  88. name,
  89. g.Help(),
  90. []string{labelName},
  91. nil),
  92. vt: vt}
  93. prometheus.MustRegister(collector)
  94. }
  95. // Describe implements Collector.
  96. func (g *gaugesWithSingleLabelCollector) Describe(ch chan<- *prometheus.Desc) {
  97. ch <- g.desc
  98. }
  99. // Collect implements Collector.
  100. func (g *gaugesWithSingleLabelCollector) Collect(ch chan<- prometheus.Metric) {
  101. for tag, val := range g.gauges.Counts() {
  102. metric, err := prometheus.NewConstMetric(g.desc, g.vt, float64(val), tag)
  103. if err == nil {
  104. ch <- metric
  105. }
  106. }
  107. }
  108. type metricWithMultiLabelsCollector struct {
  109. cml *stats.CountersWithMultiLabels
  110. desc *prometheus.Desc
  111. }
  112. func newMetricWithMultiLabelsCollector(cml *stats.CountersWithMultiLabels, name string) {
  113. c := &metricWithMultiLabelsCollector{
  114. cml: cml,
  115. desc: prometheus.NewDesc(
  116. name,
  117. cml.Help(),
  118. labelsToSnake(cml.Labels()),
  119. nil),
  120. }
  121. prometheus.MustRegister(c)
  122. }
  123. // Describe implements Collector.
  124. func (c *metricWithMultiLabelsCollector) Describe(ch chan<- *prometheus.Desc) {
  125. ch <- c.desc
  126. }
  127. // Collect implements Collector.
  128. func (c *metricWithMultiLabelsCollector) Collect(ch chan<- prometheus.Metric) {
  129. for lvs, val := range c.cml.Counts() {
  130. labelValues := strings.Split(lvs, ".")
  131. value := float64(val)
  132. metric, err := prometheus.NewConstMetric(c.desc, prometheus.CounterValue, value, labelValues...)
  133. if err == nil {
  134. ch <- metric
  135. }
  136. }
  137. }
  138. type gaugesWithMultiLabelsCollector struct {
  139. gml *stats.GaugesWithMultiLabels
  140. desc *prometheus.Desc
  141. }
  142. func newGaugesWithMultiLabelsCollector(gml *stats.GaugesWithMultiLabels, name string) {
  143. c := &gaugesWithMultiLabelsCollector{
  144. gml: gml,
  145. desc: prometheus.NewDesc(
  146. name,
  147. gml.Help(),
  148. labelsToSnake(gml.Labels()),
  149. nil),
  150. }
  151. prometheus.MustRegister(c)
  152. }
  153. // Describe implements Collector.
  154. func (c *gaugesWithMultiLabelsCollector) Describe(ch chan<- *prometheus.Desc) {
  155. ch <- c.desc
  156. }
  157. // Collect implements Collector.
  158. func (c *gaugesWithMultiLabelsCollector) Collect(ch chan<- prometheus.Metric) {
  159. for lvs, val := range c.gml.Counts() {
  160. labelValues := strings.Split(lvs, ".")
  161. value := float64(val)
  162. metric, err := prometheus.NewConstMetric(c.desc, prometheus.GaugeValue, value, labelValues...)
  163. if err == nil {
  164. ch <- metric
  165. }
  166. }
  167. }
  168. type metricsFuncWithMultiLabelsCollector struct {
  169. cfml *stats.CountersFuncWithMultiLabels
  170. desc *prometheus.Desc
  171. vt prometheus.ValueType
  172. }
  173. func newMetricsFuncWithMultiLabelsCollector(cfml *stats.CountersFuncWithMultiLabels, name string, vt prometheus.ValueType) {
  174. collector := &metricsFuncWithMultiLabelsCollector{
  175. cfml: cfml,
  176. desc: prometheus.NewDesc(
  177. name,
  178. cfml.Help(),
  179. labelsToSnake(cfml.Labels()),
  180. nil),
  181. vt: vt,
  182. }
  183. prometheus.MustRegister(collector)
  184. }
  185. // Describe implements Collector.
  186. func (c *metricsFuncWithMultiLabelsCollector) Describe(ch chan<- *prometheus.Desc) {
  187. ch <- c.desc
  188. }
  189. // Collect implements Collector.
  190. func (c *metricsFuncWithMultiLabelsCollector) Collect(ch chan<- prometheus.Metric) {
  191. for lvs, val := range c.cfml.Counts() {
  192. labelValues := strings.Split(lvs, ".")
  193. value := float64(val)
  194. metric, err := prometheus.NewConstMetric(c.desc, c.vt, value, labelValues...)
  195. if err == nil {
  196. ch <- metric
  197. }
  198. }
  199. }
  200. type timingsCollector struct {
  201. t *stats.Timings
  202. cutoffs []float64
  203. desc *prometheus.Desc
  204. }
  205. func newTimingsCollector(t *stats.Timings, name string) {
  206. cutoffs := make([]float64, len(t.Cutoffs()))
  207. for i, val := range t.Cutoffs() {
  208. cutoffs[i] = float64(val) / 1000000000
  209. }
  210. collector := &timingsCollector{
  211. t: t,
  212. cutoffs: cutoffs,
  213. desc: prometheus.NewDesc(
  214. name,
  215. t.Help(),
  216. []string{t.Label()},
  217. nil),
  218. }
  219. prometheus.MustRegister(collector)
  220. }
  221. // Describe implements Collector.
  222. func (c *timingsCollector) Describe(ch chan<- *prometheus.Desc) {
  223. ch <- c.desc
  224. }
  225. // Collect implements Collector.
  226. func (c *timingsCollector) Collect(ch chan<- prometheus.Metric) {
  227. for cat, his := range c.t.Histograms() {
  228. metric, err := prometheus.NewConstHistogram(c.desc,
  229. uint64(his.Count()),
  230. float64(his.Total())/1000000000,
  231. makeCumulativeBuckets(c.cutoffs,
  232. his.Buckets()), cat)
  233. if err == nil {
  234. ch <- metric
  235. }
  236. }
  237. }
  238. func makeCumulativeBuckets(cutoffs []float64, buckets []int64) map[float64]uint64 {
  239. output := make(map[float64]uint64)
  240. last := uint64(0)
  241. for i, key := range cutoffs {
  242. //TODO(zmagg): int64 => uint64 conversion. error if it overflows?
  243. output[key] = uint64(buckets[i]) + last
  244. last = output[key]
  245. }
  246. return output
  247. }
  248. type multiTimingsCollector struct {
  249. mt *stats.MultiTimings
  250. cutoffs []float64
  251. desc *prometheus.Desc
  252. }
  253. func newMultiTimingsCollector(mt *stats.MultiTimings, name string) {
  254. cutoffs := make([]float64, len(mt.Cutoffs()))
  255. for i, val := range mt.Cutoffs() {
  256. cutoffs[i] = float64(val) / 1000000000
  257. }
  258. collector := &multiTimingsCollector{
  259. mt: mt,
  260. cutoffs: cutoffs,
  261. desc: prometheus.NewDesc(
  262. name,
  263. mt.Help(),
  264. labelsToSnake(mt.Labels()),
  265. nil),
  266. }
  267. prometheus.MustRegister(collector)
  268. }
  269. // Describe implements Collector.
  270. func (c *multiTimingsCollector) Describe(ch chan<- *prometheus.Desc) {
  271. ch <- c.desc
  272. }
  273. // Collect implements Collector.
  274. func (c *multiTimingsCollector) Collect(ch chan<- prometheus.Metric) {
  275. for cat, his := range c.mt.Timings.Histograms() {
  276. labelValues := strings.Split(cat, ".")
  277. metric, err := prometheus.NewConstHistogram(
  278. c.desc,
  279. uint64(his.Count()),
  280. float64(his.Total())/1000000000,
  281. makeCumulativeBuckets(c.cutoffs, his.Buckets()),
  282. labelValues...)
  283. if err == nil {
  284. ch <- metric
  285. }
  286. }
  287. }
  288. type histogramCollector struct {
  289. h *stats.Histogram
  290. cutoffs []float64
  291. desc *prometheus.Desc
  292. }
  293. func newHistogramCollector(h *stats.Histogram, name string) {
  294. cutoffs := make([]float64, len(h.Cutoffs()))
  295. for i, val := range h.Cutoffs() {
  296. cutoffs[i] = float64(val)
  297. }
  298. collector := &histogramCollector{
  299. h: h,
  300. cutoffs: cutoffs,
  301. desc: prometheus.NewDesc(
  302. name,
  303. h.Help(),
  304. []string{},
  305. nil),
  306. }
  307. prometheus.MustRegister(collector)
  308. }
  309. // Describe implements Collector.
  310. func (c *histogramCollector) Describe(ch chan<- *prometheus.Desc) {
  311. ch <- c.desc
  312. }
  313. // Collect implements Collector.
  314. func (c *histogramCollector) Collect(ch chan<- prometheus.Metric) {
  315. metric, err := prometheus.NewConstHistogram(c.desc,
  316. uint64(c.h.Count()),
  317. float64(c.h.Total()),
  318. makeCumulativeBuckets(c.cutoffs, c.h.Buckets()))
  319. if err == nil {
  320. ch <- metric
  321. }
  322. }