Description
The DogStatsD sink (USE_DOG_STATSD=true) does not support Unix Domain Socket addresses for STATSD_HOST. When STATSD_HOST is set to a unix:// address (as documented/expected by the underlying DataDog/datadog-go client), the sink unconditionally appends STATSD_PORT to it, producing an invalid address that never resolves to the actual socket file. All stats are silently dropped — no error is logged anywhere.
Root cause
In src/godogstats/dogstatsd_sink.go, NewSink() builds the address as:
client, err := statsd.New(sink.config.host+":"+strconv.Itoa(sink.config.port), statsd.WithoutClientSideAggregation())
This always concatenates host + ":" + port, with no check for whether host is already a complete unix://, unixgram://, or unixstream:// address (all of which are documented, supported formats for datadog-go's statsd.New).
StatsdPort (STATSD_PORT) also always defaults to 8125 (src/settings/settings.go), so even if a user doesn't set STATSD_PORT at all, it's still appended.
Example: with
STATSD_HOST=unix:///var/run/datadog/dsd.socket
(and STATSD_PORT left at its default), the resulting address passed to statsd.New is:
unix:///var/run/datadog/dsd.socket:8125
datadog-go's resolveAddr/createWriter (in statsdex.go) recognize the unix:// prefix and pass the rest of the string verbatim as the socket file path — so the writer ends up trying to connect to a socket literally named /var/run/datadog/dsd.socket:8125, which does not exist (the real file is /var/run/datadog/dsd.socket, without a port suffix).
Because datadog-go's UDS writer defers the actual connect() until the first Write() call (see uds.go, "Defer connection to first Write"), NewSink() returns no error and the service logs "Stats initialized for dogstatsd" successfully at startup. Every subsequent Write() then fails with ENOENT/"no such file or directory", but FlushCounter/FlushGauge/FlushTimer in dogstatsd_sink.go discard the error returned by client.Count()/client.Gauge()/client.Timing(), so the failure is completely silent — no logs, no metrics, no crash, no indication anything is wrong.
Expected behavior
Setting STATSD_HOST to a unix://, unixgram://, or unixstream:// address should work for DogStatsD over a Unix Domain Socket, without requiring/appending a port — matching how datadog-go's own statsd.New documents its addr parameter:
New returns a pointer to a new Client given an addr in the format "hostname:port" for UDP, "unix:///path/to/socket" for UDS or "\.\pipe\path\to\pipe" for Windows Named Pipes.
Actual behavior
STATSD_PORT is always appended to STATSD_HOST, corrupting any Unix Domain Socket address and causing all metrics to be silently dropped.
Suggested fix
In NewSink(), only append :port when host does not already look like a complete address (e.g. doesn't have a unix:///unixgram:///unixstream:// prefix or a Windows named pipe prefix), similar to how datadog-go's own resolveAddr decides whether to append a port:
addr := sink.config.host
if !hasSchemePrefix(addr) { // unix://, unixgram://, unixstream://, \\.\pipe\
addr = addr + ":" + strconv.Itoa(sink.config.port)
}
client, err := statsd.New(addr, statsd.WithoutClientSideAggregation())
Environment
Description
The DogStatsD sink (
USE_DOG_STATSD=true) does not support Unix Domain Socket addresses forSTATSD_HOST. WhenSTATSD_HOSTis set to aunix://address (as documented/expected by the underlyingDataDog/datadog-goclient), the sink unconditionally appendsSTATSD_PORTto it, producing an invalid address that never resolves to the actual socket file. All stats are silently dropped — no error is logged anywhere.Root cause
In
src/godogstats/dogstatsd_sink.go,NewSink()builds the address as:This always concatenates
host + ":" + port, with no check for whetherhostis already a completeunix://,unixgram://, orunixstream://address (all of which are documented, supported formats fordatadog-go'sstatsd.New).StatsdPort(STATSD_PORT) also always defaults to8125(src/settings/settings.go), so even if a user doesn't setSTATSD_PORTat all, it's still appended.Example: with
(and
STATSD_PORTleft at its default), the resulting address passed tostatsd.Newis:datadog-go'sresolveAddr/createWriter(instatsdex.go) recognize theunix://prefix and pass the rest of the string verbatim as the socket file path — so the writer ends up trying to connect to a socket literally named/var/run/datadog/dsd.socket:8125, which does not exist (the real file is/var/run/datadog/dsd.socket, without a port suffix).Because
datadog-go's UDS writer defers the actualconnect()until the firstWrite()call (seeuds.go, "Defer connection to first Write"),NewSink()returns no error and the service logs"Stats initialized for dogstatsd"successfully at startup. Every subsequentWrite()then fails withENOENT/"no such file or directory", butFlushCounter/FlushGauge/FlushTimerindogstatsd_sink.godiscard the error returned byclient.Count()/client.Gauge()/client.Timing(), so the failure is completely silent — no logs, no metrics, no crash, no indication anything is wrong.Expected behavior
Setting
STATSD_HOSTto aunix://,unixgram://, orunixstream://address should work for DogStatsD over a Unix Domain Socket, without requiring/appending a port — matching howdatadog-go's ownstatsd.Newdocuments itsaddrparameter:Actual behavior
STATSD_PORTis always appended toSTATSD_HOST, corrupting any Unix Domain Socket address and causing all metrics to be silently dropped.Suggested fix
In
NewSink(), only append:portwhenhostdoes not already look like a complete address (e.g. doesn't have aunix:///unixgram:///unixstream://prefix or a Windows named pipe prefix), similar to howdatadog-go's ownresolveAddrdecides whether to append a port:Environment
envoyproxy/ratelimitbuilt from a recentmain(confirmed present as of commit range including feat(DogStatsD): parse EXTRA_TAGS to move from metric name into statsd tags #625/fix(dogstatsd_sink): switch from pure map to list of key/value pairs #627, June 2024, and still present inmainas of August 2026)USE_DOG_STATSD=true,STATSD_HOST=unix:///var/run/datadog/dsd.socketmounted via ahostPathvolume shared with the Datadog node agent's DogStatsD Unix Domain Socket