micro/metrics/prometheus/reporter.go
Prawn f9f61d29de
Observability/metrics update (#1962)
* Removing logging from the NOOP implementatino

* Simplifying the percentiles option

* Simple logging implementation

Co-authored-by: chris <chris@Profanity.local>
2020-08-21 20:57:10 +12:00

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
}