Skip to content

Conversation

alyssawilk
Copy link
Contributor

After a whole bunch of macro shenanigans (several variants uploaded) replacing RELEASE_ASSERT(CONDITIONAL) with RELEASE_ASSERT(CONDITIONAL, REASON)

The really ugly VA_ARG macros would allow folks to easily slip in RELEASE_ASSERTS without details, and there were only 133 RELEASE_ASSERTS in the code base.

For folks with downstream RELEASE_ASSERTS I suggest
for file in grep -rIl RELEASE_ASSERT; do sed -i 's/(RELEASE_ASSERT.).;/\1, "");/' $file; done
with a bonus grep -rIl "RELEASE_ASSERT[^;]
$" to track down multi-line stragglers.

Risk Level: Medium (may break downstream builds)
Testing: All tests pass, new assert test.
Docs Changes: n/a
Release Notes: n/a

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk alyssawilk requested a review from zuercher as a code owner July 11, 2018 18:09
@alyssawilk
Copy link
Contributor Author

For anyone interested in the details, the first pass with RELEASE_ASSERT_SELECTOR was fairly readable, but unfortunately did early eval of X, which meant error messages went from IMO more
useful rc != EAGAIN to rc != 11.

After [more time than I care to admit] playing with the C++ preprocessor I got a monster series of about 8 more macros that did exactly what I wanted it to do, and then spent another [still longer than I want to admit] trying and failing to simplify it without unsetting the delicate balance of preprocessing order. Having utterly failed to do that, I opted to keep things simple and just resorted to sed. :-P

I'm totally amenable to reverting to either prior version so feel free to bikeshed away :-)

@alyssawilk
Copy link
Contributor Author

@htuch @ggreenway @mattklein123 as having shown interest on #3829

ENVOY_LOG_TO_LOGGER(Envoy::Logger::Registry::getLog(Envoy::Logger::Id::assert), critical, \
"assert failure: {}", #X); \
"assert failure: {}.{}{}", #X, \
details.length() == 0 ? "" : " Details: ", DETAILS); \
Copy link
Member

Choose a reason for hiding this comment

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

details.empty()

Copy link
Member

Choose a reason for hiding this comment

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

Also, s/DETAILS/details/.

*
* The new style of release assert is of the form
* RELEASE_ASSERT(foo == bar, "reason foo should actually be bar");
* new uses of RELEASE_ASSERT are strongly encouraged to supply a verbose
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 this comment applies to one of your previous iterations. This is a required param of the macro, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this is correct, explaining the old macro and legacy ""s. I've made wording stronger for "include details already" :-)

do { \
if (!(X)) { \
std::string details = DETAILS; \
Copy link
Member

Choose a reason for hiding this comment

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

Could this be an absl::string_view to avoid copying? Or does that break things?

Copy link
Member

Choose a reason for hiding this comment

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

Why do you want to optimize copy on a termination path?!

Copy link
Member

Choose a reason for hiding this comment

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

I would recommend writing this as const std::string& details = (DETAILS);

Copy link
Member

Choose a reason for hiding this comment

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

Ha, good point; I think that comment just came out of habit.

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

(still looking at coverage failure)

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.

Nice

do { \
if (!(X)) { \
std::string details = DETAILS; \
Copy link
Member

Choose a reason for hiding this comment

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

I would recommend writing this as const std::string& details = (DETAILS);

ENVOY_LOG_TO_LOGGER(Envoy::Logger::Registry::getLog(Envoy::Logger::Id::assert), critical, \
"assert failure: {}", #X); \
"assert failure: {}.{}{}", #X, \
details.length() == 0 ? "" : " Details: ", DETAILS); \
Copy link
Member

Choose a reason for hiding this comment

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

Also, s/DETAILS/details/.

*/
#define RELEASE_ASSERT(X) \
#define RELEASE_ASSERT(X, DETAILS) \
Copy link
Member

Choose a reason for hiding this comment

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

Do you want ... and __VA_ARGS__ here to support arbitrary fmtlib?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I figured we'd have folks do fmt:: inline as I did in the unit tests.

Copy link
Member

@htuch htuch Jul 11, 2018

Choose a reason for hiding this comment

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

I think it's like a one line change in the macro to have it do the magic for the user (and default to something sane), e.g. (untested):

#define RELEASE_ASSERT(X, DETAILS,...) \
...
  ENVOY_LOG_TO_LOGGER(Envoy::Logger::Registry::getLog(Envoy::Logger::Id::assert), critical,  "assert failure: {}.{}{}", #X, details.empty() ? "" : " Details: ", fmt::format(details, ##__VA_ARGS__)); \
...

see https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not convinced it's that simple. It could be you have some minor typo, but adding in the vargs as you proposed lands me an
assert error argument index out of range
Meanwhile I find
{ RELEASE_ASSERT(0 == EAGAIN, fmt::format("using {}", "fmt")); },
more readable than
{ RELEASE_ASSERT(0 == EAGAIN, "native {}", "fmt"); },
because it's not inherently a logging macro.

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.

LGTM once tests are passing. Nice!

ggreenway
ggreenway previously approved these changes Jul 11, 2018
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.

LGTM

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@htuch htuch merged commit 6881200 into envoyproxy:master Jul 11, 2018
@lizan
Copy link
Member

lizan commented Jul 11, 2018

Somehow there is a missed RELEASE_ASSERT, master doesn't build...
https://github.com/envoyproxy/envoy/blob/master/source/extensions/filters/network/thrift_proxy/transport_impl.cc#L63

snowp pushed a commit to snowp/envoy that referenced this pull request Jul 12, 2018
* origin/master:
  config: making v2-config-only a boolean flag (envoyproxy#3847)
  lc trie: add exclusive flag. (envoyproxy#3825)
  upstream: introduce PriorityStateManager, refactor EDS (envoyproxy#3783)
  test: deflaking header_integration_test (envoyproxy#3849)
  http: new style WebSockets, where headers and data are processed by the filter chain. (envoyproxy#3776)
  common: minor doc updates (envoyproxy#3845)
  fix master build (envoyproxy#3844)
  logging: Requiring details for RELEASE_ASSERT (envoyproxy#3842)
  test: add test for consistency of RawStatData internal memory representation (envoyproxy#3843)
  common: jittered backoff implementation (envoyproxy#3791)
  format: run buildifier on .bzl files. (envoyproxy#3824)
  Support mutable metadata for endpoints (envoyproxy#3814)
  test: deflaking a test, improving debugability (envoyproxy#3829)
  Update ApiConfigSource docs with grpc_services only for GRPC configs (envoyproxy#3834)
  Add hard-coded /hot_restart_version test (envoyproxy#3832)
  healthchecks: Add interval_jitter_percent healthcheck option (envoyproxy#3816)

Signed-off-by: Snow Pettersen <snowp@squareup.com>
htuch pushed a commit that referenced this pull request Aug 3, 2018
Allowing ASSERT to optionally use the details added to RELEASE_ASSERT in #3842

Risk Level: Low
Testing: bazel //test/..., unit tests of new and old behavior.
Docs Changes: n/a
Release Notes: n/a

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk alyssawilk deleted the logging branch November 28, 2018 16:02
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