* Removing logging from the NOOP implementatino * Simplifying the percentiles option * Simple logging implementation Co-authored-by: chris <chris@Profanity.local>
		
			
				
	
	
		
			76 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			76 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package prometheus
 | |
| 
 | |
| import (
 | |
| 	"net/http"
 | |
| 	"strings"
 | |
| 
 | |
| 	log "github.com/micro/go-micro/v3/logger"
 | |
| 	"github.com/micro/go-micro/v3/metrics"
 | |
| 	"github.com/prometheus/client_golang/prometheus"
 | |
| 	"github.com/prometheus/client_golang/prometheus/promhttp"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	// quantileThresholds maps quantiles / percentiles to error thresholds (required by the Prometheus client).
 | |
| 	// Must be from our pre-defined set [0.0, 0.5, 0.75, 0.90, 0.95, 0.98, 0.99, 1]:
 | |
| 	quantileThresholds = map[float64]float64{0.0: 0, 0.5: 0.05, 0.75: 0.04, 0.90: 0.03, 0.95: 0.02, 0.98: 0.001, 1: 0}
 | |
| )
 | |
| 
 | |
| // Reporter is an implementation of metrics.Reporter:
 | |
| type Reporter struct {
 | |
| 	options            metrics.Options
 | |
| 	prometheusRegistry *prometheus.Registry
 | |
| 	metrics            metricFamily
 | |
| }
 | |
| 
 | |
| // New returns a configured prometheus reporter:
 | |
| func New(opts ...metrics.Option) (*Reporter, error) {
 | |
| 	options := metrics.NewOptions(opts...)
 | |
| 
 | |
| 	// Make a prometheus registry (this keeps track of any metrics we generate):
 | |
| 	prometheusRegistry := prometheus.NewRegistry()
 | |
| 	prometheusRegistry.Register(prometheus.NewGoCollector())
 | |
| 	prometheusRegistry.Register(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{Namespace: "goruntime"}))
 | |
| 
 | |
| 	// Make a new Reporter:
 | |
| 	newReporter := &Reporter{
 | |
| 		options:            options,
 | |
| 		prometheusRegistry: prometheusRegistry,
 | |
| 	}
 | |
| 
 | |
| 	// Add metrics families for each type:
 | |
| 	newReporter.metrics = newReporter.newMetricFamily()
 | |
| 
 | |
| 	// Handle the metrics endpoint with prometheus:
 | |
| 	log.Infof("Metrics/Prometheus [http] Listening on %s%s", options.Address, options.Path)
 | |
| 	http.Handle(options.Path, promhttp.HandlerFor(prometheusRegistry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}))
 | |
| 	go http.ListenAndServe(options.Address, nil)
 | |
| 
 | |
| 	return newReporter, nil
 | |
| }
 | |
| 
 | |
| // convertTags turns Tags into prometheus labels:
 | |
| func (r *Reporter) convertTags(tags metrics.Tags) prometheus.Labels {
 | |
| 	labels := prometheus.Labels{}
 | |
| 	for key, value := range tags {
 | |
| 		labels[key] = r.stripUnsupportedCharacters(value)
 | |
| 	}
 | |
| 	return labels
 | |
| }
 | |
| 
 | |
| // listTagKeys returns a list of tag keys (we need to provide this to the Prometheus client):
 | |
| func (r *Reporter) listTagKeys(tags metrics.Tags) (labelKeys []string) {
 | |
| 	for key := range tags {
 | |
| 		labelKeys = append(labelKeys, key)
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // stripUnsupportedCharacters cleans up a metrics key or value:
 | |
| func (r *Reporter) stripUnsupportedCharacters(metricName string) string {
 | |
| 	valueWithoutDots := strings.Replace(metricName, ".", "_", -1)
 | |
| 	valueWithoutCommas := strings.Replace(valueWithoutDots, ",", "_", -1)
 | |
| 	valueWIthoutSpaces := strings.Replace(valueWithoutCommas, " ", "", -1)
 | |
| 	return valueWIthoutSpaces
 | |
| }
 |