2017-08-23 20:46:03 +02:00
package metrics
import (
2018-11-14 10:18:03 +01:00
"context"
2017-08-23 20:46:03 +02:00
"time"
"github.com/go-kit/kit/metrics/dogstatsd"
2024-07-19 14:52:04 +02:00
kitlog "github.com/go-kit/log"
2020-09-16 15:46:04 +02: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 20:46:03 +02:00
)
2021-10-06 09:34:07 -06:00
var (
2022-06-29 10:34:08 +02:00
datadogClient * dogstatsd . Dogstatsd
datadogLoopCancelFunc context . CancelFunc
2021-10-06 09:34:07 -06:00
)
2017-08-23 20:46:03 +02:00
// Metric names consistent with https://github.com/DataDog/integrations-extras/pull/64
const (
2020-12-18 18:44:03 +01:00
ddConfigReloadsName = "config.reload.total"
ddConfigReloadsFailureTagName = "failure"
ddLastConfigReloadSuccessName = "config.reload.lastSuccessTimestamp"
ddLastConfigReloadFailureName = "config.reload.lastFailureTimestamp"
ddTLSCertsNotAfterTimestampName = "tls.certs.notAfterTimestamp"
2021-04-30 10:22:04 +02:00
ddEntryPointReqsName = "entrypoint.request.total"
ddEntryPointReqsTLSName = "entrypoint.request.tls.total"
ddEntryPointReqDurationName = "entrypoint.request.duration"
ddEntryPointOpenConnsName = "entrypoint.connections.open"
2022-09-12 17:10:09 +02:00
ddEntryPointReqsBytesName = "entrypoint.requests.bytes.total"
ddEntryPointRespsBytesName = "entrypoint.responses.bytes.total"
ddRouterReqsName = "router.request.total"
ddRouterReqsTLSName = "router.request.tls.total"
ddRouterReqsDurationName = "router.request.duration"
ddRouterOpenConnsName = "router.connections.open"
ddRouterReqsBytesName = "router.requests.bytes.total"
ddRouterRespsBytesName = "router.responses.bytes.total"
ddServiceReqsName = "service.request.total"
ddServiceReqsTLSName = "service.request.tls.total"
ddServiceReqsDurationName = "service.request.duration"
ddServiceRetriesName = "service.retries.total"
ddServiceOpenConnsName = "service.connections.open"
ddServiceServerUpName = "service.server.up"
ddServiceReqsBytesName = "service.requests.bytes.total"
ddServiceRespsBytesName = "service.responses.bytes.total"
2017-08-23 20:46:03 +02:00
)
// RegisterDatadog registers the metrics pusher if this didn't happen yet and creates a datadog Registry instance.
2019-09-02 12:18:04 +02:00
func RegisterDatadog ( ctx context . Context , config * types . Datadog ) Registry {
2022-06-29 10:34:08 +02:00
// Ensures there is only one DataDog client sending metrics at any given time.
StopDatadog ( )
2021-10-06 09:34:07 -06:00
// just to be sure there is a prefix defined
if config . Prefix == "" {
config . Prefix = defaultMetricsPrefix
}
datadogClient = dogstatsd . New ( config . Prefix + "." , kitlog . LoggerFunc ( func ( keyvals ... interface { } ) error {
2022-07-19 18:38:09 +02:00
log . WithoutContext ( ) . WithField ( log . MetricsProviderName , "datadog" ) . Info ( keyvals ... )
2021-10-06 09:34:07 -06:00
return nil
} ) )
2022-06-29 10:34:08 +02:00
initDatadogClient ( ctx , config )
2017-08-23 20:46:03 +02:00
registry := & standardRegistry {
2020-12-18 18:44:03 +01:00
configReloadsCounter : datadogClient . NewCounter ( ddConfigReloadsName , 1.0 ) ,
configReloadsFailureCounter : datadogClient . NewCounter ( ddConfigReloadsName , 1.0 ) . With ( ddConfigReloadsFailureTagName , "true" ) ,
lastConfigReloadSuccessGauge : datadogClient . NewGauge ( ddLastConfigReloadSuccessName ) ,
lastConfigReloadFailureGauge : datadogClient . NewGauge ( ddLastConfigReloadFailureName ) ,
tlsCertsNotAfterTimestampGauge : datadogClient . NewGauge ( ddTLSCertsNotAfterTimestampName ) ,
2019-07-18 21:36:05 +02:00
}
if config . AddEntryPointsLabels {
registry . epEnabled = config . AddEntryPointsLabels
2023-03-20 18:06:07 +01:00
registry . entryPointReqsCounter = NewCounterWithNoopHeaders ( datadogClient . NewCounter ( ddEntryPointReqsName , 1.0 ) )
2021-04-30 10:22:04 +02:00
registry . entryPointReqsTLSCounter = datadogClient . NewCounter ( ddEntryPointReqsTLSName , 1.0 )
2020-03-05 15:10:07 +01:00
registry . entryPointReqDurationHistogram , _ = NewHistogramWithScale ( datadogClient . NewHistogram ( ddEntryPointReqDurationName , 1.0 ) , time . Second )
2019-07-18 21:36:05 +02:00
registry . entryPointOpenConnsGauge = datadogClient . NewGauge ( ddEntryPointOpenConnsName )
2022-09-12 17:10:09 +02:00
registry . entryPointReqsBytesCounter = datadogClient . NewCounter ( ddEntryPointReqsBytesName , 1.0 )
registry . entryPointRespsBytesCounter = datadogClient . NewCounter ( ddEntryPointRespsBytesName , 1.0 )
2019-07-18 21:36:05 +02:00
}
2021-04-30 10:22:04 +02:00
if config . AddRoutersLabels {
registry . routerEnabled = config . AddRoutersLabels
2023-03-20 18:06:07 +01:00
registry . routerReqsCounter = NewCounterWithNoopHeaders ( datadogClient . NewCounter ( ddRouterReqsName , 1.0 ) )
2022-09-12 17:10:09 +02:00
registry . routerReqsTLSCounter = datadogClient . NewCounter ( ddRouterReqsTLSName , 1.0 )
registry . routerReqDurationHistogram , _ = NewHistogramWithScale ( datadogClient . NewHistogram ( ddRouterReqsDurationName , 1.0 ) , time . Second )
2021-04-30 10:22:04 +02:00
registry . routerOpenConnsGauge = datadogClient . NewGauge ( ddRouterOpenConnsName )
2022-09-12 17:10:09 +02:00
registry . routerReqsBytesCounter = datadogClient . NewCounter ( ddRouterReqsBytesName , 1.0 )
registry . routerRespsBytesCounter = datadogClient . NewCounter ( ddRouterRespsBytesName , 1.0 )
2021-04-30 10:22:04 +02:00
}
2019-07-18 21:36:05 +02:00
if config . AddServicesLabels {
registry . svcEnabled = config . AddServicesLabels
2023-03-20 18:06:07 +01:00
registry . serviceReqsCounter = NewCounterWithNoopHeaders ( datadogClient . NewCounter ( ddServiceReqsName , 1.0 ) )
2022-09-12 17:10:09 +02:00
registry . serviceReqsTLSCounter = datadogClient . NewCounter ( ddServiceReqsTLSName , 1.0 )
registry . serviceReqDurationHistogram , _ = NewHistogramWithScale ( datadogClient . NewHistogram ( ddServiceReqsDurationName , 1.0 ) , time . Second )
registry . serviceRetriesCounter = datadogClient . NewCounter ( ddServiceRetriesName , 1.0 )
registry . serviceOpenConnsGauge = datadogClient . NewGauge ( ddServiceOpenConnsName )
registry . serviceServerUpGauge = datadogClient . NewGauge ( ddServiceServerUpName )
registry . serviceReqsBytesCounter = datadogClient . NewCounter ( ddServiceReqsBytesName , 1.0 )
registry . serviceRespsBytesCounter = datadogClient . NewCounter ( ddServiceRespsBytesName , 1.0 )
2017-08-23 20:46:03 +02:00
}
return registry
}
2022-06-29 10:34:08 +02:00
func initDatadogClient ( ctx context . Context , config * types . Datadog ) {
2017-08-23 20:46:03 +02:00
address := config . Address
if len ( address ) == 0 {
address = "localhost:8125"
}
2022-06-29 10:34:08 +02:00
ctx , datadogLoopCancelFunc = context . WithCancel ( ctx )
2017-08-23 20:46:03 +02:00
safe . Go ( func ( ) {
2022-06-29 10:34:08 +02:00
ticker := time . NewTicker ( time . Duration ( config . PushInterval ) )
defer ticker . Stop ( )
2017-08-23 20:46:03 +02:00
2022-06-29 10:34:08 +02:00
datadogClient . SendLoop ( ctx , ticker . C , "udp" , address )
} )
2017-08-23 20:46:03 +02:00
}
2022-06-29 10:34:08 +02:00
// StopDatadog stops the Datadog metrics pusher.
2017-08-23 20:46:03 +02:00
func StopDatadog ( ) {
2022-06-29 10:34:08 +02:00
if datadogLoopCancelFunc != nil {
datadogLoopCancelFunc ( )
datadogLoopCancelFunc = nil
2017-08-23 20:46:03 +02:00
}
}