-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Made stats sinks a statically registered component #1506
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding this. I'm wondering if we want to go straight to v2 though, we're basically ready to do this now by adding these fields into the bootstrap proto.
source/common/json/config_schemas.cc
Outdated
@@ -1187,6 +1187,10 @@ const std::string Json::Schema::TOP_LEVEL_CONFIG_SCHEMA(R"EOF( | |||
"statsd_udp_ip_address" : {"type" : "string"}, | |||
"statsd_tcp_cluster_name" : {"type" : "string"}, | |||
"stats_flush_interval_ms" : {"type" : "integer"}, | |||
"stats_sinks" : { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will be added support to the v2 bootstrap proto (https://github.com/lyft/envoy-api/blob/master/api/bootstrap.proto) to cover this functionality (as well as a bunch of stuff at the top-level) tomorrow. Do you think you want this feature in v1, or maybe it would make sense to make it v2 only?
class TcpStatsdSinkFactory : Logger::Loggable<Logger::Id::config>, public StatsSinkFactory { | ||
public: | ||
// StatsSinkFactory | ||
Stats::SinkPtr createStatsSink(const Json::Object& json_config, Instance& server, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would prefer we go proto-only on this new feature, see what is being done in https://github.com/lyft/envoy/pull/1495/files.
source/server/configuration_impl.cc
Outdated
|
||
// Used to convert the deprecated statsd configuration into a json snippet for consumption by the | ||
// new sink config parsing logic. | ||
const std::string statsd_json = R"EOF( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the translate*()
conversion functions in source/common/config/*_json.cc
for the stylized way we are mapping from v1 JSON to v2 proto.
fmt::format("Didn't find cluster_name in the {} Stats::Sink config", name())); | ||
} | ||
|
||
std::string TcpStatsdSinkFactory::name() { return "statsd_tcp"; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest using the reverse DNS scheme described in https://github.com/lyft/envoy-api/blob/master/README.md#principles for custom components. I think for builtins, we would use envoy.statsd_tcp
, since I've been using the envoy.
prefix other places in v2 for builtins.
That makes sense. Let's go straight to v2 with this. |
It was intended to be a 1.5.0 deprecation, and there's no rush on getting it merged, so we can definitely wait til next week to keep it from complicating the 1.4.0 release. |
OK perfect thank you. |
@mrice32 can you merge master, then we can get this in. |
I think we should wait on #1521 to get merged. Otherwise, we'll have to reimplement the stats portion of the json -> proto conversion from that PR in this one. If you'd like we can close this for now and reopen once that gets merged. |
OK sounds good. I will review #1521. |
Merged and should be ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great.
|
||
#include <string> | ||
|
||
#include "envoy/registry/registry.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Any header that is depended upon in .{cc,h}
should be directly reflected in the deps
in the BUILD
file. This avoids surprises when A depends on B providing C, but later on, B no longer depends on C. Since we lack tool automation for this in OSS, we don't really enforce it (I'm sure I'm guilty of many breaches of this), but best to try and shoot for it. Basically, you want IWYU (include what you use, i.e. have all include headers in a file directly for symbols that appear in the file) and then BUILD
dep
pointing at libs providing the headers.
source/server/configuration_impl.cc
Outdated
|
||
if (!sink_object.has_config()) { | ||
throw EnvoyException( | ||
"sink object does not contain the 'config' object to configure the implementation"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think an empty default config is legit, we could have some filters that don't require config.
source/server/configuration_impl.h
Outdated
/** | ||
* Create a particular Stats::Sink implementation. If the implementation is unable to produce a | ||
* Stats::Sink with the provided parameters, it should throw an EnvoyException in the case of | ||
* general error or a Json::Exception if the json configuration is erroneous. The returned |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why Json::Exception
? This is a pure v2 feature, we shouldn't have RapidJSON involved as we're working in proto land here. The only JSON conversion is performed by the protobuf library that won't create these types of exceptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see, this is copy+paste from https://github.com/lyft/envoy/blob/master/include/envoy/server/filter_config.h. In filter_config.h
, the JSON stuff doesn't apply to the ...FromProto()
variants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, sorry, that was just a typo. Thought I removed it.
source/server/configuration_impl.h
Outdated
* @param cluster_manager supplies the cluster_manager instance | ||
*/ | ||
virtual Stats::SinkPtr createStatsSink(const Protobuf::Message& config, Instance& server, | ||
Upstream::ClusterManager& cluster_manager) PURE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is ClusterManager
a distinct parameter here? I think it can be inferred from the Server::Instance
parameter?
using testing::NiceMock; | ||
using testing::Return; | ||
using testing::ReturnRef; | ||
using testing::_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: place outside the namespace block as per Envoy convention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few other tests (including the one I modeled after) that put it inside the Envoy namespace block. Should I go ahead and update those as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, thanks.
TEST(StatsConfigTest, ValidTcpStatsd) { | ||
const std::string name = "envoy.statsd"; | ||
Protobuf::Struct config; | ||
ProtobufWkt::Map<ProtobufTypes::String, ProtobufWkt::Value>& field_map = *config.mutable_fields(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer using auto
here and elsewhere for proto handlers, the extra noise of the complex types doesn't help readability.
EXPECT_THROW(factory->createStatsSink(*message, server, server.clusterManager()), EnvoyException); | ||
} | ||
|
||
} // namespace Configuration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's probably a few of the throw EnvoyException
cases that don't have coverage in this file. Can you add?
Responded to comments. Added tests for other throw cases in the tests for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, two small questions..
*address_field_map["socket_address"].mutable_struct_value()->mutable_fields(); | ||
socket_address_field_map["protocol"].set_string_value("UDP"); | ||
socket_address_field_map["address"].set_string_value("127.0.0.1"); | ||
socket_address_field_map["port_value"].set_number_value(8125); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not build a typed envoy::api::v2::Address
and the JsonConvert()
it to the Struct
? Seems a bit more robust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I had an internal debate about which one was a better way to go about testing it. In hindsight, since we're moving to a protobuf specified bootstrap config, I think your suggestion makes sense. I'll update.
EXPECT_NE(dynamic_cast<Stats::Statsd::UdpStatsdSink*>(sink.get()), nullptr); | ||
} | ||
|
||
TEST(StatsConfigTest, EmptyConfig) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought you removed the empty config exception above, how come this still throws?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because an empty config is invalid for that particular sink (statsd). I can add an expected throw message to clarify.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests are not calling into the ConfigurationImpl
object. They are meant to test the configuration of specific instances of stats sinks rather than the general configuration mechanism in ConfigurationImpl
.
Hmmm, |
@mrice32 that's a known flake/failure. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Thanks for fixing all the namespace stuff!
Description: This PR modifies the build recipe for `envoy_engine.so` to hide all symbols except for `_PyInit_envoy_engine` by default on maOS, so that envoy_engine can be loaded alongside a [protobuf](http://pypi.org/project/protobuf) wheel without breaking. Loading in protobuf alongside `envoy_engine.so` would register two sets of the same symbols and, on macOS, the runtime linker chooses the first symbol it finds causing problems. See the [similar protobuf change](protocolbuffers/protobuf#8346) and its [sister change in grpc](grpc/grpc#24992) for more information on what's going on. Risk Level: Low Testing: See the now-closed #1504 for how I've been testing this. Docs Changes: N/A Release Notes: N/A Signed-off-by: Cerek Hillen <[email protected]> Signed-off-by: JP Simard <[email protected]>
Description: This PR modifies the build recipe for `envoy_engine.so` to hide all symbols except for `_PyInit_envoy_engine` by default on maOS, so that envoy_engine can be loaded alongside a [protobuf](http://pypi.org/project/protobuf) wheel without breaking. Loading in protobuf alongside `envoy_engine.so` would register two sets of the same symbols and, on macOS, the runtime linker chooses the first symbol it finds causing problems. See the [similar protobuf change](protocolbuffers/protobuf#8346) and its [sister change in grpc](grpc/grpc#24992) for more information on what's going on. Risk Level: Low Testing: See the now-closed #1504 for how I've been testing this. Docs Changes: N/A Release Notes: N/A Signed-off-by: Cerek Hillen <[email protected]> Signed-off-by: JP Simard <[email protected]>
This is part of a larger effort to make various implementations more flexible by allowing proprietary components to be statically registered with Envoy needing only to be linked to the binary at build time and configured at runtime #967 .
The user-visible configuration changes do involve a few deprecations:
statsd_udp_ip_address
andstatsd_tcp_cluster_name
will be deprecated, and their equivalents will be moved to a newstats_sinks
array where the configurations for any statically registered sink will exist. As a part of this change, all integration tests were moved to the new configuration format, but a new configuration test was added to ensure that the deprecated format continues to work until it is removed in 1.5.0.