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

Add ENVOY_LOG_PERIODIC #12961

Merged
merged 7 commits into from
Sep 9, 2020
Merged

Add ENVOY_LOG_PERIODIC #12961

merged 7 commits into from
Sep 9, 2020

Conversation

oschaaf
Copy link
Member

@oschaaf oschaaf commented Sep 2, 2020

Follow up to #12830 with another sparse log variant.
The periodic version relies on a real world time source, which can
be discussed separately here.

Signed-off-by: Otto van der Schaaf oschaaf@we-amp.com

Risk Level: Low
Testing: Unit tests

Follow up to envoyproxy#12830 with another sparse log variant.
The periodic version relies on a real world time source, which can
be discussed separately here.

Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
@oschaaf
Copy link
Member Author

oschaaf commented Sep 2, 2020

/assign htuch
/cc @ggreenway

source/common/common/logger.h Outdated Show resolved Hide resolved
test/common/common/log_macros_test.cc Outdated Show resolved Hide resolved
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, but quick check with @jmarantz on whether it would make sense to have a time singleton here for testing.

@jmarantz
Copy link
Contributor

jmarantz commented Sep 3, 2020

IMO I'd rather test with real-time here and not introduce singletons.

htuch
htuch previously approved these changes Sep 3, 2020
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!

source/common/common/logger.h Outdated Show resolved Hide resolved
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
source/common/common/logger.h Show resolved Hide resolved
ENVOY_LOG(LEVEL, ##__VA_ARGS__); \
if (ENVOY_LOG_COMP_LEVEL(ENVOY_LOGGER(), LEVEL)) { \
static auto* countdown = new std::atomic<uint64_t>(); \
if (countdown->fetch_add(1) < N) { \

Choose a reason for hiding this comment

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

The counter may eventually overflow. ;)

source/common/common/logger.h Show resolved Hide resolved
ENVOY_LOG(LEVEL, ##__VA_ARGS__); \
if (ENVOY_LOG_COMP_LEVEL(ENVOY_LOGGER(), LEVEL)) { \
static auto* count = new std::atomic<uint64_t>(); \
if (std::bitset<64>(1 + count->fetch_add(1)).count() == 1) { \

Choose a reason for hiding this comment

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

How about this kind of thing:

auto bits = count->fetch_add(1);
if ( bits && !(bits & (bits-1)) )

The unsigned type here is fine.
Any bitwise && of any power of 2 with a number less by 1 will give 0. No need to involve std::bitset and we get rid of that magic number too.

Copy link
Member Author

@oschaaf oschaaf Sep 4, 2020

Choose a reason for hiding this comment

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

I went with std::bitset because I think I remember it being compiled to something fast under the hood (__builtin_popcount?); but also - and this is probably subjective - I find it easier to grok. The +1 deserves a comment, e.g. // +1 because the first hit needs to be logged, but this imho this also wouldn't hurt with the -1 (or maybe the whole expression) in the variant you propose, depending on who the audience is?

Choose a reason for hiding this comment

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

Ok. Let's leave it be for now, no problemo. bitset.count() is readable, true.
Yes, __builtin_popcount for GCC and for LLVM it's a similar thing; which translates, depending on the platform, into about 2-3 cpu intructions, or into Kernighan’s algorithm (latter is slower than this little trick).

But you're right. To follow readibility guidelines i should've suggested a lambda at least here, sth like auto is_exactly_one_bit_set = [](const uint64_t bits) { return bits && !(bits & (bits-1)); };.

@glodomorski
Copy link

I'm still trying to figure out how relaxed these atomic ops we could make. We probably can be fine with memory_order_consume in some cases, and, depending on the platform, go with a logic based on compare_exchange_weak (like, do we even care for spurious failures in sparse logging?). With atomics running on default full sequential consistency (the default is memory_order_seq_cst everywhere iirc) we may be introducing unnecessary sync points.
I'll bite deeper into it next week and hopefully be able to give some design ideas there. (Logging is always very interesting and complex topic.)

@oschaaf
Copy link
Member Author

oschaaf commented Sep 4, 2020

re: I'm still trying to figure out how relaxed these atomic ops we could make.

Yeah, I had some similar thoughts there: #12830 (comment)
But I wanted to propose the "straight forward" version first. But I was thinking that this could potentially go from being precise to tracking local to the thread and accepting the log line duplication. Or maybe approximate what was configured by relaxing barriers a lot, trading precision for speed.
Also, in a thread local variant, maybe working with an assumption that log lines will be hit evenly distributed across workers allows a different type of opportunity. For example guaranteeing caps by dividing the periodic log frequency by the number of workers.

@glodomorski
Copy link

Rgr. Pretty much exactly my thoughts. I won't be blocking you on this PR anymore, apologies. Let's get it going. I will read up on this and hopefully be able to contribute with more insight later on.

@oschaaf
Copy link
Member Author

oschaaf commented Sep 4, 2020

Rgr. Pretty much exactly my thoughts. I won't be blocking you on this PR anymore, apologies. Let's get it going. I will read up on this and hopefully be able to contribute with more insight later on.

Sure; super appreciate the feedback. If you want, we can discuss more on Slack too if you like, my handle is oschaaf.

Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
glodomorski
glodomorski previously approved these changes Sep 4, 2020
Copy link

@glodomorski glodomorski left a comment

Choose a reason for hiding this comment

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

approved, but keeping my eye on it ;)

if ((count->fetch_add(1) % N) == 0) { \
ENVOY_LOG(LEVEL, ##__VA_ARGS__); \
if (ENVOY_LOG_COMP_LEVEL(ENVOY_LOGGER(), LEVEL)) { \
static auto* count = new std::atomic<int64_t>(); \
Copy link
Member

Choose a reason for hiding this comment

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

Please switch these back to uint64_t. There is no possibility of overflow in 500+ years if we're bumping once a nanosecond..

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in 15819e6, except in the case where it's implied via the chrono count() call.

Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
htuch
htuch previously approved these changes Sep 9, 2020
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, thanks!

@htuch
Copy link
Member

htuch commented Sep 9, 2020

@oschaaf this looks like a legitimate build failure on Windows.

Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
@oschaaf
Copy link
Member Author

oschaaf commented Sep 9, 2020

@oschaaf this looks like a legitimate build failure on Windows.

Pushed efbabc5 to resolve a platform issue. Let's hope that resolves the CI error.

@htuch htuch merged commit 5187c34 into envoyproxy:master Sep 9, 2020
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