From 18203f57d2bd5d2f48ab443a227927bef6e1b86e Mon Sep 17 00:00:00 2001 From: Liam van der Viven <62619917+liamvdv@users.noreply.github.com> Date: Mon, 29 Jan 2024 17:08:05 +0100 Subject: [PATCH] Add support for sending DogStatsD metrics over Unix Socket --- docs/content/observability/metrics/datadog.md | 2 + docs/mkdocs.yml | 4 ++ pkg/metrics/datadog.go | 27 ++++++++++--- pkg/metrics/datadog_test.go | 39 +++++++++++++++++++ 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/docs/content/observability/metrics/datadog.md b/docs/content/observability/metrics/datadog.md index 00a5d6c9f..134b726df 100644 --- a/docs/content/observability/metrics/datadog.md +++ b/docs/content/observability/metrics/datadog.md @@ -27,6 +27,8 @@ _Required, Default="127.0.0.1:8125"_ Address instructs exporter to send metrics to datadog-agent at this address. +This address can be a Unix Domain Socket (UDS) address with the following form: `unix:///path/to/datadog.socket`. + ```yaml tab="File (YAML)" metrics: datadog: diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 6ba875a3f..0b7ffaa2c 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -153,7 +153,11 @@ nav: - 'Access Logs': 'observability/access-logs.md' - 'Metrics': - 'Overview': 'observability/metrics/overview.md' + - 'Datadog': 'observability/metrics/datadog.md' + - 'InfluxDB2': 'observability/metrics/influxdb2.md' - 'OpenTelemetry': 'observability/metrics/opentelemetry.md' + - 'Prometheus': 'observability/metrics/prometheus.md' + - 'StatsD': 'observability/metrics/statsd.md' - 'Tracing': - 'Overview': 'observability/tracing/overview.md' - 'OpenTelemetry': 'observability/tracing/opentelemetry.md' diff --git a/pkg/metrics/datadog.go b/pkg/metrics/datadog.go index b09e3407a..fcb8be6d2 100644 --- a/pkg/metrics/datadog.go +++ b/pkg/metrics/datadog.go @@ -2,6 +2,7 @@ package metrics import ( "context" + "strings" "time" "github.com/go-kit/kit/metrics/dogstatsd" @@ -16,6 +17,8 @@ var ( datadogLoopCancelFunc context.CancelFunc ) +const unixAddressPrefix = "unix://" + // Metric names consistent with https://github.com/DataDog/integrations-extras/pull/64 const ( ddConfigReloadsName = "config.reload.total" @@ -99,10 +102,7 @@ func RegisterDatadog(ctx context.Context, config *types.Datadog) Registry { } func initDatadogClient(ctx context.Context, config *types.Datadog) { - address := config.Address - if len(address) == 0 { - address = "localhost:8125" - } + network, address := parseDatadogAddress(config.Address) ctx, datadogLoopCancelFunc = context.WithCancel(ctx) @@ -110,10 +110,27 @@ func initDatadogClient(ctx context.Context, config *types.Datadog) { ticker := time.NewTicker(time.Duration(config.PushInterval)) defer ticker.Stop() - datadogClient.SendLoop(ctx, ticker.C, "udp", address) + datadogClient.SendLoop(ctx, ticker.C, network, address) }) } +func parseDatadogAddress(address string) (string, string) { + network := "udp" + + var addr string + switch { + case strings.HasPrefix(address, unixAddressPrefix): + network = "unix" + addr = address[len(unixAddressPrefix):] + case address != "": + addr = address + default: + addr = "localhost:8125" + } + + return network, addr +} + // StopDatadog stops the Datadog metrics pusher. func StopDatadog() { if datadogLoopCancelFunc != nil { diff --git a/pkg/metrics/datadog_test.go b/pkg/metrics/datadog_test.go index 6a53bf065..cd4b99433 100644 --- a/pkg/metrics/datadog_test.go +++ b/pkg/metrics/datadog_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stvp/go-udp-testing" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v3/pkg/types" @@ -39,6 +40,44 @@ func TestDatadogWithPrefix(t *testing.T) { testDatadogRegistry(t, "testPrefix", datadogRegistry) } +func TestDatadog_parseDatadogAddress(t *testing.T) { + tests := []struct { + desc string + address string + expNetwork string + expAddress string + }{ + { + desc: "empty address", + expNetwork: "udp", + expAddress: "localhost:8125", + }, + { + desc: "udp address", + address: "127.0.0.1:8080", + expNetwork: "udp", + expAddress: "127.0.0.1:8080", + }, + { + desc: "unix address", + address: "unix:///path/to/datadog.socket", + expNetwork: "unix", + expAddress: "/path/to/datadog.socket", + }, + } + + for _, test := range tests { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + gotNetwork, gotAddress := parseDatadogAddress(test.address) + assert.Equal(t, test.expNetwork, gotNetwork) + assert.Equal(t, test.expAddress, gotAddress) + }) + } +} + func testDatadogRegistry(t *testing.T, metricsPrefix string, datadogRegistry Registry) { t.Helper()