github.com/amazechain/amc@v0.1.3/internal/metrics/prometheus/prometheus.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package prometheus exposes go-metrics into a Prometheus format. 18 package prometheus 19 20 import ( 21 "fmt" 22 metrics2 "github.com/VictoriaMetrics/metrics" 23 "github.com/amazechain/amc/log" 24 "github.com/prometheus/client_golang/prometheus" 25 "github.com/prometheus/common/expfmt" 26 27 "net/http" 28 "sort" 29 ) 30 31 // Handler returns an HTTP handler which dump metrics in Prometheus format. 32 // Output format can be cheched here: https://o11y.tools/metricslint/ 33 func Handler(reg Registry) http.Handler { 34 prometheus.DefaultRegisterer.MustRegister(defaultSet) 35 36 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 37 // Gather and pre-sort the metrics to avoid random listings 38 var names []string 39 reg.Each(func(name string, i interface{}) { 40 names = append(names, name) 41 }) 42 sort.Strings(names) 43 44 w.Header().Set("Access-Control-Allow-Origin", "*") 45 46 metrics2.WritePrometheus(w, true) 47 48 contentType := expfmt.Negotiate(r.Header) 49 enc := expfmt.NewEncoder(w, contentType) 50 mf, err := prometheus.DefaultGatherer.Gather() 51 if err != nil { 52 return 53 } 54 for _, m := range mf { 55 enc.Encode(m) 56 } 57 58 // Aggregate all the metris into a Prometheus collector 59 c := newCollector() 60 c.buff.WriteRune('\n') 61 62 var typeName string 63 var prevTypeName string 64 65 for _, name := range names { 66 i := reg.Get(name) 67 68 typeName = stripLabels(name) 69 70 switch m := i.(type) { 71 case *metrics2.Counter: 72 if m.IsGauge() { 73 c.writeGauge(name, m.Get(), typeName != prevTypeName) 74 } else { 75 c.writeCounter(name, m.Get(), typeName != prevTypeName) 76 } 77 case *metrics2.Gauge: 78 c.writeGauge(name, m, typeName != prevTypeName) 79 case *metrics2.FloatCounter: 80 c.writeFloatCounter(name, m, typeName != prevTypeName) 81 case *metrics2.Histogram: 82 c.writeHistogram(name, m, typeName != prevTypeName) 83 case *metrics2.Summary: 84 c.writeTimer(name, m, typeName != prevTypeName) 85 default: 86 log.Warn("Unknown Prometheus metric type", "type", fmt.Sprintf("%T", i)) 87 } 88 89 prevTypeName = typeName 90 } 91 w.Header().Add("Content-Type", "text/plain") 92 w.Header().Add("Content-Length", fmt.Sprint(c.buff.Len())) 93 w.Write(c.buff.Bytes()) 94 }) 95 }