mirror of
				https://github.com/traefik/traefik.git
				synced 2025-10-31 00:11:38 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			382 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			382 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package metrics
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/go-kit/kit/metrics"
 | |
| 	"github.com/go-kit/kit/metrics/multi"
 | |
| )
 | |
| 
 | |
| const defaultMetricsPrefix = "traefik"
 | |
| 
 | |
| // Registry has to implemented by any system that wants to monitor and expose metrics.
 | |
| type Registry interface {
 | |
| 	// IsEpEnabled shows whether metrics instrumentation is enabled on entry points.
 | |
| 	IsEpEnabled() bool
 | |
| 	// IsRouterEnabled shows whether metrics instrumentation is enabled on routers.
 | |
| 	IsRouterEnabled() bool
 | |
| 	// IsSvcEnabled shows whether metrics instrumentation is enabled on services.
 | |
| 	IsSvcEnabled() bool
 | |
| 
 | |
| 	// server metrics
 | |
| 
 | |
| 	ConfigReloadsCounter() metrics.Counter
 | |
| 	LastConfigReloadSuccessGauge() metrics.Gauge
 | |
| 	OpenConnectionsGauge() metrics.Gauge
 | |
| 
 | |
| 	// TLS
 | |
| 
 | |
| 	TLSCertsNotAfterTimestampGauge() metrics.Gauge
 | |
| 
 | |
| 	// entry point metrics
 | |
| 
 | |
| 	EntryPointReqsCounter() CounterWithHeaders
 | |
| 	EntryPointReqsTLSCounter() metrics.Counter
 | |
| 	EntryPointReqDurationHistogram() ScalableHistogram
 | |
| 	EntryPointReqsBytesCounter() metrics.Counter
 | |
| 	EntryPointRespsBytesCounter() metrics.Counter
 | |
| 
 | |
| 	// router metrics
 | |
| 
 | |
| 	RouterReqsCounter() CounterWithHeaders
 | |
| 	RouterReqsTLSCounter() metrics.Counter
 | |
| 	RouterReqDurationHistogram() ScalableHistogram
 | |
| 	RouterReqsBytesCounter() metrics.Counter
 | |
| 	RouterRespsBytesCounter() metrics.Counter
 | |
| 
 | |
| 	// service metrics
 | |
| 
 | |
| 	ServiceReqsCounter() CounterWithHeaders
 | |
| 	ServiceReqsTLSCounter() metrics.Counter
 | |
| 	ServiceReqDurationHistogram() ScalableHistogram
 | |
| 	ServiceRetriesCounter() metrics.Counter
 | |
| 	ServiceServerUpGauge() metrics.Gauge
 | |
| 	ServiceReqsBytesCounter() metrics.Counter
 | |
| 	ServiceRespsBytesCounter() metrics.Counter
 | |
| }
 | |
| 
 | |
| // NewVoidRegistry is a noop implementation of metrics.Registry.
 | |
| // It is used to avoid nil checking in components that do metric collections.
 | |
| func NewVoidRegistry() Registry {
 | |
| 	return NewMultiRegistry([]Registry{})
 | |
| }
 | |
| 
 | |
| // NewMultiRegistry is an implementation of metrics.Registry that wraps multiple registries.
 | |
| // It handles the case when a registry hasn't registered some metric and returns nil.
 | |
| // This allows for feature disparity between the different metric implementations.
 | |
