github.com/verrazzano/verrazzano-monitoring-operator@v0.0.30/pkg/metricsexporter/metricsexporter_utils.go (about)

     1  // Copyright (C) 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 metricsexporter
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  	"strconv"
    10  	"time"
    11  
    12  	"github.com/prometheus/client_golang/prometheus"
    13  	"github.com/prometheus/client_golang/prometheus/promhttp"
    14  	"go.uber.org/zap"
    15  	"k8s.io/apimachinery/pkg/util/wait"
    16  )
    17  
    18  func init() {
    19  	RequiredInitialization()
    20  	RegisterMetrics()
    21  }
    22  
    23  // RequiredInitialization populates the metricsexporter, this function must be called before any other non-init exporter function is called
    24  func RequiredInitialization() {
    25  	MetricsExp = metricsExporter{
    26  		internalMetricsDelegate: metricsDelegate{},
    27  		internalConfig:          initConfiguration(),
    28  		internalData: data{
    29  			functionMetricsMap:     initFunctionMetricsMap(),
    30  			simpleCounterMetricMap: initCounterMetricMap(),
    31  			simpleGaugeMetricMap:   initGaugeMetricMap(),
    32  			durationMetricMap:      initDurationMetricMap(),
    33  			timestampMetricMap:     initTimestampMetricMap(),
    34  			errorMetricMap:         initErrorMetricMap(),
    35  		},
    36  	}
    37  
    38  	DefaultLabelFunction = func(index int64) string {
    39  		return strconv.FormatInt(index, 10)
    40  	}
    41  	deploymentLabelFunction = MetricsExp.internalData.functionMetricsMap[NamesDeployment].GetLabel
    42  	configMapLabelFunction = MetricsExp.internalData.simpleCounterMetricMap[NamesConfigMap].GetLabel
    43  	servicesLabelFunction = MetricsExp.internalData.simpleCounterMetricMap[NamesServices].GetLabel
    44  	roleBindingLabelFunction = MetricsExp.internalData.simpleCounterMetricMap[NamesRoleBindings].GetLabel
    45  	VMOUpdateLabelFunction = MetricsExp.internalData.simpleCounterMetricMap[NamesVMOUpdate].GetLabel
    46  }
    47  
    48  // RegisterMetrics begins the registration process, Required Initialization must be called first. This function does not start the metrics server
    49  func RegisterMetrics() {
    50  	MetricsExp.internalMetricsDelegate.InitializeAllMetricsArray()  // populate allMetrics array with all map values
    51  	go MetricsExp.internalMetricsDelegate.RegisterMetricsHandlers() // begin the retry process
    52  }
    53  
    54  func StartMetricsServer() {
    55  	go wait.Until(func() {
    56  		http.Handle("/metrics", promhttp.Handler())
    57  		server := &http.Server{
    58  			Addr:              ":9100",
    59  			ReadHeaderTimeout: 3 * time.Second,
    60  		}
    61  		err := server.ListenAndServe()
    62  		if err != nil {
    63  			zap.S().Errorf("Failed to start metrics server for VMO: %v", err)
    64  		}
    65  	}, time.Second*3, wait.NeverStop)
    66  }
    67  
    68  // InitializeAllMetricsArray internal function used to add all metrics from the metrics maps to the allMetrics array
    69  func (md *metricsDelegate) InitializeAllMetricsArray() {
    70  	// loop through all metrics declarations in metric maps
    71  	for _, value := range MetricsExp.internalData.functionMetricsMap {
    72  		MetricsExp.internalConfig.allMetrics = append(MetricsExp.internalConfig.allMetrics, value.callsTotal.metric, value.durationMetric.metric, value.errorTotal.metric, value.lastCallTimestamp.metric, value.durationMetric.metric)
    73  	}
    74  	for _, value := range MetricsExp.internalData.simpleCounterMetricMap {
    75  		MetricsExp.internalConfig.allMetrics = append(MetricsExp.internalConfig.allMetrics, value.metric)
    76  	}
    77  	for _, value := range MetricsExp.internalData.durationMetricMap {
    78  		MetricsExp.internalConfig.allMetrics = append(MetricsExp.internalConfig.allMetrics, value.metric)
    79  	}
    80  	for _, value := range MetricsExp.internalData.timestampMetricMap {
    81  		MetricsExp.internalConfig.allMetrics = append(MetricsExp.internalConfig.allMetrics, value.metric)
    82  	}
    83  	for _, value := range MetricsExp.internalData.errorMetricMap {
    84  		MetricsExp.internalConfig.allMetrics = append(MetricsExp.internalConfig.allMetrics, value.metric)
    85  	}
    86  	for _, value := range MetricsExp.internalData.simpleGaugeMetricMap {
    87  		MetricsExp.internalConfig.allMetrics = append(MetricsExp.internalConfig.allMetrics, value.metric)
    88  	}
    89  }
    90  
    91  // RegisterMetricsHandlers loops through the failedMetrics map until all metrics are registered successfully
    92  func (md *metricsDelegate) RegisterMetricsHandlers() {
    93  	md.initializeFailedMetricsArray() // Get list of metrics to register initially
    94  	// loop until there is no error in registering
    95  	for err := md.registerMetricsHandlersHelper(); err != nil; err = md.registerMetricsHandlersHelper() {
    96  		zap.S().Errorf("Failed to register metrics for VMO %v \n", err)
    97  		time.Sleep(time.Second)
    98  	}
    99  }
   100  
   101  func (md *metricsDelegate) GetAllMetricsArray() *[]prometheus.Collector {
   102  	return &MetricsExp.internalConfig.allMetrics
   103  }
   104  
   105  func (md *metricsDelegate) GetFailedMetricsMap() map[prometheus.Collector]int {
   106  	return MetricsExp.internalConfig.failedMetrics
   107  }
   108  
   109  func (md *metricsDelegate) GetCounterMetric(name metricName) prometheus.Counter {
   110  	return MetricsExp.internalData.simpleCounterMetricMap[name].metric
   111  }
   112  
   113  func (md *metricsDelegate) GetGaugeMetrics(name metricName) prometheus.Gauge {
   114  	return MetricsExp.internalData.simpleGaugeMetricMap[name].metric
   115  }
   116  
   117  func (md *metricsDelegate) GetTimestampMetric(name metricName) *prometheus.GaugeVec {
   118  	return MetricsExp.internalData.timestampMetricMap[name].metric
   119  }
   120  
   121  // GetFunctionMetrics returns a functionMetric for use if it exists, otherwise returns nil.
   122  func GetFunctionMetrics(name metricName) (*FunctionMetrics, error) {
   123  	returnVal, found := MetricsExp.internalData.functionMetricsMap[name]
   124  	if !found {
   125  		return returnVal, fmt.Errorf("%v is not a valid function metric, it is not in the functionMetrics map", name)
   126  	}
   127  	return returnVal, nil
   128  }
   129  
   130  func (md *metricsDelegate) GetFunctionTimestampMetric(name metricName) *prometheus.GaugeVec {
   131  	return MetricsExp.internalData.functionMetricsMap[name].lastCallTimestamp.metric
   132  }
   133  
   134  func (md *metricsDelegate) GetFunctionDurationMetric(name metricName) prometheus.Summary {
   135  	return MetricsExp.internalData.functionMetricsMap[name].durationMetric.metric
   136  }
   137  
   138  func (md *metricsDelegate) GetFunctionErrorMetric(name metricName) *prometheus.CounterVec {
   139  	return MetricsExp.internalData.functionMetricsMap[name].errorTotal.metric
   140  }
   141  
   142  func (md *metricsDelegate) GetFunctionCounterMetric(name metricName) prometheus.Counter {
   143  	return MetricsExp.internalData.functionMetricsMap[name].callsTotal.metric
   144  }
   145  
   146  // GetCounterMetrics returns a simpleCounterMetric for use if it exists, otherwise returns nil.
   147  func GetCounterMetrics(name metricName) (*CounterMetric, error) {
   148  	returnVal, found := MetricsExp.internalData.simpleCounterMetricMap[name]
   149  	if !found {
   150  		return returnVal, fmt.Errorf("%v is not a valid function metric, it is not in the simpleCounterMetric map", name)
   151  	}
   152  	return returnVal, nil
   153  }
   154  
   155  // GetGaugeMetrics returns a simpleGaugeMetric for use if it exists, otherwise returns nil.
   156  func GetGaugeMetrics(name metricName) (*GaugeMetric, error) {
   157  	returnVal, found := MetricsExp.internalData.simpleGaugeMetricMap[name]
   158  	if !found {
   159  		return returnVal, fmt.Errorf("%v is not a valid function metric, it is not in the simpleGaugeMetric map", name)
   160  	}
   161  	return returnVal, nil
   162  }
   163  
   164  // GetErrorMetrics returns a ErrorMetric for use if it exists, otherwise returns nil.
   165  func GetErrorMetrics(name metricName) (*ErrorMetric, error) {
   166  	returnVal, found := MetricsExp.internalData.errorMetricMap[name]
   167  	if !found {
   168  		return returnVal, fmt.Errorf("%v is not a valid function metric, it is not in the errorMetric map", name)
   169  	}
   170  	return returnVal, nil
   171  }
   172  
   173  // GetDurationMetrics returns a durationMetric for use if it exists, otherwise returns nil.
   174  func GetDurationMetrics(name metricName) (*DurationMetric, error) {
   175  	returnVal, found := MetricsExp.internalData.durationMetricMap[name]
   176  	if !found {
   177  		return returnVal, fmt.Errorf("%v is not a valid function metric, it is not in the durationMetric map", name)
   178  	}
   179  	return returnVal, nil
   180  }
   181  
   182  // GetTimestampMetrics returns a timeStampMetric for use if it exists, otherwise returns nil.
   183  func GetTimestampMetrics(name metricName) (*TimestampMetric, error) {
   184  	returnVal, found := MetricsExp.internalData.timestampMetricMap[name]
   185  	if !found {
   186  		return returnVal, fmt.Errorf("%v is not a valid function metric, it is not in the timestampMetric map", name)
   187  	}
   188  	return returnVal, nil
   189  }