2017-08-23 21:46:03 +03:00
package metrics
import (
2018-11-14 12:18:03 +03:00
"context"
2017-08-23 21:46:03 +03:00
"time"
kitlog "github.com/go-kit/kit/log"
"github.com/go-kit/kit/metrics/statsd"
2020-09-16 16:46:04 +03:00
"github.com/traefik/traefik/v2/pkg/log"
"github.com/traefik/traefik/v2/pkg/safe"
"github.com/traefik/traefik/v2/pkg/types"
2017-08-23 21:46:03 +03:00
)
2020-07-07 15:42:03 +03:00
var (
statsdClient * statsd . Statsd
statsdTicker * time . Ticker
)
2017-08-23 21:46:03 +03:00
2017-11-08 17:14:03 +03:00
const (
2021-04-30 11:22:04 +03:00
statsdConfigReloadsName = "config.reload.total"
statsdConfigReloadsFailureName = statsdConfigReloadsName + ".failure"
statsdLastConfigReloadSuccessName = "config.reload.lastSuccessTimestamp"
statsdLastConfigReloadFailureName = "config.reload.lastFailureTimestamp"
2020-12-18 20:44:03 +03:00
statsdTLSCertsNotAfterTimestampName = "tls.certs.notAfterTimestamp"
2021-04-30 11:22:04 +03:00
statsdEntryPointReqsName = "entrypoint.request.total"
statsdEntryPointReqsTLSName = "entrypoint.request.tls.total"
statsdEntryPointReqDurationName = "entrypoint.request.duration"
statsdEntryPointOpenConnsName = "entrypoint.connections.open"
statsdRouterReqsName = "router.request.total"
statsdRouterReqsTLSName = "router.request.tls.total"
statsdRouterReqsDurationName = "router.request.duration"
statsdRouterOpenConnsName = "router.connections.open"
statsdServiceReqsName = "service.request.total"
statsdServiceReqsTLSName = "service.request.tls.total"
statsdServiceReqsDurationName = "service.request.duration"
statsdServiceRetriesTotalName = "service.retries.total"
statsdServiceServerUpName = "service.server.up"
statsdServiceOpenConnsName = "service.connections.open"
2017-11-08 17:14:03 +03:00
)
2017-08-23 21:46:03 +03:00
// RegisterStatsd registers the metrics pusher if this didn't happen yet and creates a statsd Registry instance.
2018-11-14 12:18:03 +03:00
func RegisterStatsd ( ctx context . Context , config * types . Statsd ) Registry {
2019-11-12 20:18:04 +03:00
// just to be sure there is a prefix defined
if config . Prefix == "" {
2021-10-06 18:34:07 +03:00
config . Prefix = defaultMetricsPrefix
2019-11-12 20:18:04 +03:00
}
statsdClient = statsd . New ( config . Prefix + "." , kitlog . LoggerFunc ( func ( keyvals ... interface { } ) error {
2022-07-19 19:38:09 +03:00
log . WithoutContext ( ) . WithField ( log . MetricsProviderName , "statsd" ) . Info ( keyvals ... )
2019-11-12 20:18:04 +03:00
return nil
} ) )
2017-08-23 21:46:03 +03:00
if statsdTicker == nil {
2018-11-14 12:18:03 +03:00
statsdTicker = initStatsdTicker ( ctx , config )
2017-08-23 21:46:03 +03:00
}
2019-07-18 22:36:05 +03:00
registry := & standardRegistry {
2020-12-18 20:44:03 +03:00
configReloadsCounter : statsdClient . NewCounter ( statsdConfigReloadsName , 1.0 ) ,
configReloadsFailureCounter : statsdClient . NewCounter ( statsdConfigReloadsFailureName , 1.0 ) ,
lastConfigReloadSuccessGauge : statsdClient . NewGauge ( statsdLastConfigReloadSuccessName ) ,
lastConfigReloadFailureGauge : statsdClient . NewGauge ( statsdLastConfigReloadFailureName ) ,
tlsCertsNotAfterTimestampGauge : statsdClient . NewGauge ( statsdTLSCertsNotAfterTimestampName ) ,
2017-08-23 21:46:03 +03:00
}
2019-07-18 22:36:05 +03:00
if config . AddEntryPointsLabels {
registry . epEnabled = config . AddEntryPointsLabels
registry . entryPointReqsCounter = statsdClient . NewCounter ( statsdEntryPointReqsName , 1.0 )
2021-04-30 11:22:04 +03:00
registry . entryPointReqsTLSCounter = statsdClient . NewCounter ( statsdEntryPointReqsTLSName , 1.0 )
2020-03-05 17:10:07 +03:00
registry . entryPointReqDurationHistogram , _ = NewHistogramWithScale ( statsdClient . NewTiming ( statsdEntryPointReqDurationName , 1.0 ) , time . Millisecond )
2019-07-18 22:36:05 +03:00
registry . entryPointOpenConnsGauge = statsdClient . NewGauge ( statsdEntryPointOpenConnsName )
}
2021-04-30 11:22:04 +03:00
if config . AddRoutersLabels {
registry . routerEnabled = config . AddRoutersLabels
registry . routerReqsCounter = statsdClient . NewCounter ( statsdRouterReqsName , 1.0 )
registry . routerReqsTLSCounter = statsdClient . NewCounter ( statsdRouterReqsTLSName , 1.0 )
registry . routerReqDurationHistogram , _ = NewHistogramWithScale ( statsdClient . NewTiming ( statsdRouterReqsDurationName , 1.0 ) , time . Millisecond )
registry . routerOpenConnsGauge = statsdClient . NewGauge ( statsdRouterOpenConnsName )
}
2019-07-18 22:36:05 +03:00
if config . AddServicesLabels {
registry . svcEnabled = config . AddServicesLabels
2021-04-30 11:22:04 +03:00
registry . serviceReqsCounter = statsdClient . NewCounter ( statsdServiceReqsName , 1.0 )
registry . serviceReqsTLSCounter = statsdClient . NewCounter ( statsdServiceReqsTLSName , 1.0 )
registry . serviceReqDurationHistogram , _ = NewHistogramWithScale ( statsdClient . NewTiming ( statsdServiceReqsDurationName , 1.0 ) , time . Millisecond )
registry . serviceRetriesCounter = statsdClient . NewCounter ( statsdServiceRetriesTotalName , 1.0 )
registry . serviceOpenConnsGauge = statsdClient . NewGauge ( statsdServiceOpenConnsName )
registry . serviceServerUpGauge = statsdClient . NewGauge ( statsdServiceServerUpName )
2019-07-18 22:36:05 +03:00
}
return registry
2017-08-23 21:46:03 +03:00
}
2020-05-11 13:06:07 +03:00
// initStatsdTicker initializes metrics pusher and creates a statsdClient if not created already.
2018-11-14 12:18:03 +03:00
func initStatsdTicker ( ctx context . Context , config * types . Statsd ) * time . Ticker {
2017-08-23 21:46:03 +03:00
address := config . Address
if len ( address ) == 0 {
address = "localhost:8125"
}
2019-06-17 12:48:05 +03:00
report := time . NewTicker ( time . Duration ( config . PushInterval ) )
2017-08-23 21:46:03 +03:00
safe . Go ( func ( ) {
2019-07-18 22:36:05 +03:00
statsdClient . SendLoop ( ctx , report . C , "udp" , address )
2017-08-23 21:46:03 +03:00
} )
return report
}
2020-05-11 13:06:07 +03:00
// StopStatsd stops internal statsdTicker which controls the pushing of metrics to StatsD Agent and resets it to `nil`.
2017-08-23 21:46:03 +03:00
func StopStatsd ( ) {
if statsdTicker != nil {
statsdTicker . Stop ( )
}
statsdTicker = nil
}