Skip to content

config: logging a warning on use of deprecated proto fields#5760

Merged
alyssawilk merged 8 commits intoenvoyproxy:masterfrom
alyssawilk:runtime
Feb 4, 2019
Merged

config: logging a warning on use of deprecated proto fields#5760
alyssawilk merged 8 commits intoenvoyproxy:masterfrom
alyssawilk:runtime

Conversation

@alyssawilk
Copy link
Contributor

Risk Level: Low (logging only)
Testing: new unit tests
Docs Changes: n/a
Release Notes: not included
Part of #5559

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor Author

Some discussion points.

I'd prefer this to be a critical log but I think the forced-flush could work very badly if it were present in a large (order tens of thousands of repeated messages) config, so I'm erring on the side of perf-caution

I think we should probably un-deprecate 2 of the 3 remaining deprecated_v1 fields to avoid user-confusion that they will be removed soon. I believe the removal of bind_to_port and the cds tcp proxy filter are blocked on code, so should probably be undeprecated until code is complete and then de-deprecated following normal Envoy process.
The third one, which is the hashing algorithm, I think we can still kill off in fairly short order but I'm happy to be overriden by the folks at Lyft working on their migration.

Copy link
Member

@ggreenway ggreenway left a comment

Choose a reason for hiding this comment

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

This is great!

Do we consistently call validate() on all messages, and specifically on the bits that get passed as a Struct and re-proto-ified in filters?

const auto* desc = message.GetDescriptor();
const auto* refl = message.GetReflection();
for (int i = 0; i < desc->field_count(); ++i) {
const auto* fd = desc->field(i);
Copy link
Member

Choose a reason for hiding this comment

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

nit: fd means file descriptor in my brain. Rename to field?

envoy::test::deprecation_test::Base base;
base.set_is_deprecated("foo");
// Non-fatal checks for a deprecated field shouldn't throw an exception.
MessageUtil::checkForDeprecation(base, false);
Copy link
Member

Choose a reason for hiding this comment

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

Wrap in EXPECT_LOG_CONTAINS?

static void loadFromYaml(const std::string& yaml, Protobuf::Message& message);
static void loadFromFile(const std::string& path, Protobuf::Message& message);

template <class MessageType>
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this need to be templatized, using Protobuf::Message should be just enough.

static void checkForDeprecation(const MessageType& message, bool fatal) {
const auto* desc = message.GetDescriptor();
const auto* refl = message.GetReflection();
for (int i = 0; i < desc->field_count(); ++i) {
Copy link
Member

Choose a reason for hiding this comment

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

This only checks top level field and not about inner fields such as here, Validate does recursive validation internally but MessageUtil::validate isn't called at every level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah my bad, I didn't realize Validate was doing the recursion - will fix and regression test

@lizan
Copy link
Member

lizan commented Jan 29, 2019

Do we consistently call validate() on all messages, and specifically on the bits that get passed as a Struct and re-proto-ified in filters?

Struct and re-proto-ified ones are validated via downcastAndValidate so it will be checked by this method.

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor Author

alyssawilk commented Jan 29, 2019

Noting for the record I'm now officially out of my depth w.r.t proto reflection so please to encourage more tests if you see any gaps.

And uploaded without testing beyond the unit test - living dangerously today! :-P

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
static void loadFromYaml(const std::string& yaml, Protobuf::Message& message);
static void loadFromFile(const std::string& path, Protobuf::Message& message);

static void checkForDeprecation(const Protobuf::Message& message, bool fatal) {
Copy link
Member

Choose a reason for hiding this comment

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

move the impl to .cc

"Using deprecated option '{}'. This configuration will be removed from Envoy soon. "
"Please see https://github.com/envoyproxy/envoy/blob/master/DEPRECATED.md for "
"details.",
field->name());
Copy link
Member

Choose a reason for hiding this comment

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

full_name() instead of name should be more helpful.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the tip - this is going to be even more useful!

if (fatal) {
throw ProtoValidationException(err, message);
} else {
ENVOY_LOG_MISC(warn, "{}", err);
Copy link
Member

Choose a reason for hiding this comment

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

use config logger?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Which logger? The only other log macro in the util.cc used MISC so I didn't think any of the other log macros were suitable.

Copy link
Member

Choose a reason for hiding this comment

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

We could wrap in a class to provide access to the config logger (or maybe there is a more direct way?).

Copy link
Member

Choose a reason for hiding this comment

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

Just make MessageUtil inherit Loggable and it should be good (it only provides static method)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, so you want it to inherit from Logger::LoggableLogger::Id::config

Done, though I think ENVOY_LOG_MISC might make more sense, given that someone could put non-config related proto utilities in source/common/protobuf/utility.h

That said the main uses of proto are config and gRPC which has its own directories, so it's fine for now.

}

// If this is a message, recurse to check for deprecated fields in the sub-message.
switch (field->cpp_type()) {
Copy link
Member

Choose a reason for hiding this comment

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

just if (field->cpp_type == Protobuf::FieldDescriptor::CPPTYPE_MESSAGE)?

@htuch
Copy link
Member

htuch commented Jan 29, 2019

I think for things like bind_to_port, we should keep it deprecated, since we want to encourage users to migrate away. I think warning is ideal, critical is too high for use of a feature the is deprecated but not dead.

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 modulo comments, nice to see that there is first-class support for the deprecated annotation in reflection.

"Using deprecated option 'inner_deprecated'.");
}

// Check that repeated sub-messages get validated.
Copy link
Member

Choose a reason for hiding this comment

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

Nit: preference for making these all separate TEST_F, since they don't share state and it's more self-documenting.

static void loadFromYaml(const std::string& yaml, Protobuf::Message& message);
static void loadFromFile(const std::string& path, Protobuf::Message& message);

static void checkForDeprecation(const Protobuf::Message& message, bool fatal) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: prefer warn_only vs. fatal, since it's not fatal, it's raising an exception which could be handled in other ways at a call-site (even though you probably only plan on using it for fatal..).

@alyssawilk
Copy link
Contributor Author

@htuch my only concern there is potentially causing confusion for folks who get the warning that they should migrate but can't migrate yet.

That said on both the deprecated_v1 fields I'm dubious about, I think the only folks who can't move are Istio, so as long as they know the logged warning doesn't change our deprecation plans I guess we're good? Tagging @PiotrSikora for Istio comms to avoid any confusion on their part and I'll add a release note as well.

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@htuch
Copy link
Member

htuch commented Jan 30, 2019

Also @costinm for Istio viz.

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 modulo nits and unresolved comments from @lizan.

EXPECT_THROW_WITH_REGEX(
MessageUtil::checkForDeprecation(base, false), ProtoValidationException,
"Using deprecated option 'envoy.test.deprecation_test.Base.is_deprecated'.");
}
Copy link
Member

Choose a reason for hiding this comment

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

Nit: no need for the inner braces in all these TESTs..

}

