@@ -13,7 +13,6 @@ import (
1313 "google.golang.org/api/monitoring/v3"
1414
1515 "github.com/frodenas/stackdriver_exporter/utils"
16- "sort"
1716)
1817
1918type MonitoringCollector struct {
@@ -28,6 +27,7 @@ type MonitoringCollector struct {
2827 lastScrapeErrorMetric prometheus.Gauge
2928 lastScrapeTimestampMetric prometheus.Gauge
3029 lastScrapeDurationSecondsMetric prometheus.Gauge
30+ collectorFillMissingLabels bool
3131}
3232
3333func NewMonitoringCollector (
@@ -36,6 +36,7 @@ func NewMonitoringCollector(
3636 metricsInterval time.Duration ,
3737 metricsOffset time.Duration ,
3838 monitoringService * monitoring.Service ,
39+ collectorFillMissingLabels bool ,
3940) (* MonitoringCollector , error ) {
4041 apiCallsTotalMetric := prometheus .NewCounter (
4142 prometheus.CounterOpts {
@@ -109,6 +110,7 @@ func NewMonitoringCollector(
109110 lastScrapeErrorMetric : lastScrapeErrorMetric ,
110111 lastScrapeTimestampMetric : lastScrapeTimestampMetric ,
111112 lastScrapeDurationSecondsMetric : lastScrapeDurationSecondsMetric ,
113+ collectorFillMissingLabels : collectorFillMissingLabels ,
112114 }
113115
114116 return monitoringCollector , nil
@@ -236,7 +238,7 @@ func (c *MonitoringCollector) reportTimeSeriesMetrics(
236238 timeSeriesMetrics := & TimeSeriesMetrics {
237239 metricDescriptor : metricDescriptor ,
238240 ch : ch ,
239- fillMissingLabels : true , //TODO: this can be configurable
241+ fillMissingLabels : c . collectorFillMissingLabels ,
240242 constMetrics : make (map [string ][]ConstMetric ),
241243 histogramMetrics : make (map [string ][]HistogramMetric ),
242244 }
@@ -362,234 +364,3 @@ func (c *MonitoringCollector) generateHistogramBuckets(
362364 }
363365 return buckets , nil
364366}
365-
366- func buildFQName (timeSeries * monitoring.TimeSeries ) string {
367- // The metric name to report is composed by the 3 parts:
368- // 1. namespace is a constant prefix (stackdriver)
369- // 2. subsystem is the monitored resource type (ie gce_instance)
370- // 3. name is the metric type (ie compute.googleapis.com/instance/cpu/usage_time)
371- return prometheus .BuildFQName ("stackdriver" , utils .NormalizeMetricName (timeSeries .Resource .Type ), utils .NormalizeMetricName (timeSeries .Metric .Type ))
372- }
373-
374- type TimeSeriesMetrics struct {
375- metricDescriptor * monitoring.MetricDescriptor
376- ch chan <- prometheus.Metric
377-
378- fillMissingLabels bool
379- constMetrics map [string ][]ConstMetric
380- histogramMetrics map [string ][]HistogramMetric
381- }
382-
383- func (t * TimeSeriesMetrics ) NewMetricDesc (fqName string , labelKeys []string ) * prometheus.Desc {
384- return prometheus .NewDesc (
385- fqName ,
386- t .metricDescriptor .Description ,
387- labelKeys ,
388- prometheus.Labels {},
389- )
390- }
391-
392- type ConstMetric struct {
393- fqName string
394- labelKeys []string
395- valueType prometheus.ValueType
396- value float64
397- labelValues []string
398-
399- keysHash uint64
400- }
401-
402- type HistogramMetric struct {
403- fqName string
404- labelKeys []string
405- dist * monitoring.Distribution
406- buckets map [float64 ]uint64
407- labelValues []string
408-
409- keysHash uint64
410- }
411-
412- func (t * TimeSeriesMetrics ) CollectNewConstHistogram (timeSeries * monitoring.TimeSeries , labelKeys []string , dist * monitoring.Distribution , buckets map [float64 ]uint64 , labelValues []string ) {
413- fqName := buildFQName (timeSeries )
414-
415- if t .fillMissingLabels {
416- vs , ok := t .histogramMetrics [fqName ]
417- if ! ok {
418- vs = make ([]HistogramMetric , 0 )
419- }
420- v := HistogramMetric {
421- fqName : fqName ,
422- labelKeys : labelKeys ,
423- dist : dist ,
424- buckets : buckets ,
425- labelValues : labelValues ,
426-
427- keysHash : hashLabelKeys (labelKeys ),
428- }
429- t .histogramMetrics [fqName ] = append (vs , v )
430- return
431- }
432-
433- metric := prometheus .MustNewConstHistogram (
434- t .NewMetricDesc (fqName , labelKeys ),
435- uint64 (dist .Count ),
436- dist .Mean * float64 (dist .Count ), // Stackdriver does not provide the sum, but we can fake it
437- buckets ,
438- labelValues ... ,
439- )
440- t .ch <- metric
441- }
442-
443- func (t * TimeSeriesMetrics ) CollectNewConstMetric (timeSeries * monitoring.TimeSeries , labelKeys []string , metricValueType prometheus.ValueType , metricValue float64 , labelValues []string ) {
444- fqName := buildFQName (timeSeries )
445-
446- if t .fillMissingLabels {
447- vs , ok := t .constMetrics [fqName ]
448- if ! ok {
449- vs = make ([]ConstMetric , 0 )
450- }
451- v := ConstMetric {
452- fqName : fqName ,
453- labelKeys : labelKeys ,
454- valueType : metricValueType ,
455- value : metricValue ,
456- labelValues : labelValues ,
457-
458- keysHash : hashLabelKeys (labelKeys ),
459- }
460- t .constMetrics [fqName ] = append (vs , v )
461- return
462- }
463-
464- metric := prometheus .MustNewConstMetric (
465- t .NewMetricDesc (fqName , labelKeys ),
466- metricValueType ,
467- metricValue ,
468- labelValues ... ,
469- )
470- t .ch <- metric
471- }
472-
473- func hashLabelKeys (labelKeys []string ) uint64 {
474- dh := hashNew ()
475- sortedKeys := make ([]string , len (labelKeys ))
476- copy (sortedKeys , labelKeys )
477- sort .Strings (sortedKeys )
478- for _ , key := range sortedKeys {
479- dh = hashAdd (dh , key )
480- dh = hashAddByte (dh , separatorByte )
481- }
482- return dh
483- }
484-
485- func (t * TimeSeriesMetrics ) Complete () {
486- t .CompleteConstMetrics ()
487- t .CompleteHistogramMetrics ()
488- }
489-
490- func (t * TimeSeriesMetrics ) CompleteConstMetrics () {
491- for _ , vs := range t .constMetrics {
492- if len (vs ) > 1 {
493- var needFill bool
494- for i := 1 ; i < len (vs ); i ++ {
495- if vs [0 ].keysHash != vs [i ].keysHash {
496- needFill = true
497- }
498- }
499- if needFill {
500- vs = fillConstMetricsLabels (vs )
501- }
502- }
503-
504- for _ , v := range vs {
505- metric := prometheus .MustNewConstMetric (
506- t .NewMetricDesc (v .fqName , v .labelKeys ),
507- v .valueType ,
508- v .value ,
509- v .labelValues ... ,
510- )
511- t .ch <- metric
512- }
513- }
514- }
515-
516- func (t * TimeSeriesMetrics ) CompleteHistogramMetrics () {
517- for _ , vs := range t .histogramMetrics {
518- if len (vs ) > 1 {
519- var needFill bool
520- for i := 1 ; i < len (vs ); i ++ {
521- if vs [0 ].keysHash != vs [i ].keysHash {
522- needFill = true
523- }
524- }
525- if needFill {
526- vs = fillHistogramMetricsLabels (vs )
527- }
528- }
529-
530- for _ , v := range vs {
531- metric := prometheus .MustNewConstHistogram (
532- t .NewMetricDesc (v .fqName , v .labelKeys ),
533- uint64 (v .dist .Count ),
534- v .dist .Mean * float64 (v .dist .Count ), // Stackdriver does not provide the sum, but we can fake it
535- v .buckets ,
536- v .labelValues ... ,
537- )
538- t .ch <- metric
539- }
540- }
541- }
542-
543- func fillConstMetricsLabels (metrics []ConstMetric ) []ConstMetric {
544- allKeys := make (map [string ]struct {})
545- for _ , metric := range metrics {
546- for _ , key := range metric .labelKeys {
547- allKeys [key ] = struct {}{}
548- }
549- }
550- result := make ([]ConstMetric , len (metrics ))
551- for i , metric := range metrics {
552- if len (metric .labelKeys ) != len (allKeys ) {
553- metricKeys := make (map [string ]struct {})
554- for _ , key := range metric .labelKeys {
555- metricKeys [key ] = struct {}{}
556- }
557- for key := range allKeys {
558- if _ , ok := metricKeys [key ]; ! ok {
559- metric .labelKeys = append (metric .labelKeys , key )
560- metric .labelValues = append (metric .labelValues , "" )
561- }
562- }
563- }
564- result [i ] = metric
565- }
566-
567- return result
568- }
569-
570- func fillHistogramMetricsLabels (metrics []HistogramMetric ) []HistogramMetric {
571- allKeys := make (map [string ]struct {})
572- for _ , metric := range metrics {
573- for _ , key := range metric .labelKeys {
574- allKeys [key ] = struct {}{}
575- }
576- }
577- result := make ([]HistogramMetric , len (metrics ))
578- for i , metric := range metrics {
579- if len (metric .labelKeys ) != len (allKeys ) {
580- metricKeys := make (map [string ]struct {})
581- for _ , key := range metric .labelKeys {
582- metricKeys [key ] = struct {}{}
583- }
584- for key := range allKeys {
585- if _ , ok := metricKeys [key ]; ! ok {
586- metric .labelKeys = append (metric .labelKeys , key )
587- metric .labelValues = append (metric .labelValues , "" )
588- }
589- }
590- }
591- result [i ] = metric
592- }
593-
594- return result
595- }
0 commit comments