github.com/klaytn/klaytn@v1.12.1/metrics/prometheus/prometheusmetrics.go (about) 1 // Copyright 2018 The klaytn Authors 2 // 3 // This file is derived from metrics/prometheus/prometheusmetrics.go (2018/06/04). 4 // See LICENSE in the top directory for the original copyright and license. 5 6 package prometheusmetrics 7 8 import ( 9 "fmt" 10 "strings" 11 "time" 12 13 klaytnmetrics "github.com/klaytn/klaytn/metrics" 14 15 "github.com/prometheus/client_golang/prometheus" 16 "github.com/rcrowley/go-metrics" 17 ) 18 19 // PrometheusConfig provides a container with config parameters for the Prometheus Exporter 20 21 type PrometheusConfig struct { 22 namespace string 23 Registry metrics.Registry // Registry to be exported 24 subsystem string 25 promRegistry prometheus.Registerer // Prometheus registry 26 FlushInterval time.Duration // interval to update prom metrics 27 gauges map[string]prometheus.Gauge 28 } 29 30 // NewPrometheusProvider returns a Provider that produces Prometheus metrics. 31 // Namespace and subsystem are applied to all produced metrics. 32 func NewPrometheusProvider(r metrics.Registry, namespace string, subsystem string, promRegistry prometheus.Registerer, 33 FlushInterval time.Duration, 34 ) *PrometheusConfig { 35 return &PrometheusConfig{ 36 namespace: namespace, 37 subsystem: subsystem, 38 Registry: r, 39 promRegistry: promRegistry, 40 FlushInterval: FlushInterval, 41 gauges: make(map[string]prometheus.Gauge), 42 } 43 } 44 45 func (c *PrometheusConfig) flattenKey(key string) string { 46 key = strings.Replace(key, " ", "_", -1) 47 key = strings.Replace(key, ".", "_", -1) 48 key = strings.Replace(key, "-", "_", -1) 49 key = strings.Replace(key, "=", "_", -1) 50 key = strings.Replace(key, "/", "_", -1) 51 return key 52 } 53 54 func (c *PrometheusConfig) gaugeFromNameAndValue(name string, val float64) { 55 key := fmt.Sprintf("%s_%s_%s", c.namespace, c.subsystem, name) 56 g, ok := c.gauges[key] 57 if !ok { 58 g = prometheus.NewGauge(prometheus.GaugeOpts{ 59 Namespace: c.flattenKey(c.namespace), 60 Subsystem: c.flattenKey(c.subsystem), 61 Name: c.flattenKey(name), 62 Help: name, 63 }) 64 c.promRegistry.MustRegister(g) 65 c.gauges[key] = g 66 } 67 g.Set(val) 68 } 69 70 func (c *PrometheusConfig) UpdatePrometheusMetrics() { 71 for range time.Tick(c.FlushInterval) { 72 c.UpdatePrometheusMetricsOnce() 73 klaytnmetrics.ResetMaxGauges() 74 } 75 } 76 77 var ( 78 pv = []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999} 79 pv_str = []string{"_0_5", "_0_75", "_0_95", "_0_99", "_0_999", "_0_9999"} 80 ) 81 82 func (c *PrometheusConfig) UpdatePrometheusMetricsOnce() error { 83 c.Registry.Each(func(name string, i interface{}) { 84 switch metric := i.(type) { 85 case metrics.Counter: 86 c.gaugeFromNameAndValue(name, float64(metric.Count())) 87 case metrics.Gauge: 88 c.gaugeFromNameAndValue(name, float64(metric.Value())) 89 case metrics.GaugeFloat64: 90 c.gaugeFromNameAndValue(name, float64(metric.Value())) 91 case metrics.Histogram: 92 samples := metric.Snapshot().Sample().Values() 93 if len(samples) > 0 { 94 lastSample := samples[len(samples)-1] 95 c.gaugeFromNameAndValue(name, float64(lastSample)) 96 } 97 case metrics.Meter: 98 lastSample := metric.Snapshot().Rate1() 99 c.gaugeFromNameAndValue(name, float64(lastSample)) 100 case metrics.Timer: 101 // use mean as a default export value of metrics.Timer 102 c.gaugeFromNameAndValue(name, metric.Mean()) 103 // also retrieve and export percentiles 104 ps := metric.Percentiles(pv) 105 for i := range pv { 106 c.gaugeFromNameAndValue(name+pv_str[i], ps[i]) 107 } 108 } 109 }) 110 return nil 111 }