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

config/stats: add udp statds address as config option #1019

Merged
merged 8 commits into from
May 26, 2017

Conversation

hennna
Copy link
Contributor

@hennna hennna commented May 25, 2017

This PR allows the statsd UDP server address to be set as a JSON config parameter.

To allow for unit testing, the udp statsd writer_ has been changed from a static thread_local object to being derived from the ThreadLocal object class.

In this PR, statsd_local_udp_port has been DEPRECATED and replaced with statsd_udp_ip_address.

Fixes #948 . Fixes part of #979 .

socklen_t sock_len = sizeof(sockaddress);

EXPECT_EQ(0, getsockname(fd, reinterpret_cast<struct sockaddr*>(&sockaddress), &sock_len));
EXPECT_EQ("127.0.0.1", Network::Address::addressFromSockAddr(sockaddress, sizeof(sockaddr_in))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is it expected that this is 127.0.0.1 and not 0.0.0.0?

Copy link
Member

Choose a reason for hiding this comment

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

I notice above we create the address as new Network::Address::Ipv4Instance(port) (which it was also doing before). This actually sets the destination IP as 0.0.0.0, which doesn't seem to make that sense to me (unless I'm missing something about UDP and local interfaces). The fact that this passes though seems to indicate it does get rebound? Maybe someone with more insight can comment here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you ping 0.0.0.0 you get

PING 0.0.0.0 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.056 ms

So somehow it's getting converted.

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

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

Looks great @hennna, thanks.

