traefik/middlewares/metrics.go

113 lines
3.2 KiB
Go
Raw Normal View History

2017-01-12 13:34:54 +00:00
package middlewares
import (
"net/http"
"strconv"
"time"
2017-04-18 06:22:06 +00:00
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/metrics/multi"
2017-01-12 13:34:54 +00:00
)
// Metrics is an Interface that must be satisfied by any system that
2017-04-18 06:22:06 +00:00
// wants to expose and monitor Metrics.
2017-01-12 13:34:54 +00:00
type Metrics interface {
getReqsCounter() metrics.Counter
2017-04-18 06:22:06 +00:00
getReqDurationHistogram() metrics.Histogram
RetryMetrics
}
// RetryMetrics must be satisfied by any system that wants to collect and
// expose retry specific Metrics.
type RetryMetrics interface {
getRetryCounter() metrics.Counter
2017-01-12 13:34:54 +00:00
}
// MultiMetrics is a struct that provides a wrapper container for multiple Metrics, if they are configured
type MultiMetrics struct {
wrappedMetrics *[]Metrics
reqsCounter metrics.Counter
reqDurationHistogram metrics.Histogram
retryCounter metrics.Counter
}
// NewMultiMetrics creates a new instance of MultiMetrics
func NewMultiMetrics(manyMetrics []Metrics) *MultiMetrics {
counters := []metrics.Counter{}
histograms := []metrics.Histogram{}
retryCounters := []metrics.Counter{}
for _, m := range manyMetrics {
counters = append(counters, m.getReqsCounter())
histograms = append(histograms, m.getReqDurationHistogram())
retryCounters = append(retryCounters, m.getRetryCounter())
}
var mm MultiMetrics
mm.wrappedMetrics = &manyMetrics
mm.reqsCounter = multi.NewCounter(counters...)
mm.reqDurationHistogram = multi.NewHistogram(histograms...)
mm.retryCounter = multi.NewCounter(retryCounters...)
return &mm
}
func (mm *MultiMetrics) getReqsCounter() metrics.Counter {
return mm.reqsCounter
}
func (mm *MultiMetrics) getReqDurationHistogram() metrics.Histogram {
return mm.reqDurationHistogram
}
func (mm *MultiMetrics) getRetryCounter() metrics.Counter {
return mm.retryCounter
}
2017-01-12 13:34:54 +00:00
// MetricsWrapper is a Negroni compatible Handler which relies on a
2017-04-18 06:22:06 +00:00
// given Metrics implementation to expose and monitor Traefik Metrics.
2017-01-12 13:34:54 +00:00
type MetricsWrapper struct {
Impl Metrics
}
// NewMetricsWrapper return a MetricsWrapper struct with
// a given Metrics implementation e.g Prometheuss
func NewMetricsWrapper(impl Metrics) *MetricsWrapper {
var metricsWrapper = MetricsWrapper{
Impl: impl,
}
return &metricsWrapper
}
func (m *MetricsWrapper) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
start := time.Now()
prw := &responseRecorder{rw, http.StatusOK}
next(prw, r)
reqLabels := []string{"code", strconv.Itoa(prw.statusCode), "method", r.Method}
m.Impl.getReqsCounter().With(reqLabels...).Add(1)
reqDurationLabels := []string{"code", strconv.Itoa(prw.statusCode)}
m.Impl.getReqDurationHistogram().With(reqDurationLabels...).Observe(float64(time.Since(start).Seconds()))
2017-04-18 06:22:06 +00:00
}
// MetricsRetryListener is an implementation of the RetryListener interface to
// record Metrics about retry attempts.
type MetricsRetryListener struct {
retryMetrics RetryMetrics
2017-01-12 13:34:54 +00:00
}
2017-04-18 06:22:06 +00:00
// Retried tracks the retry in the Metrics implementation.
func (m *MetricsRetryListener) Retried(attempt int) {
if m.retryMetrics != nil {
m.retryMetrics.getRetryCounter().Add(1)
}
2017-01-12 13:34:54 +00:00
}
2017-04-18 06:22:06 +00:00
// NewMetricsRetryListener instantiates a MetricsRetryListener with the given RetryMetrics.
func NewMetricsRetryListener(retryMetrics RetryMetrics) RetryListener {
return &MetricsRetryListener{retryMetrics: retryMetrics}
2017-01-12 13:34:54 +00:00
}