traefik/pkg/metrics/metrics.go

382 lines
14 KiB
Go
Raw Normal View History

package metrics
import (
"errors"
"time"
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/metrics/multi"
)
2021-10-06 15:34:07 +00:00
const defaultMetricsPrefix = "traefik"
// Registry has to implemented by any system that wants to monitor and expose metrics.
type Registry interface {
2019-07-18 19:36:05 +00:00
// IsEpEnabled shows whether metrics instrumentation is enabled on entry points.
IsEpEnabled() bool
2021-04-30 08:22:04 +00:00
// IsRouterEnabled shows whether metrics instrumentation is enabled on routers.
IsRouterEnabled() bool
2019-07-18 19:36:05 +00:00
// IsSvcEnabled shows whether metrics instrumentation is enabled on services.
IsSvcEnabled() bool
2018-07-03 08:02:03 +00:00
// server metrics
2022-08-31 06:24:08 +00:00
ConfigReloadsCounter() metrics.Counter
LastConfigReloadSuccessGauge() metrics.Gauge
OpenConnectionsGauge() metrics.Gauge
2020-12-18 17:44:03 +00:00
// TLS
2022-08-31 06:24:08 +00:00
2020-12-18 17:44:03 +00:00
TLSCertsNotAfterTimestampGauge() metrics.Gauge
// entry point metrics
2022-08-31 06:24:08 +00:00
EntryPointReqsCounter() CounterWithHeaders
2020-03-05 12:30:05 +00:00
EntryPointReqsTLSCounter() metrics.Counter
EntryPointReqDurationHistogram() ScalableHistogram
EntryPointReqsBytesCounter() metrics.Counter
EntryPointRespsBytesCounter() metrics.Counter
2021-04-30 08:22:04 +00:00
// router metrics
2022-08-31 06:24:08 +00:00
RouterReqsCounter() CounterWithHeaders
2021-04-30 08:22:04 +00:00
RouterReqsTLSCounter() metrics.Counter
RouterReqDurationHistogram() ScalableHistogram
RouterReqsBytesCounter() metrics.Counter
RouterRespsBytesCounter() metrics.Counter
2021-04-30 08:22:04 +00:00
2019-07-18 19:36:05 +00:00
// service metrics
2022-08-31 06:24:08 +00:00
ServiceReqsCounter() CounterWithHeaders
2020-03-05 12:30:05 +00:00
ServiceReqsTLSCounter() metrics.Counter
ServiceReqDurationHistogram() ScalableHistogram
2019-07-18 19:36:05 +00:00
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 {
2018-07-03 08:02:03 +00:00
var configReloadsCounter []metrics.Counter
var lastConfigReloadSuccessGauge []metrics.Gauge
var openConnectionsGauge []metrics.Gauge
2020-12-18 17:44:03 +00:00
var tlsCertsNotAfterTimestampGauge []metrics.Gauge
var entryPointReqsCounter []CounterWithHeaders
2020-03-05 12:30:05 +00:00
var entryPointReqsTLSCounter []metrics.Counter
var entryPointReqDurationHistogram []ScalableHistogram
var entryPointReqsBytesCounter []metrics.Counter
var entryPointRespsBytesCounter []metrics.Counter
var routerReqsCounter []CounterWithHeaders
2021-04-30 08:22:04 +00:00
var routerReqsTLSCounter []metrics.Counter
var routerReqDurationHistogram []ScalableHistogram
var routerReqsBytesCounter []metrics.Counter
var routerRespsBytesCounter []metrics.Counter
var serviceReqsCounter []CounterWithHeaders
2020-03-05 12:30:05 +00:00
var serviceReqsTLSCounter []metrics.Counter
var serviceReqDurationHistogram []ScalableHistogram
2019-07-18 19:36:05 +00:00
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())
}
2020-12-18 17:44:03 +00:00
if r.TLSCertsNotAfterTimestampGauge() != nil {
tlsCertsNotAfterTimestampGauge = append(tlsCertsNotAfterTimestampGauge, r.TLSCertsNotAfterTimestampGauge())
}
2019-07-18 19:36:05 +00:00
if r.EntryPointReqsCounter() != nil {
entryPointReqsCounter = append(entryPointReqsCounter, r.EntryPointReqsCounter())
}
2020-03-05 12:30:05 +00:00
if r.EntryPointReqsTLSCounter() != nil {
entryPointReqsTLSCounter = append(entryPointReqsTLSCounter, r.EntryPointReqsTLSCounter())
}
2019-07-18 19:36:05 +00:00
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())
}
2021-04-30 08:22:04 +00:00
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())
}
2019-07-18 19:36:05 +00:00
if r.ServiceReqsCounter() != nil {
serviceReqsCounter = append(serviceReqsCounter, r.ServiceReqsCounter())
}
2020-03-05 12:30:05 +00:00
if r.ServiceReqsTLSCounter() != nil {
serviceReqsTLSCounter = append(serviceReqsTLSCounter, r.ServiceReqsTLSCounter())
}
2019-07-18 19:36:05 +00:00
if r.ServiceReqDurationHistogram() != nil {
serviceReqDurationHistogram = append(serviceReqDurationHistogram, r.ServiceReqDurationHistogram())
}
2019-07-18 19:36:05 +00:00
if r.ServiceRetriesCounter() != nil {
serviceRetriesCounter = append(serviceRetriesCounter, r.ServiceRetriesCounter())
}
2019-07-18 19:36:05 +00:00
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...),
2020-12-18 17:44:03 +00:00
tlsCertsNotAfterTimestampGauge: multi.NewGauge(tlsCertsNotAfterTimestampGauge...),
entryPointReqsCounter: NewMultiCounterWithHeaders(entryPointReqsCounter...),
2020-03-05 12:30:05 +00:00
entryPointReqsTLSCounter: multi.NewCounter(entryPointReqsTLSCounter...),
entryPointReqDurationHistogram: MultiHistogram(entryPointReqDurationHistogram),
entryPointReqsBytesCounter: multi.NewCounter(entryPointReqsBytesCounter...),
entryPointRespsBytesCounter: multi.NewCounter(entryPointRespsBytesCounter...),
routerReqsCounter: NewMultiCounterWithHeaders(routerReqsCounter...),
2021-04-30 08:22:04 +00:00
routerReqsTLSCounter: multi.NewCounter(routerReqsTLSCounter...),
routerReqDurationHistogram: MultiHistogram(routerReqDurationHistogram),
routerReqsBytesCounter: multi.NewCounter(routerReqsBytesCounter...),
routerRespsBytesCounter: multi.NewCounter(routerRespsBytesCounter...),
serviceReqsCounter: NewMultiCounterWithHeaders(serviceReqsCounter...),
2020-03-05 12:30:05 +00:00
serviceReqsTLSCounter: multi.NewCounter(serviceReqsTLSCounter...),
serviceReqDurationHistogram: MultiHistogram(serviceReqDurationHistogram),
2019-07-18 19:36:05 +00:00
serviceRetriesCounter: multi.NewCounter(serviceRetriesCounter...),
serviceServerUpGauge: multi.NewGauge(serviceServerUpGauge...),
serviceReqsBytesCounter: multi.NewCounter(serviceReqsBytesCounter...),
serviceRespsBytesCounter: multi.NewCounter(serviceRespsBytesCounter...),
}
}
type standardRegistry struct {
2019-07-18 19:36:05 +00:00
epEnabled bool
2021-04-30 08:22:04 +00:00
routerEnabled bool
2019-07-18 19:36:05 +00:00
svcEnabled bool
configReloadsCounter metrics.Counter
lastConfigReloadSuccessGauge metrics.Gauge
openConnectionsGauge metrics.Gauge
2020-12-18 17:44:03 +00:00
tlsCertsNotAfterTimestampGauge metrics.Gauge
entryPointReqsCounter CounterWithHeaders
2020-03-05 12:30:05 +00:00
entryPointReqsTLSCounter metrics.Counter
entryPointReqDurationHistogram ScalableHistogram
entryPointReqsBytesCounter metrics.Counter
entryPointRespsBytesCounter metrics.Counter
routerReqsCounter CounterWithHeaders
2021-04-30 08:22:04 +00:00
routerReqsTLSCounter metrics.Counter
routerReqDurationHistogram ScalableHistogram
routerReqsBytesCounter metrics.Counter
routerRespsBytesCounter metrics.Counter
serviceReqsCounter CounterWithHeaders
2020-03-05 12:30:05 +00:00
serviceReqsTLSCounter metrics.Counter
serviceReqDurationHistogram ScalableHistogram
2019-07-18 19:36:05 +00:00
serviceRetriesCounter metrics.Counter
serviceServerUpGauge metrics.Gauge
serviceReqsBytesCounter metrics.Counter
serviceRespsBytesCounter metrics.Counter
}
2019-07-18 19:36:05 +00:00
func (r *standardRegistry) IsEpEnabled() bool {
return r.epEnabled
}
2021-04-30 08:22:04 +00:00
func (r *standardRegistry) IsRouterEnabled() bool {
return r.routerEnabled
}
2019-07-18 19:36:05 +00:00
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
}
2020-12-18 17:44:03 +00:00
func (r *standardRegistry) TLSCertsNotAfterTimestampGauge() metrics.Gauge {
return r.tlsCertsNotAfterTimestampGauge
}
func (r *standardRegistry) EntryPointReqsCounter() CounterWithHeaders {
2019-07-18 19:36:05 +00:00
return r.entryPointReqsCounter
}
2020-03-05 12:30:05 +00:00
func (r *standardRegistry) EntryPointReqsTLSCounter() metrics.Counter {
return r.entryPointReqsTLSCounter
}
func (r *standardRegistry) EntryPointReqDurationHistogram() ScalableHistogram {
2019-07-18 19:36:05 +00:00
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 {
2021-04-30 08:22:04 +00:00
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 {
2019-07-18 19:36:05 +00:00
return r.serviceReqsCounter
}
2020-03-05 12:30:05 +00:00
func (r *standardRegistry) ServiceReqsTLSCounter() metrics.Counter {
return r.serviceReqsTLSCounter
}
func (r *standardRegistry) ServiceReqDurationHistogram() ScalableHistogram {
2019-07-18 19:36:05 +00:00
return r.serviceReqDurationHistogram
}
2019-07-18 19:36:05 +00:00
func (r *standardRegistry) ServiceRetriesCounter() metrics.Counter {
return r.serviceRetriesCounter
}
2019-07-18 19:36:05 +00:00
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
}