@@ -130,12 +130,18 @@ class Main {
*/
virtual Optional<std::string> statsdTcpClusterName() PURE;

// TODO(hennna): Deprecate in release: 1.4.0.
Copy link
Member

Choose a reason for hiding this comment

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

Nit: it's deprecated now, will be removed in 1.4.0.

DEPERECATED.md Outdated
@@ -0,0 +1,3 @@
# DEPRECATED starting from 1.3.0
Copy link
Member

Choose a reason for hiding this comment

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

Maybe DEPRECATED (will be removed in 1.4.0). @RomanDzhabarov thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe put a top level description of what this file is for and what rules are (feature is removed starting from the specified version, etc)

And then having a list of features that will be removed in a specific version.

Description

Version 1.4.0:

  • item 1
  • item 2

Version 1.5.0:

  • ..

etc

Copy link
Contributor

Choose a reason for hiding this comment

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

Update the file name DEPERECATED.md -> DEPRECATED.md now, otherwise we will have to deprecate the DEPERECATED.md at a later date!

/**
* @return Optional<uint32_t> the optional local UDP statsd port to write to.
*/
virtual Optional<uint32_t> statsdUdpPort() PURE;

/**
* @return Optional<uint32_t> the optional UDP statsd address to write to.
Copy link
Member

Choose a reason for hiding this comment

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

Stale comment type.

/**
* @return Optional<uint32_t> the optional local UDP statsd port to write to.
*/
virtual Optional<uint32_t> statsdUdpPort() PURE;

/**
* @return Optional<uint32_t> the optional UDP statsd address to write to.
*/
virtual Optional<std::string> statsdUdpIpAddress() PURE;
Copy link
Member

Choose a reason for hiding this comment

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

Should this be a string or Network::Address::InstanceConstSharedPtr?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is string and has to do with parsing the JSON config file.

void Writer::shutdown() {
shutdown_ = true;
if (fd_ != -1) {
ASSERT(close(fd_) == 0);
Copy link
Member

Choose a reason for hiding this comment

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

This should be RELEASE_ASSERT or it will get compiled out in release builds.

log().info("statsd UDP port: {}", config_->statsdUdpPort().value());
stat_sinks_.emplace_back(new Stats::Statsd::UdpStatsdSink(config_->statsdUdpPort().value()));
stat_sinks_.emplace_back(
new Stats::Statsd::UdpStatsdSink(thread_local_, config_->statsdUdpPort().value()));
Copy link
Member

Choose a reason for hiding this comment

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

You could localize the deprecation to this method if you switch the UdpStatsdSink constructor to just take an Address.

socklen_t sock_len = sizeof(sockaddress);

EXPECT_EQ(0, getsockname(fd, reinterpret_cast<struct sockaddr*>(&sockaddress), &sock_len));
EXPECT_EQ("127.0.0.1", Network::Address::addressFromSockAddr(sockaddress, sizeof(sockaddr_in))
Copy link
Member

Choose a reason for hiding this comment

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

I notice above we create the address as new Network::Address::Ipv4Instance(port) (which it was also doing before). This actually sets the destination IP as 0.0.0.0, which doesn't seem to make that sense to me (unless I'm missing something about UDP and local interfaces). The fact that this passes though seems to indicate it does get rebound? Maybe someone with more insight can comment here.

The following features have been DEPRECATED and will be removed in the specified release cycle.

* Version 1.4.0
* Config option `statsd_local_udp_port` has been deprecated and has been replaced with
Copy link
Member

Choose a reason for hiding this comment

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

thanks @hennna I'll update this with 3a466c3
once you merge it

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

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

LGTM

~Writer();

void writeCounter(const std::string& name, uint64_t increment);
void writeGauge(const std::string& name, uint64_t value);
void writeTimer(const std::string& name, const std::chrono::milliseconds& ms);
void shutdown() override;
// Called in unit test to validate address.
int getFdForTests() { return fd_; };
Copy link
Member

Choose a reason for hiding this comment

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

const

EXPECT_EQ("127.0.0.1", Network::Address::addressFromFd(fd)->ip()->addressAsString());
} else {
EXPECT_EQ("::1", Network::Address::addressFromFd(fd)->ip()->addressAsString());
}
Copy link
Member

Choose a reason for hiding this comment

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

What about checking expected port?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This need to be updated to getpeername. Will fix.

@@ -232,7 +232,7 @@

"admin": { "access_log_path": "/dev/null", "profile_path": "{{ test_tmpdir }}/envoy.prof", "address": "tcp://127.0.0.1:0" },
"flags_path": "/invalid_flags",
"statsd_local_udp_port": 8125,
"statsd_udp_ip_address": "127.0.0.1:0",
Copy link
Member

Choose a reason for hiding this comment

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

It's a bit weird specifying a 0 send port, but sure, why not, it at least points out this is distinguished.

@@ -45,9 +45,11 @@ flags_path
*(optional, string)* The file system path to search for :ref:`startup flag files
<operations_file_system_flags>`.

statsd_local_udp_port
Copy link
Member

Choose a reason for hiding this comment

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

shall we keep this until it's removed from the code? (and add deprecation warning)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. Will add it back.


uint32_t port_;
ThreadLocal::Instance& tls_;
uint32_t tls_slot_;
Copy link
Member

Choose a reason for hiding this comment

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

const

statsd_local_udp_port
*(optional, integer)* The UDP port of a locally running statsd compliant listener. If specified,
:ref:`statistics <arch_overview_statistics>` will be flushed to this port.
statsd_udp_ip_address
Copy link
Member

Choose a reason for hiding this comment

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

what happens if both specified?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It will choose ip_address over port in server.cc

Copy link
Member

Choose a reason for hiding this comment

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

wondering if we just should throw to avoid confusion when we checked whether one or another is set.
https://github.com/lyft/envoy/pull/1019/files#diff-3eda0ff865e056f19775ad626a5c2920R321


private:
void send(const std::string& message);

int fd_;
bool shutdown_ = false;
Copy link
Member

Choose a reason for hiding this comment

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

for consistency, bool shutdown_{};

@RomanDzhabarov RomanDzhabarov self-assigned this May 26, 2017
@RomanDzhabarov
Copy link
Member

+1

@RomanDzhabarov RomanDzhabarov merged commit a8c446a into envoyproxy:master May 26, 2017
@jylin
Copy link

jylin commented May 26, 2017

Does this patch support a DNS address instead of an IP? If so, maybe just statsd_udp_remote_address is a better option name.

@htuch
Copy link
Member

htuch commented May 26, 2017

This doesn't support a DNS address, only IP:port. In general, Envoy only supports DNS resolutions today when redirecting via cluster resolution.

@jylin
Copy link

jylin commented May 30, 2017

OK, although then using this option sort of forces you into a bad practice of hard-coding IP addresses. Would it make sense to try to make the "statsd_tcp_cluster_name" then support UDP too (i.e. a "statsd_udp_cluster_name")?

@htuch
Copy link
Member

htuch commented May 30, 2017

This seems reasonable from a config/API perspective, but will involve a bit of work to make work. Currently the cluster implementations such as LogicalDnsCluster are assuming TCP connections. So, we can leave open to track this but I don't think anyone is actively working on it. PRs are welcome.

@htuch
Copy link
Member

htuch commented May 30, 2017

This is also related to #492 - if there was general support for UDP proxying we would be able to leverage that to do have UDP addressable clusters for statsd.

@htuch
Copy link
Member

htuch commented May 30, 2017

Tracking in #1028.

@hennna hennna deleted the udp-stats-address branch May 31, 2017 16:26
jpsim pushed a commit that referenced this pull request Nov 28, 2022
Signed-off-by: Michael Rebello <[email protected]>
Signed-off-by: JP Simard <[email protected]>
jpsim pushed a commit that referenced this pull request Nov 29, 2022
Signed-off-by: Michael Rebello <[email protected]>
Signed-off-by: JP Simard <[email protected]>
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.

5 participants