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  }