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  }