traefik/middlewares/prometheus.go

130 lines
3.7 KiB
Go
Raw Normal View History

2017-01-12 13:34:54 +00:00
package middlewares
import (
2017-04-18 06:22:06 +00:00
"fmt"
2017-01-12 13:34:54 +00:00
"github.com/containous/traefik/types"
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/metrics/prometheus"
stdprometheus "github.com/prometheus/client_golang/prometheus"
)
const (
2017-04-18 06:22:06 +00:00
reqsTotalName = "traefik_requests_total"
reqDurationName = "traefik_request_duration_seconds"
retriesTotalName = "traefik_backend_retries_total"
2017-01-12 13:34:54 +00:00
)
2017-04-18 06:22:06 +00:00
// Prometheus is an Implementation for Metrics that exposes the following Prometheus metrics:
// - number of requests partitioned by status code and method
// - request durations partitioned by status code
2017-04-18 06:22:06 +00:00
// - amount of retries happened
2017-01-12 13:34:54 +00:00
type Prometheus struct {
2017-04-18 06:22:06 +00:00
reqsCounter metrics.Counter
reqDurationHistogram metrics.Histogram
retryCounter metrics.Counter
2017-01-12 13:34:54 +00:00
}
func (p *Prometheus) getReqsCounter() metrics.Counter {
return p.reqsCounter
}
2017-04-18 06:22:06 +00:00
func (p *Prometheus) getReqDurationHistogram() metrics.Histogram {
return p.reqDurationHistogram
}
func (p *Prometheus) getRetryCounter() metrics.Counter {
return p.retryCounter
2017-01-12 13:34:54 +00:00
}
2017-04-18 06:22:06 +00:00
// NewPrometheus returns a new Prometheus Metrics implementation.
// With the returned collectors you have the possibility to clean up the internal Prometheus state by unsubscribing the collectors.
// This is for example useful while testing the Prometheus implementation.
// If any of the Prometheus Metrics can not be registered an error will be returned and the returned Metrics implementation will be nil.
func NewPrometheus(name string, config *types.Prometheus) (*Prometheus, []stdprometheus.Collector, error) {
var prom Prometheus
var collectors []stdprometheus.Collector
2017-03-08 14:17:07 +00:00
cv := stdprometheus.NewCounterVec(
2017-01-12 13:34:54 +00:00
stdprometheus.CounterOpts{
2017-04-18 06:22:06 +00:00
Name: reqsTotalName,
2017-01-12 13:34:54 +00:00
Help: "How many HTTP requests processed, partitioned by status code and method.",
ConstLabels: stdprometheus.Labels{"service": name},
},
[]string{"code", "method"},
)
2017-04-18 06:22:06 +00:00
cv, err := registerCounterVec(cv)
2017-03-08 14:17:07 +00:00
if err != nil {
2017-04-18 06:22:06 +00:00
return nil, collectors, err
2017-03-08 14:17:07 +00:00
}
2017-04-18 06:22:06 +00:00
prom.reqsCounter = prometheus.NewCounter(cv)
collectors = append(collectors, cv)
2017-03-08 14:17:07 +00:00
2017-01-12 13:34:54 +00:00
var buckets []float64
if config.Buckets != nil {
buckets = config.Buckets
} else {
2017-01-17 17:14:13 +00:00
buckets = []float64{0.1, 0.3, 1.2, 5}
2017-01-12 13:34:54 +00:00
}
2017-03-08 14:17:07 +00:00
hv := stdprometheus.NewHistogramVec(
2017-01-12 13:34:54 +00:00
stdprometheus.HistogramOpts{
2017-04-18 06:22:06 +00:00
Name: reqDurationName,
2017-01-17 17:14:13 +00:00
Help: "How long it took to process the request.",
2017-01-12 13:34:54 +00:00
ConstLabels: stdprometheus.Labels{"service": name},
Buckets: buckets,
},
[]string{"code"},
2017-01-12 13:34:54 +00:00
)
2017-04-18 06:22:06 +00:00
hv, err = registerHistogramVec(hv)
if err != nil {
return nil, collectors, err
}
prom.reqDurationHistogram = prometheus.NewHistogram(hv)
collectors = append(collectors, hv)
cv = stdprometheus.NewCounterVec(
stdprometheus.CounterOpts{
Name: retriesTotalName,
Help: "How many request retries happened in total.",
ConstLabels: stdprometheus.Labels{"service": name},
},
[]string{},
)
cv, err = registerCounterVec(cv)
if err != nil {
return nil, collectors, err
}
prom.retryCounter = prometheus.NewCounter(cv)
collectors = append(collectors, cv)
return &prom, collectors, nil
}
func registerCounterVec(cv *stdprometheus.CounterVec) (*stdprometheus.CounterVec, error) {
err := stdprometheus.Register(cv)
2017-03-08 14:17:07 +00:00
if err != nil {
e, ok := err.(stdprometheus.AlreadyRegisteredError)
if !ok {
2017-04-18 06:22:06 +00:00
return nil, fmt.Errorf("error registering CounterVec: %s", e)
2017-03-08 14:17:07 +00:00
}
2017-04-18 06:22:06 +00:00
cv = e.ExistingCollector.(*stdprometheus.CounterVec)
2017-03-08 14:17:07 +00:00
}
2017-04-18 06:22:06 +00:00
return cv, nil
2017-01-12 13:34:54 +00:00
}
2017-04-18 06:22:06 +00:00
func registerHistogramVec(hv *stdprometheus.HistogramVec) (*stdprometheus.HistogramVec, error) {
err := stdprometheus.Register(hv)
if err != nil {
e, ok := err.(stdprometheus.AlreadyRegisteredError)
if !ok {
return nil, fmt.Errorf("error registering HistogramVec: %s", e)
}
hv = e.ExistingCollector.(*stdprometheus.HistogramVec)
}
return hv, nil
2017-01-12 13:34:54 +00:00
}