| func NewMultiRegistry(registries []Registry) Registry {
 | |
| 	var configReloadsCounter []metrics.Counter
 | |
| 	var lastConfigReloadSuccessGauge []metrics.Gauge
 | |
| 	var openConnectionsGauge []metrics.Gauge
 | |
| 	var tlsCertsNotAfterTimestampGauge []metrics.Gauge
 | |
| 	var entryPointReqsCounter []CounterWithHeaders
 | |
| 	var entryPointReqsTLSCounter []metrics.Counter
 | |
| 	var entryPointReqDurationHistogram []ScalableHistogram
 | |
| 	var entryPointReqsBytesCounter []metrics.Counter
 | |
| 	var entryPointRespsBytesCounter []metrics.Counter
 | |
| 	var routerReqsCounter []CounterWithHeaders
 | |
| 	var routerReqsTLSCounter []metrics.Counter
 | |
| 	var routerReqDurationHistogram []ScalableHistogram
 | |
| 	var routerReqsBytesCounter []metrics.Counter
 | |
| 	var routerRespsBytesCounter []metrics.Counter
 | |
| 	var serviceReqsCounter []CounterWithHeaders
 | |
| 	var serviceReqsTLSCounter []metrics.Counter
 | |
| 	var serviceReqDurationHistogram []ScalableHistogram
 | |
| 	var serviceRetriesCounter []metrics.Counter
 | |
| 	var serviceServerUpGauge []metrics.Gauge
 | |
| 	var serviceReqsBytesCounter []metrics.Counter
 | |
| 	var serviceRespsBytesCounter []metrics.Counter
 | |
| 
 | |
| 	for _, r := range registries {
 | |
| 		if r.ConfigReloadsCounter() != nil {
 | |
| 			configReloadsCounter = append(configReloadsCounter, r.ConfigReloadsCounter())
 | |
| 		}
 | |
| 		if r.LastConfigReloadSuccessGauge() != nil {
 | |
| 			lastConfigReloadSuccessGauge = append(lastConfigReloadSuccessGauge, r.LastConfigReloadSuccessGauge())
 | |
| 		}
 | |
| 		if r.OpenConnectionsGauge() != nil {
 | |
| 			openConnectionsGauge = append(openConnectionsGauge, r.OpenConnectionsGauge())
 | |
| 		}
 | |
| 		if r.TLSCertsNotAfterTimestampGauge() != nil {
 | |
| 			tlsCertsNotAfterTimestampGauge = append(tlsCertsNotAfterTimestampGauge, r.TLSCertsNotAfterTimestampGauge())
 | |
| 		}
 | |
| 		if r.EntryPointReqsCounter() != nil {
 | |
| 			entryPointReqsCounter = append(entryPointReqsCounter, r.EntryPointReqsCounter())
 | |
| 		}
 | |
| 		if r.EntryPointReqsTLSCounter() != nil {
 | |
| 			entryPointReqsTLSCounter = append(entryPointReqsTLSCounter, r.EntryPointReqsTLSCounter())
 | |
| 		}
 | |
| 		if r.EntryPointReqDurationHistogram() != nil {
 | |
| 			entryPointReqDurationHistogram = append(entryPointReqDurationHistogram, r.EntryPointReqDurationHistogram())
 | |
| 		}
 | |
| 		if r.EntryPointReqsBytesCounter() != nil {
 | |
| 			entryPointReqsBytesCounter = append(entryPointReqsBytesCounter, r.EntryPointReqsBytesCounter())
 | |
| 		}
 | |
| 		if r.EntryPointRespsBytesCounter() != nil {
 | |
| 			entryPointRespsBytesCounter = append(entryPointRespsBytesCounter, r.EntryPointRespsBytesCounter())
 | |
| 		}
 | |
| 		if r.RouterReqsCounter() != nil {
 | |
| 			routerReqsCounter = append(routerReqsCounter, r.RouterReqsCounter())
 | |
| 		}
 | |
| 		if r.RouterReqsTLSCounter() != nil {
 | |
| 			routerReqsTLSCounter = append(routerReqsTLSCounter, r.RouterReqsTLSCounter())
 | |
| 		}
 | |
| 		if r.RouterReqDurationHistogram() != nil {
 | |
| 			routerReqDurationHistogram = append(routerReqDurationHistogram, r.RouterReqDurationHistogram())
 | |
| 		}
 | |
| 		if r.RouterReqsBytesCounter() != nil {
 | |
| 			routerReqsBytesCounter = append(routerReqsBytesCounter, r.RouterReqsBytesCounter())
 | |
| 		}
 | |
| 		if r.RouterRespsBytesCounter() != nil {
 | |
| 			routerRespsBytesCounter = append(routerRespsBytesCounter, r.RouterRespsBytesCounter())
 | |
| 		}
 | |
| 		if r.ServiceReqsCounter() != nil {
 | |
| 			serviceReqsCounter = append(serviceReqsCounter, r.ServiceReqsCounter())
 | |
| 		}
 | |
| 		if r.ServiceReqsTLSCounter() != nil {
 | |
| 			serviceReqsTLSCounter = append(serviceReqsTLSCounter, r.ServiceReqsTLSCounter())
 | |
| 		}
 | |
| 		if r.ServiceReqDurationHistogram() != nil {
 | |
| 			serviceReqDurationHistogram = append(serviceReqDurationHistogram, r.ServiceReqDurationHistogram())
 | |
| 		}
 | |
| 		if r.ServiceRetriesCounter() != nil {
 | |
| 			serviceRetriesCounter = append(serviceRetriesCounter, r.ServiceRetriesCounter())
 | |
| 		}
 | |
| 		if r.ServiceServerUpGauge() != nil {
 | |
| 			serviceServerUpGauge = append(serviceServerUpGauge, r.ServiceServerUpGauge())
 | |
| 		}
 | |
| 		if r.ServiceReqsBytesCounter() != nil {
 | |
| 			serviceReqsBytesCounter = append(serviceReqsBytesCounter, r.ServiceReqsBytesCounter())
 | |
| 		}
 | |
| 		if r.ServiceRespsBytesCounter() != nil {
 | |
| 			serviceRespsBytesCounter = append(serviceRespsBytesCounter, r.ServiceRespsBytesCounter())
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return &standardRegistry{
 | |
| 		epEnabled:                      len(entryPointReqsCounter) > 0 || len(entryPointReqDurationHistogram) > 0,
 | |
| 		svcEnabled:                     len(serviceReqsCounter) > 0 || len(serviceReqDurationHistogram) > 0 || len(serviceRetriesCounter) > 0 || len(serviceServerUpGauge) > 0,
 | |
| 		routerEnabled:                  len(routerReqsCounter) > 0 || len(routerReqDurationHistogram) > 0,
 | |
| 		configReloadsCounter:           multi.NewCounter(configReloadsCounter...),
 | |
| 		lastConfigReloadSuccessGauge:   multi.NewGauge(lastConfigReloadSuccessGauge...),
 | |
| 		openConnectionsGauge:           multi.NewGauge(openConnectionsGauge...),
 | |
| 		tlsCertsNotAfterTimestampGauge: multi.NewGauge(tlsCertsNotAfterTimestampGauge...),
 | |
| 		entryPointReqsCounter:          NewMultiCounterWithHeaders(entryPointReqsCounter...),
 | |
| 		entryPointReqsTLSCounter:       multi.NewCounter(entryPointReqsTLSCounter...),
 | |
| 		entryPointReqDurationHistogram: MultiHistogram(entryPointReqDurationHistogram),
 | |
| 		entryPointReqsBytesCounter:     multi.NewCounter(entryPointReqsBytesCounter...),
 | |
| 		entryPointRespsBytesCounter:    multi.NewCounter(entryPointRespsBytesCounter...),
 | |
| 		routerReqsCounter:              NewMultiCounterWithHeaders(routerReqsCounter...),
 | |
| 		routerReqsTLSCounter:           multi.NewCounter(routerReqsTLSCounter...),
 | |
| 		routerReqDurationHistogram:     MultiHistogram(routerReqDurationHistogram),
 | |
| 		routerReqsBytesCounter:         multi.NewCounter(routerReqsBytesCounter...),
 | |
| 		routerRespsBytesCounter:        multi.NewCounter(routerRespsBytesCounter...),
 | |
| 		serviceReqsCounter:             NewMultiCounterWithHeaders(serviceReqsCounter...),
 | |
| 		serviceReqsTLSCounter:          multi.NewCounter(serviceReqsTLSCounter...),
 | |
| 		serviceReqDurationHistogram:    MultiHistogram(serviceReqDurationHistogram),
 | |
| 		serviceRetriesCounter:          multi.NewCounter(serviceRetriesCounter...),
 | |
| 		serviceServerUpGauge:           multi.NewGauge(serviceServerUpGauge...),
 | |
| 		serviceReqsBytesCounter:        multi.NewCounter(serviceReqsBytesCounter...),
 | |
| 		serviceRespsBytesCounter:       multi.NewCounter(serviceRespsBytesCounter...),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type standardRegistry struct {
 | |
| 	epEnabled                      bool
 | |
| 	routerEnabled                  bool
 | |
| 	svcEnabled                     bool
 | |
| 	configReloadsCounter           metrics.Counter
 | |
| 	lastConfigReloadSuccessGauge   metrics.Gauge
 | |
| 	openConnectionsGauge           metrics.Gauge
 | |
| 	tlsCertsNotAfterTimestampGauge metrics.Gauge
 | |
| 	entryPointReqsCounter          CounterWithHeaders
 | |
| 	entryPointReqsTLSCounter       metrics.Counter
 | |
| 	entryPointReqDurationHistogram ScalableHistogram
 | |
| 	entryPointReqsBytesCounter     metrics.Counter
 | |
| 	entryPointRespsBytesCounter    metrics.Counter
 | |
| 	routerReqsCounter              CounterWithHeaders
 | |
| 	routerReqsTLSCounter           metrics.Counter
 | |
| 	routerReqDurationHistogram     ScalableHistogram
 | |
| 	routerReqsBytesCounter         metrics.Counter
 | |
| 	routerRespsBytesCounter        metrics.Counter
 | |
| 	serviceReqsCounter             CounterWithHeaders
 | |
| 	serviceReqsTLSCounter          metrics.Counter
 | |
| 	serviceReqDurationHistogram    ScalableHistogram
 | |
| 	serviceRetriesCounter          metrics.Counter
 | |
| 	serviceServerUpGauge           metrics.Gauge
 | |
| 	serviceReqsBytesCounter        metrics.Counter
 | |
| 	serviceRespsBytesCounter       metrics.Counter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) IsEpEnabled() bool {
 | |
| 	return r.epEnabled
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) IsRouterEnabled() bool {
 | |
| 	return r.routerEnabled
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) IsSvcEnabled() bool {
 | |
| 	return r.svcEnabled
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) ConfigReloadsCounter() metrics.Counter {
 | |
| 	return r.configReloadsCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) LastConfigReloadSuccessGauge() metrics.Gauge {
 | |
| 	return r.lastConfigReloadSuccessGauge
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) OpenConnectionsGauge() metrics.Gauge {
 | |
| 	return r.openConnectionsGauge
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) TLSCertsNotAfterTimestampGauge() metrics.Gauge {
 | |
| 	return r.tlsCertsNotAfterTimestampGauge
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) EntryPointReqsCounter() CounterWithHeaders {
 | |
| 	return r.entryPointReqsCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) EntryPointReqsTLSCounter() metrics.Counter {
 | |
| 	return r.entryPointReqsTLSCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) EntryPointReqDurationHistogram() ScalableHistogram {
 | |
| 	return r.entryPointReqDurationHistogram
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) EntryPointReqsBytesCounter() metrics.Counter {
 | |
| 	return r.entryPointReqsBytesCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) EntryPointRespsBytesCounter() metrics.Counter {
 | |
| 	return r.entryPointRespsBytesCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) RouterReqsCounter() CounterWithHeaders {
 | |
| 	return r.routerReqsCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) RouterReqsTLSCounter() metrics.Counter {
 | |
| 	return r.routerReqsTLSCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) RouterReqDurationHistogram() ScalableHistogram {
 | |
| 	return r.routerReqDurationHistogram
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) RouterReqsBytesCounter() metrics.Counter {
 | |
| 	return r.routerReqsBytesCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) RouterRespsBytesCounter() metrics.Counter {
 | |
| 	return r.routerRespsBytesCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) ServiceReqsCounter() CounterWithHeaders {
 | |
| 	return r.serviceReqsCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) ServiceReqsTLSCounter() metrics.Counter {
 | |
| 	return r.serviceReqsTLSCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) ServiceReqDurationHistogram() ScalableHistogram {
 | |
| 	return r.serviceReqDurationHistogram
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) ServiceRetriesCounter() metrics.Counter {
 | |
| 	return r.serviceRetriesCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) ServiceServerUpGauge() metrics.Gauge {
 | |
| 	return r.serviceServerUpGauge
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) ServiceReqsBytesCounter() metrics.Counter {
 | |
| 	return r.serviceReqsBytesCounter
 | |
| }
 | |
| 
 | |
| func (r *standardRegistry) ServiceRespsBytesCounter() metrics.Counter {
 | |
| 	return r.serviceRespsBytesCounter
 | |
| }
 | |
| 
 | |
| // ScalableHistogram is a Histogram with a predefined time unit,
 | |
| // used when producing observations without explicitly setting the observed value.
 | |
| type ScalableHistogram interface {
 | |
| 	With(labelValues ...string) ScalableHistogram
 | |
| 	Observe(v float64)
 | |
| 	ObserveFromStart(start time.Time)
 | |
| }
 | |
| 
 | |
| // HistogramWithScale is a histogram that will convert its observed value to the specified unit.
 | |
| type HistogramWithScale struct {
 | |
| 	histogram metrics.Histogram
 | |
| 	unit      time.Duration
 | |
| }
 | |
| 
 | |
| // With implements ScalableHistogram.
 | |
| func (s *HistogramWithScale) With(labelValues ...string) ScalableHistogram {
 | |
| 	h, _ := NewHistogramWithScale(s.histogram.With(labelValues...), s.unit)
 | |
| 	return h
 | |
| }
 | |
| 
 | |
| // ObserveFromStart implements ScalableHistogram.
 | |
| func (s *HistogramWithScale) ObserveFromStart(start time.Time) {
 | |
| 	if s.unit <= 0 {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	d := float64(time.Since(start).Nanoseconds()) / float64(s.unit)
 | |
| 	if d < 0 {
 | |
| 		d = 0
 | |
| 	}
 | |
| 	s.histogram.Observe(d)
 | |
| }
 | |
| 
 | |
| // Observe implements ScalableHistogram.
 | |
| func (s *HistogramWithScale) Observe(v float64) {
 | |
| 	s.histogram.Observe(v)
 | |
| }
 | |
| 
 | |
| // NewHistogramWithScale returns a ScalableHistogram. It returns an error if the given unit is <= 0.
 | |
| func NewHistogramWithScale(histogram metrics.Histogram, unit time.Duration) (ScalableHistogram, error) {
 | |
| 	if unit <= 0 {
 | |
| 		return nil, errors.New("invalid time unit")
 | |
| 	}
 | |
| 	return &HistogramWithScale{
 | |
| 		histogram: histogram,
 | |
| 		unit:      unit,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| // MultiHistogram collects multiple individual histograms and treats them as a unit.
 | |
| type MultiHistogram []ScalableHistogram
 | |
| 
 | |
| // ObserveFromStart implements ScalableHistogram.
 | |
| func (h MultiHistogram) ObserveFromStart(start time.Time) {
 | |
| 	for _, histogram := range h {
 | |
| 		histogram.ObserveFromStart(start)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Observe implements ScalableHistogram.
 | |
| func (h MultiHistogram) Observe(v float64) {
 | |
| 	for _, histogram := range h {
 | |
| 		histogram.Observe(v)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // With implements ScalableHistogram.
 | |
| func (h MultiHistogram) With(labelValues ...string) ScalableHistogram {
 | |
| 	next := make(MultiHistogram, len(h))
 | |
| 	for i := range h {
 | |
| 		next[i] = h[i].With(labelValues...)
 | |
| 	}
 | |
| 	return next
 | |
| }
 |