Conversation
Sometimes there's error flow control in the hot path that deserves logging, but plain logging there risks generating a large amount of log spam. It would be great to have a low-barrier and easy-to-consume way to emit a single or bounded number of log lines in these cases. This proposes a means to emit a single log line in those cases. Cross referencing Nighthawk issue to prompted this: envoyproxy/nighthawk#484 Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
|
/assign htuch |
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
|
Instead of once, what about the strategy used in ENVOY_BUG, which IIRC takes an action on powers of two counts of the event occurring, which results in exponential backoff. It gives more signal about whether something really only happened once, or is happening repeatedly. |
|
@ggreenway Thanks for the feedback; I should first get this simplest of cases to work, because CI indicates something isn't right. Having said that, and assuming I can fix that using the current approach: with respect to logging, I wonder if there's a silver bullet. Maybe we should consider offering a series so one can choose the best one? Some variants that I can think of:
and then maybe have flags or macro variants that set things up to configure strictness of the log gating of these macros; |
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
|
I had to amend the expected number of argument evaluations in the test for when fine grained logging is enabled / FANCY_LOG is used: when enabled, ENVOY_LOG will evaluate arguments regardless of the configured log level, whereas without the feature enabled, it will only evaluate when the log level filter doesn't squelch the message. I think that with 63b8a08 this will pass CI, but isn't it kind of tricky to have the argument evaluation behaviour change based on a flag? (because of potential side effects?) |
|
I think we don't want to evaluate ENVOY_LOG arguments if the log level doesn't match, this seems a bug in the fancy logger. |
|
@oschaaf can you file a bug and attach a TODO for fancy logger? Looking at how we use this kind of macro, how about a small modification to make this a bit more general and make this |
Periodic isn't perfect, as it reference a real-world time source directly. Depending on feedback / if it's a lot of work to do this right, it can be backed out for now. Will need a follow up with more tests for the new macros. Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
|
@htuch Added Regardless, to take this foward, I will need another follow to add more tests. But I'm curious to hear your thoughts on ps: rebuilding Envoy takes a while when touching |
|
Filed #12885 for the FANCY_LOG variadic macro evaluation issue observed here. |
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
| } | ||
| // Allow threads to accrue on future.wait() to maximize concurrency on the call | ||
| // we are testing. | ||
| sleep(1); |
There was a problem hiding this comment.
I think we want to avoid relying on real-time for tests. @jmarantz do you see a way to cleanly add an injected time source for the periodic macro that @oschaaf introduced in this PR? I'm thinking maybe we need a time source singleton for logging and do singleton injection, to avoid having to worry about time source at call site.
There was a problem hiding this comment.
In 371fa5d I rewrote the test to not rely on sleep().
Also backed out ENVOY_LOG_PERIODIC with the intent to do a follow up for adding that after this.
(so we can take a look and discuss that separately)
| ENVOY_LOG_FIRST_N(LEVEL, 1, ##__VA_ARGS__); \ | ||
| } while (0) | ||
|
|
||
| #define ENVOY_LOG_EVERY_NTH(LEVEL, N, ...) \ |
There was a problem hiding this comment.
As per earlier discussion, every Pow2 could be good as well.
There was a problem hiding this comment.
Oh yes good catch, my intent was actually to add that. Will do.
There was a problem hiding this comment.
Done, added ENVOY_LOG_WITH_BACKOFF in 371fa5d + tests
- Back out controversial ENVOY_LOG_PERIODIC, will split that out. - Don't rely on sleep() in tests - Add ENVOY_LOG_WITH_BACKOFF Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
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
Outdated
| } \ | ||
| } while (0) | ||
|
|
||
| #define ENVOY_LOG_WITH_BACKOFF(LEVEL, ...) \ |
There was a problem hiding this comment.
Nit: ENVOY_LOG_EVERY_POW_2 (more consistent with some internal terminology and clearer what backoff means).
| } | ||
| // Allow threads to accrue on future.wait() to maximize concurrency on the call | ||
| // we are testing. | ||
| while (runcount != num_threads) { |
There was a problem hiding this comment.
What about something like https://abseil.io/docs/cpp/guides/synchronization#barrier?
There was a problem hiding this comment.
Ooh, that's awesome. Switched to use absl::Barrier in de23f2a
- Use absl::Barrier - Rename ENVOY_LOG_WITH_BACKOFF to ENVOY_LOG_EVERY_POW_2 Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
…oposal Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
Signed-off-by: Otto van der Schaaf <oschaaf@we-amp.com>
|
Coverage flaked on an unrelated issue |
|
Retrying Azure Pipelines, to retry CircleCI checks, use |
|
/retest |
|
Retrying Azure Pipelines, to retry CircleCI checks, use |
ggreenway
left a comment
There was a problem hiding this comment.
Other than sorting out the thread-safety of static variables, I like this a lot.
|
|
||
| #define ENVOY_LOG_FIRST_N(LEVEL, N, ...) \ | ||
| do { \ | ||
| static auto* countdown = new std::atomic<uint64_t>(); \ |
There was a problem hiding this comment.
This isn't thread-safe. If two threads do this at the same time, there could be a leak. I think this ends up being better as static std::atomic<uint64_t> countdown;. Either the compiler will see that it is initialized by zeroing, and do so at program start, or it will double-zero the same memory by initializing multiple times, but should avoid a leak at least.
There was a problem hiding this comment.
Wouldn't that lead up to a potential deinitialization fiasco? I was following the lead of
envoy/source/common/common/macros.h
Line 32 in f2306b3
Reading up I am led to believe this would be thread safe since c++ 11 but I can't find a source that I would consider authorative,. Will dig some more.
There was a problem hiding this comment.
Relevant on the subject of leaking and stack vs heap allocation in the construct on first use idiom: Why doesn’t the Construct On First Use Idiom use a static object instead of a static pointer?
There was a problem hiding this comment.
https://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables has:
If multiple threads attempt to initialize the same static local variable concurrently, the initialization occurs exactly once (similar behavior can be obtained for arbitrary functions with std::call_once). Note: usual implementations of this feature use variants of the double-checked locking pattern, which reduces runtime overhead for already-initialized local statics to a single non-atomic boolean comparison.
There was a problem hiding this comment.
Did some reading, and you're correct. TIL something new about static initialization.
|
/wait |
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>
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. Risk Level: Low Testing: Unit tests Signed-off-by: Otto van der Schaaf oschaaf@we-amp.com
Sometimes there's error flow control in the hot path that deserves logging,
but plain logging there risks generating a large amount of log spam.
It would be great to have a low-barrier and easy-to-consume way to emit a single
or bounded number of log lines in these cases. This proposes a means to emit
a single log line in those cases.
Cross referencing Nighthawk issue to prompted this:
envoyproxy/nighthawk#484
Signed-off-by: Otto van der Schaaf oschaaf@we-amp.com
Risk Level: Low
Testing: Unit test