Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for DD_DOGSTATSD_HOST #208

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,16 @@ Find a list of all the available options for your DogStatsD Client in the [Datad

### Supported environment variables

* If the `addr` parameter is empty, the client uses the `DD_AGENT_HOST` environment variables to build a target address.
Example: `DD_AGENT_HOST=127.0.0.1:8125` for UDP, `DD_AGENT_HOST=unix:///path/to/socket` for UDS and `DD_AGENT_HOST=\\.\pipe\my_windows_pipe` for Windows
* If the `DD_ENTITY_ID` environment variable is found, its value is injected as a global `dd.internal.entity_id` tag. The Datadog Agent uses this tag to insert container tags into the metrics. To avoid overwriting this global tag, only `append` to the `c.Tags` slice.
* If the `addr` parameter is empty, the client uses the `DD_DOGSTATSD_HOST` and then `DD_AGENT_HOST` environment
variables to build a target address. `DD_DOGSTATSD_HOST` takes precedence over `DD_AGENT_HOST`, but both use the same
format.
Example: `DD_AGENT_HOST=127.0.0.1:8125` for UDP, `DD_AGENT_HOST=unix:///path/to/socket` for UDS and
`DD_AGENT_HOST=\\.\pipe\my_windows_pipe` for named pipes
* `DD_DOGSTATSD_PORT` can be use to set the UDP port. If `DD_DOGSTATSD_HOST` or `DD_AGENT_HOST` already contains a port
then `DD_DOGSTATSD_PORT` is ignored.
Example: `DD_AGENT_HOST=127.0.0.1` with `DD_DOGSTATSD_PORT=8125`.
* If the `DD_ENTITY_ID` environment variable is found, its value is injected as a global `dd.internal.entity_id` tag.
The Datadog Agent uses this tag to insert container tags into the metrics.

To enable origin detection and set the `DD_ENTITY_ID` environment variable, add the following lines to your application manifest:

Expand Down
15 changes: 10 additions & 5 deletions statsd/statsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ traffic instead of UDP.
const WindowsPipeAddressPrefix = `\\.\pipe\`

const (
agentHostEnvVarName = "DD_AGENT_HOST"
agentPortEnvVarName = "DD_DOGSTATSD_PORT"
defaultUDPPort = "8125"
agentHostEnvVarName = "DD_AGENT_HOST"
dogstatsdHostEnvVarName = "DD_DOGSTATSD_HOST"
dogstatsdPortEnvVarName = "DD_DOGSTATSD_PORT"
defaultUDPPort = "8125"
)

/*
Expand Down Expand Up @@ -230,8 +231,12 @@ var _ ClientInterface = &Client{}
func resolveAddr(addr string) string {
envPort := ""
if addr == "" {
addr = os.Getenv(agentHostEnvVarName)
envPort = os.Getenv(agentPortEnvVarName)
if dsdHost := os.Getenv(dogstatsdHostEnvVarName); dsdHost != "" {
addr = dsdHost
} else {
addr = os.Getenv(agentHostEnvVarName)
}
envPort = os.Getenv(dogstatsdPortEnvVarName)
}

if addr == "" {
Expand Down
100 changes: 96 additions & 4 deletions statsd/statsd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,11 @@ func TestResolveAddressFromEnvironment(t *testing.T) {
} else {
defer os.Unsetenv(agentHostEnvVarName)
}
portInitialValue, portInitiallySet := os.LookupEnv(agentPortEnvVarName)
portInitialValue, portInitiallySet := os.LookupEnv(dogstatsdPortEnvVarName)
if portInitiallySet {
defer os.Setenv(agentPortEnvVarName, portInitialValue)
defer os.Setenv(dogstatsdPortEnvVarName, portInitialValue)
} else {
defer os.Unsetenv(agentPortEnvVarName)
defer os.Unsetenv(dogstatsdPortEnvVarName)
}

for _, tc := range []struct {
Expand Down Expand Up @@ -224,7 +224,7 @@ func TestResolveAddressFromEnvironment(t *testing.T) {
} {
t.Run(tc.name, func(t *testing.T) {
os.Setenv(agentHostEnvVarName, tc.hostEnv)
os.Setenv(agentPortEnvVarName, tc.portEnv)
os.Setenv(dogstatsdPortEnvVarName, tc.portEnv)

addr := resolveAddr(tc.addrParam)
assert.Equal(t, tc.expectedAddr, addr)
Expand Down Expand Up @@ -269,3 +269,95 @@ func TestGetTelemetry(t *testing.T) {
assert.Equal(t, uint64(1), tlm.AggregationNbContextDistribution, "telmetry AggregationNbContextDistribution was wrong")
assert.Equal(t, uint64(2), tlm.AggregationNbContextTiming, "telmetry AggregationNbContextTiming was wrong")
}

func TestEnvAgentHost(t *testing.T) {
defer func() { os.Unsetenv("DD_AGENT_HOST") }()

os.Setenv("DD_AGENT_HOST", "localhost:8765")

ts, client := newClientAndTestServerCustomAddr(t,
"udp",
"",
"localhost:8765",
nil,
)

ts.sendAllAndAssert(t, client)
}

func TestEnvAgentHostAndPort(t *testing.T) {
defer func() { os.Unsetenv("DD_AGENT_HOST") }()
defer func() { os.Unsetenv("DD_DOGSTATSD_PORT") }()

// Check that DD_AGENT_PORT is ignored when DD_AGENT_HOST already contains a port
os.Setenv("DD_AGENT_HOST", "localhost:8765")
os.Setenv("DD_DOGSTATSD_PORT", "1234")

ts, client := newClientAndTestServerCustomAddr(t,
"udp",
"",
"localhost:8765",
nil,
)

ts.sendAllAndAssert(t, client)

// Check that DD_DOGSTATSD_PORT is used
os.Setenv("DD_AGENT_HOST", "localhost")
os.Setenv("DD_DOGSTATSD_PORT", "8766")

ts, client = newClientAndTestServerCustomAddr(t,
"udp",
"",
"localhost:8766",
nil,
)

ts.sendAllAndAssert(t, client)
}

func TestEnvDogstatsddHost(t *testing.T) {
defer func() { os.Unsetenv("DD_DOGSTATSD_HOST") }()

os.Setenv("DD_DOGSTATSD_HOST", "localhost:8765")

ts, client := newClientAndTestServerCustomAddr(t,
"udp",
"",
"localhost:8765",
nil,
)

ts.sendAllAndAssert(t, client)
}

func TestEnvDogstatsddHostAndPort(t *testing.T) {
defer func() { os.Unsetenv("DD_DOGSTATSD_HOST") }()
defer func() { os.Unsetenv("DD_DOGSTATSD_PORT") }()

// Check that DD_DOGSTATSD_PORT is ignored when DD_AGENT_HOST already contains a port
os.Setenv("DD_DOGSTATSD_HOST", "localhost:8765")
os.Setenv("DD_DOGSTATSD_PORT", "1234")

ts, client := newClientAndTestServerCustomAddr(t,
"udp",
"",
"localhost:8765",
nil,
)

ts.sendAllAndAssert(t, client)

// Check that DD_DOGSTATSD_PORT is used
os.Setenv("DD_DOGSTATSD_HOST", "localhost")
os.Setenv("DD_DOGSTATSD_PORT", "8766")

ts, client = newClientAndTestServerCustomAddr(t,
"udp",
"",
"localhost:8766",
nil,
)

ts.sendAllAndAssert(t, client)
}
11 changes: 6 additions & 5 deletions statsd/test_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ type testServer struct {
errors []string
readData []string
proto string
addr string
stopped chan struct{}
tags string
namespace string
Expand All @@ -66,14 +65,16 @@ type testServer struct {
}

func newClientAndTestServer(t *testing.T, proto string, addr string, tags []string, options ...Option) (*testServer, *Client) {
return newClientAndTestServerCustomAddr(t, proto, addr, addr, tags, options...)
}

func newClientAndTestServerCustomAddr(t *testing.T, proto string, addrClient string, addrTest string, tags []string, options ...Option) (*testServer, *Client) {
opt, err := resolveOptions(options)
require.NoError(t, err)

ts := &testServer{
proto: proto,
data: []string{},
addr: addr,
stopped: make(chan struct{}),
aggregation: opt.aggregation,
extendedAggregation: opt.extendedAggregation,
Expand All @@ -88,14 +89,14 @@ func newClientAndTestServer(t *testing.T, proto string, addr string, tags []stri

switch proto {
case "udp":
udpAddr, err := net.ResolveUDPAddr("udp", addr)
udpAddr, err := net.ResolveUDPAddr("udp", addrTest)
require.NoError(t, err)

conn, err := net.ListenUDP("udp", udpAddr)
require.NoError(t, err)
ts.conn = conn
case "uds":
socketPath := addr[7:]
socketPath := addrTest[7:]
address, err := net.ResolveUnixAddr("unixgram", socketPath)
require.NoError(t, err)
conn, err := net.ListenUnixgram("unixgram", address)
Expand All @@ -107,7 +108,7 @@ func newClientAndTestServer(t *testing.T, proto string, addr string, tags []stri
require.FailNow(t, "unknown proto '%s'", proto)
}

client, err := New(addr, options...)
client, err := New(addrClient, options...)
require.NoError(t, err)

go ts.start()
Expand Down