github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/pkg/test/framework/metrics/prometheus.go (about)

     1  // Copyright (c) 2021, 2022, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package metrics
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/prometheus/client_golang/prometheus"
    11  	"github.com/prometheus/client_golang/prometheus/push"
    12  	"github.com/verrazzano/verrazzano/tests/e2e/pkg"
    13  )
    14  
    15  type PrometheusMetricsReceiverConfig struct {
    16  	PushGatewayURL      string
    17  	PushGatewayUser     string
    18  	PushGatewayPassword string
    19  	PushInterval        time.Duration
    20  	Name                string
    21  }
    22  
    23  type PrometheusMetricsReceiver struct {
    24  	promPusher *push.Pusher
    25  	Name       string
    26  	counters   map[string]prometheus.Counter
    27  	gauges     map[string]prometheus.Gauge
    28  }
    29  
    30  func (pcfg *PrometheusMetricsReceiverConfig) GetReceiverType() string {
    31  	return "PrometheusMetricsReceiver"
    32  }
    33  
    34  func (rcvr *PrometheusMetricsReceiver) SetGauge(name string, value float64) error {
    35  	if rcvr.gauges == nil {
    36  		rcvr.gauges = make(map[string]prometheus.Gauge)
    37  	}
    38  	metricName := rcvr.makeMetricName(name)
    39  	gauge := rcvr.gauges[metricName]
    40  	if gauge == nil {
    41  		gauge = prometheus.NewGauge(prometheus.GaugeOpts{Name: metricName})
    42  		rcvr.gauges[metricName] = gauge
    43  	}
    44  	gauge.Set(value)
    45  	pkg.Log(pkg.Info, fmt.Sprintf("Emitting gauge %s with value %f", metricName, value))
    46  
    47  	// Asynchronously push the gauge to the Prometheus push gateway
    48  	rcvr.asyncPush(gauge, metricName)
    49  	return nil
    50  }
    51  
    52  func (rcvr *PrometheusMetricsReceiver) IncrementCounter(name string) error {
    53  	if rcvr.counters == nil {
    54  		rcvr.counters = make(map[string]prometheus.Counter)
    55  	}
    56  	metricName := rcvr.makeMetricName(name)
    57  	ctr := rcvr.counters[metricName]
    58  	if ctr == nil {
    59  		ctr = prometheus.NewCounter(prometheus.CounterOpts{Name: metricName})
    60  		rcvr.counters[metricName] = ctr
    61  	}
    62  	ctr.Inc()
    63  	pkg.Log(pkg.Info, fmt.Sprintf("Incrementing counter %s", metricName))
    64  
    65  	rcvr.asyncPush(ctr, metricName)
    66  	return nil
    67  }
    68  
    69  // Use a goroutine to asynchronously kick off a push to the Prometheus gateway represented by rcvr.promPusher
    70  func (rcvr *PrometheusMetricsReceiver) asyncPush(ctr prometheus.Collector, metricName string) {
    71  	go func() {
    72  		// push the counter to the gateway
    73  		if err := rcvr.promPusher.Collector(ctr).Add(); err != nil {
    74  			pkg.Log(pkg.Error, fmt.Sprintf("could not push metric %s to push gateway: %s", metricName, err.Error()))
    75  		}
    76  		pkg.Log(pkg.Info, fmt.Sprintf("Successfully emitted metric %s", metricName))
    77  	}()
    78  }
    79  
    80  // Create a new PrometheusMetricsReceiver based on the configuration options provided
    81  func NewPrometheusMetricsReceiver(cfg PrometheusMetricsReceiverConfig) (*PrometheusMetricsReceiver, error) {
    82  	receiver := PrometheusMetricsReceiver{}
    83  	pusher := push.New(cfg.PushGatewayURL, cfg.Name)
    84  	if cfg.PushGatewayUser != "" && cfg.PushGatewayPassword != "" {
    85  		pusher = pusher.BasicAuth(cfg.PushGatewayUser, cfg.PushGatewayPassword)
    86  	}
    87  	receiver.promPusher = pusher
    88  	receiver.Name = cfg.Name
    89  	return &receiver, nil
    90  }
    91  
    92  func (rcvr *PrometheusMetricsReceiver) makeMetricName(name string) string {
    93  	if rcvr.Name != "" {
    94  		return rcvr.Name + "_" + name
    95  	}
    96  	return name
    97  }