TEST(DeprecatedFields, SubMessageDeprecated) {
// Check that repeated sub-messages get validated.
Copy link
Member

Choose a reason for hiding this comment

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

Nit: move these comments about the TEST.

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk alyssawilk dismissed ggreenway’s stale review January 31, 2019 16:23

comments addressed

enum class ProtoUnknownFieldsMode { Strict, Allow };

class MessageUtil {
class MessageUtil : public Logger::Loggable<Logger::Id::config> {
Copy link
Member

Choose a reason for hiding this comment

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

I agree with @alyssawilk, this is not in a config related file/directory, so would prefer not to log with this. Can we pass logger as a parameter, or maybe subclass MessageUtil in config/ with a logger mixin?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or go back to MISC_LOG and claim there's precedent :-D

Copy link
Member

Choose a reason for hiding this comment

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

Ok that's fair :)

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
htuch
htuch previously approved these changes Jan 31, 2019
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!

lizan
lizan previously approved these changes Jan 31, 2019
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk alyssawilk dismissed stale reviews from lizan and htuch via 9abec4e February 4, 2019 14:52
@alyssawilk
Copy link
Contributor Author

Had to sync for merge conflict - I'd appreciate one last LGTM!

@alyssawilk alyssawilk merged commit bb9735a into envoyproxy:master Feb 4, 2019
fredlas pushed a commit to fredlas/envoy that referenced this pull request Mar 5, 2019
…xy#5760)

Risk Level: Low (logging only)
Testing: new unit tests
Docs Changes: n/a
Release Notes: not included
Part of envoyproxy#5559

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Fred Douglas <fredlas@google.com>
@alyssawilk alyssawilk deleted the runtime branch May 7, 2019 19:11
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.

4 participants