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 }