dubbo.apache.org/dubbo-go/v3@v3.1.1/metrics/api.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package metrics 19 20 import ( 21 "encoding/json" 22 "sync" 23 ) 24 25 import ( 26 "github.com/dubbogo/gost/log/logger" 27 ) 28 29 import ( 30 "dubbo.apache.org/dubbo-go/v3/common" 31 "dubbo.apache.org/dubbo-go/v3/common/constant" 32 "dubbo.apache.org/dubbo-go/v3/metrics/util/aggregate" 33 ) 34 35 const ( 36 DefaultCompression = 100 37 DefaultBucketNum = 10 38 DefaultTimeWindowSeconds = 120 39 ) 40 41 var ( 42 registries = make(map[string]func(*common.URL) MetricRegistry) 43 collectors = make([]CollectorFunc, 0) 44 registry MetricRegistry 45 once sync.Once 46 ) 47 48 // CollectorFunc used to extend more indicators 49 type CollectorFunc func(MetricRegistry, *common.URL) 50 51 // Init Metrics module 52 func Init(url *common.URL) { 53 once.Do(func() { 54 InitAppInfo(url.GetParam(constant.ApplicationKey, ""), url.GetParam(constant.AppVersionKey, "")) 55 // default protocol is already set in metricConfig 56 regFunc, ok := registries[url.Protocol] 57 if ok { 58 registry = regFunc(url) 59 for _, co := range collectors { 60 co(registry, url) 61 } 62 registry.Export() 63 } 64 }) 65 } 66 67 // SetRegistry extend more MetricRegistry, default PrometheusRegistry 68 func SetRegistry(name string, v func(*common.URL) MetricRegistry) { 69 registries[name] = v 70 } 71 72 // AddCollector add more indicators, like metadata, sla, config-center etc. 73 func AddCollector(name string, fun CollectorFunc) { 74 collectors = append(collectors, fun) 75 } 76 77 // MetricRegistry data container,data compute、expose、agg 78 type MetricRegistry interface { 79 Counter(*MetricId) CounterMetric // add or update a counter 80 Gauge(*MetricId) GaugeMetric // add or update a gauge 81 Histogram(*MetricId) ObservableMetric // add a metric num to a histogram 82 Summary(*MetricId) ObservableMetric // add a metric num to a summary 83 Rt(*MetricId, *RtOpts) ObservableMetric // add a metric num to a rt 84 Export() // expose metric data, such as Prometheus http exporter 85 // GetMetrics() []*MetricSample // get all metric data 86 // GetMetricsString() (string, error) // get text format metric data 87 } 88 89 type RtOpts struct { 90 Aggregate bool 91 BucketNum int // only for aggRt 92 TimeWindowSeconds int64 // only for aggRt 93 } 94 95 // multi registry,like micrometer CompositeMeterRegistry 96 // type CompositeRegistry struct { 97 // rs []MetricRegistry 98 // } 99 100 // Type metric type, same with micrometer 101 type Type uint8 // TODO check if Type is is useful 102 103 const ( 104 Counter Type = iota 105 Gauge 106 LongTaskTimer 107 Timer 108 DistributionSummary 109 Other 110 ) 111 112 // MetricId 113 // # HELP dubbo_metadata_store_provider_succeed_total Succeed Store Provider Metadata 114 // # TYPE dubbo_metadata_store_provider_succeed_total gauge 115 // dubbo_metadata_store_provider_succeed_total{application_name="provider",hostname="localhost",interface="org.example.DemoService",ip="10.252.156.213",} 1.0 116 // other properties except value 117 type MetricId struct { 118 Name string 119 Desc string 120 Tags map[string]string // also named label 121 Type Type // TODO check if this field is useful 122 } 123 124 func (m *MetricId) TagKeys() []string { 125 keys := make([]string, 0, len(m.Tags)) 126 for k := range m.Tags { 127 keys = append(keys, k) 128 } 129 return keys 130 } 131 132 func NewMetricId(key *MetricKey, level MetricLevel) *MetricId { 133 return &MetricId{Name: key.Name, Desc: key.Desc, Tags: level.Tags()} 134 } 135 136 // NewMetricIdByLabels create a MetricId by key and labels 137 func NewMetricIdByLabels(key *MetricKey, labels map[string]string) *MetricId { 138 return &MetricId{Name: key.Name, Desc: key.Desc, Tags: labels} 139 } 140 141 // MetricSample a metric sample,This is the final data presentation, 142 // not an intermediate result(like summary,histogram they will export to a set of MetricSample) 143 type MetricSample struct { 144 *MetricId 145 value float64 146 } 147 148 // CounterMetric counter metric 149 type CounterMetric interface { 150 Inc() 151 Add(float64) 152 } 153 154 // GaugeMetric gauge metric 155 type GaugeMetric interface { 156 Set(float64) 157 Inc() 158 Dec() 159 Add(float64) 160 Sub(float64) 161 } 162 163 // histogram summary rt metric 164 type ObservableMetric interface { 165 Observe(float64) 166 } 167 168 type BaseCollector struct { 169 R MetricRegistry 170 } 171 172 func (c *BaseCollector) StateCount(total, succ, fail *MetricKey, level MetricLevel, succed bool) { 173 c.R.Counter(NewMetricId(total, level)).Inc() 174 if succed { 175 c.R.Counter(NewMetricId(succ, level)).Inc() 176 } else { 177 c.R.Counter(NewMetricId(fail, level)).Inc() 178 } 179 } 180 181 // CounterVec means a set of counters with the same metricKey but different labels 182 type CounterVec interface { 183 Inc(labels map[string]string) 184 Add(labels map[string]string, v float64) 185 } 186 187 // NewCounterVec create a CounterVec default implementation. 188 func NewCounterVec(metricRegistry MetricRegistry, metricKey *MetricKey) CounterVec { 189 return &DefaultCounterVec{ 190 metricRegistry: metricRegistry, 191 metricKey: metricKey, 192 } 193 } 194 195 // DefaultCounterVec is a default CounterVec implementation. 196 type DefaultCounterVec struct { 197 metricRegistry MetricRegistry 198 metricKey *MetricKey 199 } 200 201 func (d *DefaultCounterVec) Inc(labels map[string]string) { 202 d.metricRegistry.Counter(NewMetricIdByLabels(d.metricKey, labels)).Inc() 203 } 204 205 func (d *DefaultCounterVec) Add(labels map[string]string, v float64) { 206 d.metricRegistry.Counter(NewMetricIdByLabels(d.metricKey, labels)).Add(v) 207 } 208 209 // GaugeVec means a set of gauges with the same metricKey but different labels 210 type GaugeVec interface { 211 Set(labels map[string]string, v float64) 212 Inc(labels map[string]string) 213 Dec(labels map[string]string) 214 Add(labels map[string]string, v float64) 215 Sub(labels map[string]string, v float64) 216 } 217 218 // NewGaugeVec create a GaugeVec default implementation. 219 func NewGaugeVec(metricRegistry MetricRegistry, metricKey *MetricKey) GaugeVec { 220 return &DefaultGaugeVec{ 221 metricRegistry: metricRegistry, 222 metricKey: metricKey, 223 } 224 } 225 226 // DefaultGaugeVec is a default GaugeVec implementation. 227 type DefaultGaugeVec struct { 228 metricRegistry MetricRegistry 229 metricKey *MetricKey 230 } 231 232 func (d *DefaultGaugeVec) Set(labels map[string]string, v float64) { 233 d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Set(v) 234 } 235 236 func (d *DefaultGaugeVec) Inc(labels map[string]string) { 237 d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Inc() 238 } 239 240 func (d *DefaultGaugeVec) Dec(labels map[string]string) { 241 d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Dec() 242 } 243 244 func (d *DefaultGaugeVec) Add(labels map[string]string, v float64) { 245 d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Add(v) 246 } 247 248 func (d *DefaultGaugeVec) Sub(labels map[string]string, v float64) { 249 d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Sub(v) 250 } 251 252 // RtVec means a set of rt metrics with the same metricKey but different labels 253 type RtVec interface { 254 Record(labels map[string]string, v float64) 255 } 256 257 // NewRtVec create a RtVec default implementation DefaultRtVec. 258 func NewRtVec(metricRegistry MetricRegistry, metricKey *MetricKey, rtOpts *RtOpts) RtVec { 259 return &DefaultRtVec{ 260 metricRegistry: metricRegistry, 261 metricKey: metricKey, 262 rtOpts: rtOpts, 263 } 264 } 265 266 // DefaultRtVec is a default RtVec implementation. 267 // 268 // If rtOpts.Aggregate is true, it will use the aggregate.TimeWindowAggregator with local aggregation, 269 // else it will use the aggregate.Result without aggregation. 270 type DefaultRtVec struct { 271 metricRegistry MetricRegistry 272 metricKey *MetricKey 273 rtOpts *RtOpts 274 } 275 276 func (d *DefaultRtVec) Record(labels map[string]string, v float64) { 277 d.metricRegistry.Rt(NewMetricIdByLabels(d.metricKey, labels), d.rtOpts).Observe(v) 278 } 279 280 // labelsToString convert @labels to json format string for cache key 281 func labelsToString(labels map[string]string) string { 282 labelsJson, err := json.Marshal(labels) 283 if err != nil { 284 logger.Errorf("json.Marshal(labels) = error:%v", err) 285 return "" 286 } 287 return string(labelsJson) 288 } 289 290 // QpsMetricVec means a set of qps metrics with the same metricKey but different labels. 291 type QpsMetricVec interface { 292 Record(labels map[string]string) 293 } 294 295 func NewQpsMetricVec(metricRegistry MetricRegistry, metricKey *MetricKey) QpsMetricVec { 296 return &DefaultQpsMetricVec{ 297 metricRegistry: metricRegistry, 298 metricKey: metricKey, 299 mux: sync.RWMutex{}, 300 cache: make(map[string]*aggregate.TimeWindowCounter), 301 } 302 } 303 304 // DefaultQpsMetricVec is a default QpsMetricVec implementation. 305 // 306 // It is concurrent safe, and it uses the aggregate.TimeWindowCounter to store and calculate the qps metrics. 307 type DefaultQpsMetricVec struct { 308 metricRegistry MetricRegistry 309 metricKey *MetricKey 310 mux sync.RWMutex 311 cache map[string]*aggregate.TimeWindowCounter // key: metrics labels, value: TimeWindowCounter 312 } 313 314 func (d *DefaultQpsMetricVec) Record(labels map[string]string) { 315 key := labelsToString(labels) 316 if key == "" { 317 return 318 } 319 d.mux.RLock() 320 twc, ok := d.cache[key] 321 d.mux.RUnlock() 322 if !ok { 323 d.mux.Lock() 324 twc, ok = d.cache[key] 325 if !ok { 326 twc = aggregate.NewTimeWindowCounter(DefaultBucketNum, DefaultTimeWindowSeconds) 327 d.cache[key] = twc 328 } 329 d.mux.Unlock() 330 } 331 twc.Inc() 332 d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Set(twc.Count() / float64(twc.LivedSeconds())) 333 } 334 335 // AggregateCounterVec means a set of aggregate counter metrics with the same metricKey but different labels. 336 type AggregateCounterVec interface { 337 Inc(labels map[string]string) 338 } 339 340 func NewAggregateCounterVec(metricRegistry MetricRegistry, metricKey *MetricKey) AggregateCounterVec { 341 return &DefaultAggregateCounterVec{ 342 metricRegistry: metricRegistry, 343 metricKey: metricKey, 344 mux: sync.RWMutex{}, 345 cache: make(map[string]*aggregate.TimeWindowCounter), 346 } 347 } 348 349 // DefaultAggregateCounterVec is a default AggregateCounterVec implementation. 350 // 351 // It is concurrent safe, and it uses the aggregate.TimeWindowCounter to store and calculate the aggregate counter metrics. 352 type DefaultAggregateCounterVec struct { 353 metricRegistry MetricRegistry 354 metricKey *MetricKey 355 mux sync.RWMutex 356 cache map[string]*aggregate.TimeWindowCounter // key: metrics labels, value: TimeWindowCounter 357 } 358 359 func (d *DefaultAggregateCounterVec) Inc(labels map[string]string) { 360 key := labelsToString(labels) 361 if key == "" { 362 return 363 } 364 d.mux.RLock() 365 twc, ok := d.cache[key] 366 d.mux.RUnlock() 367 if !ok { 368 d.mux.Lock() 369 twc, ok = d.cache[key] 370 if !ok { 371 twc = aggregate.NewTimeWindowCounter(DefaultBucketNum, DefaultTimeWindowSeconds) 372 d.cache[key] = twc 373 } 374 d.mux.Unlock() 375 } 376 twc.Inc() 377 d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Set(twc.Count()) 378 } 379 380 // QuantileMetricVec means a set of quantile metrics with the same metricKey but different labels. 381 type QuantileMetricVec interface { 382 Record(labels map[string]string, v float64) 383 } 384 385 func NewQuantileMetricVec(metricRegistry MetricRegistry, metricKeys []*MetricKey, quantiles []float64) QuantileMetricVec { 386 return &DefaultQuantileMetricVec{ 387 metricRegistry: metricRegistry, 388 metricKeys: metricKeys, 389 mux: sync.RWMutex{}, 390 cache: make(map[string]*aggregate.TimeWindowQuantile), 391 quantiles: quantiles, 392 } 393 } 394 395 // DefaultQuantileMetricVec is a default QuantileMetricVec implementation. 396 // 397 // It is concurrent safe, and it uses the aggregate.TimeWindowQuantile to store and calculate the quantile metrics. 398 type DefaultQuantileMetricVec struct { 399 metricRegistry MetricRegistry 400 metricKeys []*MetricKey 401 mux sync.RWMutex 402 cache map[string]*aggregate.TimeWindowQuantile // key: metrics labels, value: TimeWindowQuantile 403 quantiles []float64 404 } 405 406 func (d *DefaultQuantileMetricVec) Record(labels map[string]string, v float64) { 407 key := labelsToString(labels) 408 if key == "" { 409 return 410 } 411 d.mux.RLock() 412 twq, ok := d.cache[key] 413 d.mux.RUnlock() 414 if !ok { 415 d.mux.Lock() 416 twq, ok = d.cache[key] 417 if !ok { 418 twq = aggregate.NewTimeWindowQuantile(DefaultCompression, DefaultBucketNum, DefaultTimeWindowSeconds) 419 d.cache[key] = twq 420 } 421 d.mux.Unlock() 422 } 423 twq.Add(v) 424 425 for i, q := range twq.Quantiles(d.quantiles) { 426 d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKeys[i], labels)).Set(q) 427 } 428 }