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