Skip to content

Support IPv6 DogStatsD addresses - #399

Open
BakedSoups wants to merge 1 commit into
DataDog:masterfrom
BakedSoups:fix/ipv6-statsd-addresses
Open

Support IPv6 DogStatsD addresses#399
BakedSoups wants to merge 1 commit into
DataDog:masterfrom
BakedSoups:fix/ipv6-statsd-addresses

Conversation

@BakedSoups

@BakedSoups BakedSoups commented Aug 18, 2026

Copy link
Copy Markdown

Hey, big fan of the Go migration here! I saw #275 and wanted to give a PR a shot.

Problem

The address resolver assumed that any address containing a colon already included a port. Raw IPv6 addresses such as ::1 therefore reached the UDP writer without brackets or a port.

Solution

Use Go’s standard address helpers to normalize IPv6 addresses while preserving explicit ports. This supports IPv6 addresses passed directly, through DD_AGENT_HOST, or through DD_DOGSTATSD_URL. Zone identifiers are supported for direct addresses and DD_AGENT_HOST.

Testing

  • go test -race ./statsd -run ^TestResolveAddressFromEnvironment$ -count=1
  • go vet ./...

Fixes #275.

@BakedSoups
BakedSoups requested a review from a team as a code owner August 18, 2026 02:56
@atanzu
atanzu requested a lite review from Copilot August 18, 2026 06:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR improves UDP address resolution to correctly handle IPv6 literals (including bracketed forms and zone identifiers) by centralizing “add default port if missing” logic and expanding test coverage.

Changes:

  • Introduced a withPort helper using net.SplitHostPort / net.JoinHostPort to normalize host/port handling (including IPv6).
  • Updated UDP URL parsing to reuse the same port-normalization logic.
  • Added unit tests covering IPv6 address scenarios for env-based and URL-based configuration.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
statsd/statsdex.go Adds IPv6-safe port normalization via withPort and uses it for UDP URL parsing.
statsd/statsd_test.go Expands test cases to validate IPv6 behavior across env vars and DD_DOGSTATSD_URL.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread statsd/statsdex.go
Comment on lines +354 to 368
func withPort(addr, port string) string {
if _, _, err := net.SplitHostPort(addr); err == nil {
return addr
}
if envPort != "" {
addr = fmt.Sprintf("%s:%s", addr, envPort)
} else {
addr = fmt.Sprintf("%s:%s", addr, defaultUDPPort)

// Preserve the existing handling of host:port-like addresses while treating
// addresses with multiple colons as unbracketed IPv6 literals.
if strings.Count(addr, ":") == 1 {
return addr
}
return addr

host := strings.TrimPrefix(addr, "[")
host = strings.TrimSuffix(host, "]")
return net.JoinHostPort(host, port)
}
@atanzu

atanzu commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

The PR description claims zone identifier support, and it works for direct addresses and DD_AGENT_HOST like e.g. DD_AGENT_HOST=fe80::1%lo0, but zone IDs do not work in the DD_DOGSTATSD_URL path because url.Parse interprets % as a URL escape sequence, so udp://fe80::1%lo0 or udp://[fe80::1%eth0] will fail. Could you please adjust the PR description to clarify that zone ID support works with DD_AGENT_HOST and direct addresses, not DD_DOGSTATSD_URL?

Comment thread statsd/statsdex.go Outdated

// Preserve the existing handling of host:port-like addresses while treating
// addresses with multiple colons as unbracketed IPv6 literals.
if strings.Count(addr, ":") == 1 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIR SplitHostPort already handles things like localhost:, :1234, foo:bar (basically any input with a single :) so this check might probably be unneeded.

Address resolution previously treated any colon as evidence that a port was already present. As a result, raw and bracketed IPv6 hosts could reach the UDP writer without a port and fail client initialization.

Normalize IPv6 hosts with net.JoinHostPort while preserving explicitly provided ports. Apply the same behavior to direct addresses, DD_AGENT_HOST, and DD_DOGSTATSD_URL, and cover default ports, custom ports, bracketed hosts, and zone identifiers.

Fixes DataDog#275.
@BakedSoups
BakedSoups force-pushed the fix/ipv6-statsd-addresses branch from eebf792 to e577690 Compare August 28, 2026 22:25
@BakedSoups

Copy link
Copy Markdown
Author

Thanks for the review! I removed the redundant single-colon check since net.SplitHostPort already handles those cases.

I also updated the PR description to clarify that zone identifiers are supported for direct addresses and DD_AGENT_HOST, but not through DD_DOGSTATSD_URL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Client Support IPv6 address

3 participants