Skip to content

Commit 371fa5d

Browse files
committed
Review feedback.
- 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 <[email protected]>
1 parent d8783b7 commit 371fa5d

File tree

2 files changed

+17
-24
lines changed

2 files changed

+17
-24
lines changed

source/common/common/logger.h

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#pragma once
22

3-
#include <chrono>
43
#include <cstdint>
54
#include <memory>
65
#include <string>
@@ -422,18 +421,10 @@ template <Id id> class Loggable {
422421
} \
423422
} while (0)
424423

425-
// This is to get us to pass the format check. We reference a real-world time source here.
426-
// I think it's not easy to mock/simulate time here as it stands today anyway.
427-
using t_logclock = std::chrono::steady_clock; // NOLINT
428-
429-
#define ENVOY_LOG_PERIODIC(LEVEL, CHRONO_DURATION, ...) \
424+
#define ENVOY_LOG_WITH_BACKOFF(LEVEL, ...) \
430425
do { \
431-
static auto* last_hit = new std::atomic<uint64_t>(); \
432-
auto last = last_hit->load(); \
433-
const auto now = t_logclock::now().time_since_epoch().count(); \
434-
if ((now - last) > \
435-
std::chrono::duration_cast<std::chrono::nanoseconds>(CHRONO_DURATION).count() && \
436-
last_hit->compare_exchange_strong(last, now)) { \
426+
static auto* count = new std::atomic<uint64_t>(); \
427+
if (__builtin_popcount(1 + count->fetch_add(1)) == 1) { \
437428
ENVOY_LOG(LEVEL, ##__VA_ARGS__); \
438429
} \
439430
} while (0)

test/common/common/log_macros_test.cc

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#include <chrono>
21
#include <functional>
32
#include <future>
43
#include <iostream>
@@ -128,15 +127,18 @@ void spamCall(std::function<void()>&& call_to_spam, const uint32_t num_threads)
128127
std::promise<void> signal_all_threads_running;
129128
std::shared_future<void> future(signal_all_threads_running.get_future());
130129

130+
std::atomic<uint32_t> runcount = 0;
131131
for (auto& thread : threads) {
132-
thread = std::thread([future, &call_to_spam] {
132+
thread = std::thread([future, &call_to_spam, &runcount] {
133+
runcount++;
133134
future.wait();
134135
call_to_spam();
135136
});
136137
}
137138
// Allow threads to accrue on future.wait() to maximize concurrency on the call
138139
// we are testing.
139-
sleep(1);
140+
while (runcount != num_threads) {
141+
}
140142
signal_all_threads_running.set_value();
141143
for (std::thread& thread : threads) {
142144
thread.join();
@@ -152,7 +154,7 @@ TEST(Logger, SparseLogMacros) {
152154
void logSomethingBelowLogLevelOnce() { ENVOY_LOG_ONCE(debug, "foo3 '{}'", evaluations()++); }
153155
void logSomethingThrice() { ENVOY_LOG_FIRST_N(error, 3, "foo4 '{}'", evaluations()++); }
154156
void logEverySeventh() { ENVOY_LOG_EVERY_NTH(error, 7, "foo5 '{}'", evaluations()++); }
155-
void logEverySecond() { ENVOY_LOG_PERIODIC(error, 1s, "foo6 '{}'", evaluations()++); }
157+
void logWithBackoff() { ENVOY_LOG_WITH_BACKOFF(error, "foo6 '{}'", evaluations()++); }
156158
std::atomic<int32_t>& evaluations() { MUTABLE_CONSTRUCT_ON_FIRST_USE(std::atomic<int32_t>); };
157159
};
158160
constexpr uint32_t kNumThreads = 100;
@@ -181,20 +183,20 @@ TEST(Logger, SparseLogMacros) {
181183
// (100 threads / log every 7th) + 1s = 15 more evaluations upon logging very 7th.
182184
EXPECT_EQ(20, helper.evaluations());
183185

184-
// So use our knowledge that spamCall will sleep 1 second in the following lines:
185-
// We expect one log entry / second. Therefore each spamCall ought to result in one
186-
// more evaluation. This depends on real time and not sim time, hopefully 1 second
187-
// is enough to not introduce flakes in practice.
188-
spamCall([&helper]() { helper.logEverySecond(); }, kNumThreads);
186+
helper.logWithBackoff();
187+
// First call ought to propagate.
189188
EXPECT_EQ(21, helper.evaluations());
190-
spamCall([&helper]() { helper.logEverySecond(); }, kNumThreads);
191-
EXPECT_EQ(22, helper.evaluations());
189+
190+
spamCall([&helper]() { helper.logWithBackoff(); }, kNumThreads);
191+
// 64 is the highest power of two that fits when kNumThreads == 100.
192+
// We should log on 2, 4, 8, 16, 32, 64, which means we can expect to add 6 more evaluations.
193+
EXPECT_EQ(27, helper.evaluations());
192194

193195
spamCall([&helper]() { helper.logSomethingBelowLogLevelOnce(); }, kNumThreads);
194196
// Without fine-grained logging, we shouldn't observe additional argument evaluations
195197
// for log lines below the configured log level.
196198
// TODO(#12885): fancy logger shouldn't always evaluate variadic macro arguments.
197-
EXPECT_EQ(::Envoy::Logger::Context::useFancyLogger() ? 23 : 22, helper.evaluations());
199+
EXPECT_EQ(::Envoy::Logger::Context::useFancyLogger() ? 28 : 27, helper.evaluations());
198200
}
199201

200202
TEST(RegistryTest, LoggerWithName) {

0 commit comments

Comments
 (0)