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

Made stats sinks a statically registered component #1506

Merged
merged 7 commits into from
Sep 5, 2017

Conversation

mrice32
Copy link
Member

@mrice32 mrice32 commented Aug 21, 2017

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 and statsd_tcp_cluster_name will be deprecated, and their equivalents will be moved to a new stats_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.

@mrice32
Copy link
Member Author

mrice32 commented Aug 21, 2017

@htuch

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.

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.

@@ -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" : {
Copy link
Member

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,
Copy link
Member

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.


// 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(
Copy link
Member

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"; }
Copy link
Member

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.

@mrice32
Copy link
Member Author

mrice32 commented Aug 21, 2017

That makes sense. Let's go straight to v2 with this.

@mattklein123
Copy link
Member

@mrice32 @htuch do we want to try to land this before 1.4.0 is tagged (probably Friday)? Or can we potentially wait until next week and make this a 1.5.0 deprecation?

@mrice32
Copy link
Member Author

mrice32 commented Aug 21, 2017

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.

@mattklein123
Copy link
Member

OK perfect thank you.

@mattklein123
Copy link
Member

@mrice32 can you merge master, then we can get this in.

@mrice32
Copy link
Member Author

mrice32 commented Aug 25, 2017

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.

@mattklein123
Copy link
Member

OK sounds good. I will review #1521.

@mrice32
Copy link
Member Author

mrice32 commented Sep 1, 2017

Merged and should be ready for review.

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.


#include <string>

#include "envoy/registry/registry.h"
Copy link
Member

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.


if (!sink_object.has_config()) {
throw EnvoyException(
"sink object does not contain the 'config' object to configure the implementation");
Copy link
Member

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.

/**
* 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
Copy link
Member

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.

Copy link
Member

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.

Copy link
Member Author

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.

* @param cluster_manager supplies the cluster_manager instance
*/
virtual Stats::SinkPtr createStatsSink(const Protobuf::Message& config, Instance& server,
Upstream::ClusterManager& cluster_manager) PURE;
Copy link
Member

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::_;
Copy link
Member

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.

Copy link
Member Author

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?

Copy link
Member

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();
Copy link
Member

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
Copy link
Member

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?

@mrice32
Copy link
Member Author

mrice32 commented Sep 5, 2017

Responded to comments. Added tests for other throw cases in the tests for ConfigurationImpl since those throws were in that file.

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, 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);
Copy link
Member

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.

Copy link
Member Author

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) {
Copy link
Member

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?

Copy link
Member Author

@mrice32 mrice32 Sep 5, 2017

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.

Copy link
Member Author

@mrice32 mrice32 Sep 5, 2017

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.

@mrice32
Copy link
Member Author

mrice32 commented Sep 5, 2017

Hmmm, //test/common/network:connection_impl_test seems to be failing on OS X CI, but I don't think I modified anything that that would depend on...?

@htuch
Copy link
Member

htuch commented Sep 5, 2017

@mrice32 that's a known flake/failure.

Copy link
Member

@mattklein123 mattklein123 left a 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!

@htuch htuch merged commit 0702b29 into envoyproxy:master Sep 5, 2017
@mrice32 mrice32 deleted the sta_reg branch October 26, 2017 15:48
jpsim pushed a commit that referenced this pull request Nov 28, 2022
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]>
jpsim pushed a commit that referenced this pull request Nov 29, 2022
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]>
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.

3 participants