github.com/polarismesh/polaris@v1.17.8/plugin/statis/prometheus/statis.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package prometheus 19 20 import ( 21 "context" 22 "time" 23 24 "github.com/prometheus/client_golang/prometheus" 25 26 "github.com/polarismesh/polaris/common/log" 27 "github.com/polarismesh/polaris/common/metrics" 28 "github.com/polarismesh/polaris/common/utils" 29 "github.com/polarismesh/polaris/plugin" 30 "github.com/polarismesh/polaris/plugin/statis/base" 31 ) 32 33 const ( 34 PluginName = "prometheus" 35 ) 36 37 func init() { 38 s := &StatisWorker{} 39 plugin.RegisterPlugin(s.Name(), s) 40 } 41 42 // PrometheusStatis is a struct for prometheus statistics 43 type StatisWorker struct { 44 *base.BaseWorker 45 cancel context.CancelFunc 46 discoveryHandler *discoveryMetricHandle 47 configHandler *configMetricHandle 48 metricVecCaches map[string]*prometheus.GaugeVec 49 } 50 51 // Name 获取统计插件名称 52 func (s *StatisWorker) Name() string { 53 return PluginName 54 } 55 56 // Initialize 初始化统计插件 57 func (s *StatisWorker) Initialize(conf *plugin.ConfigEntry) error { 58 ctx, cancel := context.WithCancel(context.Background()) 59 s.cancel = cancel 60 s.metricVecCaches = make(map[string]*prometheus.GaugeVec) 61 s.discoveryHandler = &discoveryMetricHandle{} 62 s.configHandler = &configMetricHandle{} 63 if err := s.registerMetrics(); err != nil { 64 return err 65 } 66 67 // 设置统计打印周期 68 interval, _ := conf.Option["interval"].(int) 69 if interval == 0 { 70 interval = 60 71 } 72 73 baseWorker, err := base.NewBaseWorker(ctx, s.metricsHandle) 74 if err != nil { 75 cancel() 76 return err 77 } 78 s.BaseWorker = baseWorker 79 80 go s.Run(ctx, time.Duration(interval)*time.Second) 81 return nil 82 } 83 84 // Destroy 销毁统计插件 85 func (s *StatisWorker) Destroy() error { 86 return nil 87 } 88 89 // registerMetrics Registers the interface invocation-related observability metrics 90 func (s *StatisWorker) registerMetrics() error { 91 for _, desc := range base.MetricDescList { 92 var collector prometheus.Collector 93 switch desc.MetricType { 94 case base.TypeForGaugeVec: 95 collector = prometheus.NewGaugeVec(prometheus.GaugeOpts{ 96 Name: desc.Name, 97 Help: desc.Help, 98 ConstLabels: prometheus.Labels{ 99 metrics.LabelServerNode: utils.LocalHost, 100 }, 101 }, desc.LabelNames) 102 s.metricVecCaches[desc.Name] = collector.(*prometheus.GaugeVec) 103 default: 104 continue 105 } 106 107 if err := metrics.GetRegistry().Register(collector); err != nil { 108 log.Errorf("[APICall] register prometheus collector error, %v", err) 109 return err 110 } 111 } 112 return nil 113 } 114 115 // ReportCallMetrics report call metrics info 116 func (s *StatisWorker) ReportCallMetrics(metric metrics.CallMetric) { 117 s.BaseWorker.ReportCallMetrics(metric) 118 } 119 120 // ReportDiscoveryMetrics report discovery metrics 121 func (s *StatisWorker) ReportDiscoveryMetrics(metric ...metrics.DiscoveryMetric) { 122 s.discoveryHandler.handle(metric) 123 } 124 125 // ReportConfigMetrics report config_center metrics 126 func (s *StatisWorker) ReportConfigMetrics(metric ...metrics.ConfigMetrics) { 127 s.configHandler.handle(metric) 128 } 129 130 // ReportDiscoverCall report discover service times 131 func (s *StatisWorker) ReportDiscoverCall(service, namespace string, ttMill int64) { 132 // ignore not support this 133 } 134 135 func (a *StatisWorker) metricsHandle(mt metrics.CallMetricType, start time.Time, 136 staticsSlice []*base.APICallStatisItem) { 137 if mt != metrics.ServerCallMetric { 138 return 139 } 140 if len(staticsSlice) == 0 { 141 return 142 } 143 144 // 每一个接口,共 metricsNumber 个指标,下面的指标的个数调整时,这里的 metricsNumber 也需要调整 145 statInfos := make([]*base.MetricData, 0, len(staticsSlice)*base.MetricsNumber) 146 147 for _, item := range staticsSlice { 148 var ( 149 maxTime, avgTime, rqTime, rqCount, minTime float64 150 deleteFlag bool 151 ) 152 153 if item.Count == 0 && item.ZeroDuration > base.MaxZeroDuration { 154 deleteFlag = true 155 } else { 156 maxTime = float64(item.MaxTime) / 1e6 157 minTime = float64(item.MinTime) / 1e6 158 rqTime = float64(item.AccTime) / 1e6 159 rqCount = float64(item.Count) 160 if item.Count > 0 { 161 avgTime = float64(item.AccTime) / float64(item.Count) / 1e6 162 } 163 deleteFlag = false 164 } 165 166 statInfos = append(statInfos, &base.MetricData{ 167 Name: base.MetricForClientRqTimeoutMax, 168 Data: maxTime, 169 Labels: base.BuildMetricLabels(item), 170 DeleteFlag: deleteFlag, 171 }, &base.MetricData{ 172 Name: base.MetricForClientRqTimeoutAvg, 173 Data: avgTime, 174 Labels: base.BuildMetricLabels(item), 175 DeleteFlag: deleteFlag, 176 }, &base.MetricData{ 177 Name: base.MetricForClientRqTimeout, 178 Data: rqTime, 179 Labels: base.BuildMetricLabels(item), 180 DeleteFlag: deleteFlag, 181 }, &base.MetricData{ 182 Name: base.MetricForClientRqIntervalCount, 183 Data: rqCount, 184 Labels: base.BuildMetricLabels(item), 185 DeleteFlag: deleteFlag, 186 }, &base.MetricData{ 187 Name: base.MetricForClientRqTimeoutMin, 188 Data: minTime, 189 Labels: base.BuildMetricLabels(item), 190 DeleteFlag: deleteFlag, 191 }, 192 ) 193 } 194 195 a.reportToPrometheus(statInfos) 196 } 197 198 // collectMetricData 199 func (s *StatisWorker) reportToPrometheus(statInfos []*base.MetricData) { 200 if len(statInfos) == 0 { 201 return 202 } 203 204 // prometheus-sdk 本身做了pull时数据一致性的保证,这里不需要自己在进行额外的保护动作 205 // 清理掉当前的存量数据 206 for _, statInfo := range statInfos { 207 if len(statInfo.Labels) == 0 { 208 statInfo.Labels = make(map[string]string) 209 } 210 211 metricVec, ok := s.metricVecCaches[statInfo.Name] 212 if !ok { 213 continue 214 } 215 216 if statInfo.DeleteFlag { 217 metricVec.Delete(statInfo.Labels) 218 } else { 219 metricVec.With(statInfo.Labels).Set(statInfo.Data) 220 } 221 } 222 }