mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-08-23 21:32:33 +02:00
log: make m_limiter a shared_ptr
This allows us to safely and explicitly manage the dual dependency
on the limiter: one for the Logger, and one for the CScheduler.
Github-Pull: #33011
Rebased-From: 3d630c2544
This commit is contained in:
@@ -1384,7 +1384,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
}
|
||||
}, std::chrono::minutes{5});
|
||||
|
||||
LogInstance().SetRateLimiting(std::make_unique<BCLog::LogRateLimiter>(
|
||||
LogInstance().SetRateLimiting(BCLog::LogRateLimiter::Create(
|
||||
[&scheduler](auto func, auto window) { scheduler.scheduleEvery(std::move(func), window); },
|
||||
BCLog::RATELIMIT_MAX_BYTES,
|
||||
BCLog::RATELIMIT_WINDOW));
|
||||
|
@@ -371,12 +371,19 @@ static size_t MemUsage(const BCLog::Logger::BufferedLog& buflog)
|
||||
memusage::MallocUsage(sizeof(memusage::list_node<BCLog::Logger::BufferedLog>));
|
||||
}
|
||||
|
||||
BCLog::LogRateLimiter::LogRateLimiter(
|
||||
SchedulerFunction scheduler_func,
|
||||
uint64_t max_bytes,
|
||||
std::chrono::seconds reset_window) : m_max_bytes{max_bytes}, m_reset_window{reset_window}
|
||||
BCLog::LogRateLimiter::LogRateLimiter(uint64_t max_bytes, std::chrono::seconds reset_window)
|
||||
: m_max_bytes{max_bytes}, m_reset_window{reset_window} {}
|
||||
|
||||
std::shared_ptr<BCLog::LogRateLimiter> BCLog::LogRateLimiter::Create(
|
||||
SchedulerFunction&& scheduler_func, uint64_t max_bytes, std::chrono::seconds reset_window)
|
||||
{
|
||||
scheduler_func([this] { Reset(); }, reset_window);
|
||||
auto limiter{std::shared_ptr<LogRateLimiter>(new LogRateLimiter(max_bytes, reset_window))};
|
||||
std::weak_ptr<LogRateLimiter> weak_limiter{limiter};
|
||||
auto reset = [weak_limiter] {
|
||||
if (auto shared_limiter{weak_limiter.lock()}) shared_limiter->Reset();
|
||||
};
|
||||
scheduler_func(reset, limiter->m_reset_window);
|
||||
return limiter;
|
||||
}
|
||||
|
||||
BCLog::LogRateLimiter::Status BCLog::LogRateLimiter::Consume(
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <source_location>
|
||||
#include <string>
|
||||
@@ -130,6 +131,7 @@ namespace BCLog {
|
||||
std::unordered_map<std::source_location, Stats, SourceLocationHasher, SourceLocationEqual> m_source_locations GUARDED_BY(m_mutex);
|
||||
//! Whether any log locations are suppressed. Cached view on m_source_locations for performance reasons.
|
||||
std::atomic<bool> m_suppression_active{false};
|
||||
LogRateLimiter(uint64_t max_bytes, std::chrono::seconds reset_window);
|
||||
|
||||
public:
|
||||
using SchedulerFunction = std::function<void(std::function<void()>, std::chrono::milliseconds)>;
|
||||
@@ -141,7 +143,10 @@ namespace BCLog {
|
||||
* location.
|
||||
* @param reset_window Time window after which the stats are reset.
|
||||
*/
|
||||
LogRateLimiter(SchedulerFunction scheduler_func, uint64_t max_bytes, std::chrono::seconds reset_window);
|
||||
static std::shared_ptr<LogRateLimiter> Create(
|
||||
SchedulerFunction&& scheduler_func,
|
||||
uint64_t max_bytes,
|
||||
std::chrono::seconds reset_window);
|
||||
//! Maximum number of bytes logged per location per window.
|
||||
const uint64_t m_max_bytes;
|
||||
//! Interval after which the window is reset.
|
||||
@@ -186,7 +191,7 @@ namespace BCLog {
|
||||
size_t m_buffer_lines_discarded GUARDED_BY(m_cs){0};
|
||||
|
||||
//! Manages the rate limiting of each log location.
|
||||
std::unique_ptr<LogRateLimiter> m_limiter GUARDED_BY(m_cs);
|
||||
std::shared_ptr<LogRateLimiter> m_limiter GUARDED_BY(m_cs);
|
||||
|
||||
//! Category-specific log level. Overrides `m_log_level`.
|
||||
std::unordered_map<LogFlags, Level> m_category_log_levels GUARDED_BY(m_cs);
|
||||
@@ -255,7 +260,7 @@ namespace BCLog {
|
||||
/** Only for testing */
|
||||
void DisconnectTestLogger() EXCLUSIVE_LOCKS_REQUIRED(!m_cs);
|
||||
|
||||
void SetRateLimiting(std::unique_ptr<LogRateLimiter>&& limiter) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
|
||||
void SetRateLimiting(std::shared_ptr<LogRateLimiter> limiter) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
|
||||
{
|
||||
StdLockGuard scoped_lock(m_cs);
|
||||
m_limiter = std::move(limiter);
|
||||
|
@@ -69,6 +69,7 @@ struct LogSetup : public BasicTestingSetup {
|
||||
|
||||
LogInstance().SetLogLevel(BCLog::Level::Debug);
|
||||
LogInstance().SetCategoryLogLevel({});
|
||||
LogInstance().SetRateLimiting(nullptr);
|
||||
}
|
||||
|
||||
~LogSetup()
|
||||
@@ -82,6 +83,7 @@ struct LogSetup : public BasicTestingSetup {
|
||||
LogInstance().m_log_sourcelocations = prev_log_sourcelocations;
|
||||
LogInstance().SetLogLevel(prev_log_level);
|
||||
LogInstance().SetCategoryLogLevel(prev_category_levels);
|
||||
LogInstance().SetRateLimiting(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -309,7 +311,8 @@ BOOST_AUTO_TEST_CASE(logging_log_rate_limiter)
|
||||
uint64_t max_bytes{1024};
|
||||
auto reset_window{1min};
|
||||
auto sched_func = [&scheduler](auto func, auto window) { scheduler.scheduleEvery(std::move(func), window); };
|
||||
BCLog::LogRateLimiter limiter{sched_func, max_bytes, reset_window};
|
||||
auto limiter_{BCLog::LogRateLimiter::Create(sched_func, max_bytes, reset_window)};
|
||||
auto& limiter{*limiter_};
|
||||
|
||||
using Status = BCLog::LogRateLimiter::Status;
|
||||
auto source_loc_1{std::source_location::current()};
|
||||
@@ -405,8 +408,7 @@ BOOST_FIXTURE_TEST_CASE(logging_filesize_rate_limit, LogSetup)
|
||||
CScheduler scheduler{};
|
||||
scheduler.m_service_thread = std::thread([&] { scheduler.serviceQueue(); });
|
||||
auto sched_func = [&scheduler](auto func, auto window) { scheduler.scheduleEvery(std::move(func), window); };
|
||||
auto limiter = std::make_unique<BCLog::LogRateLimiter>(sched_func, 1024 * 1024, 20s);
|
||||
LogInstance().SetRateLimiting(std::move(limiter));
|
||||
LogInstance().SetRateLimiting(BCLog::LogRateLimiter::Create(sched_func, 1024 * 1024, 20s));
|
||||
|
||||
// Log 1024-character lines (1023 plus newline) to make the math simple.
|
||||
std::string log_message(1023, 'a');
|
||||
|
Reference in New Issue
Block a user