mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-08-24 03:11:11 +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});
|
}, 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); },
|
[&scheduler](auto func, auto window) { scheduler.scheduleEvery(std::move(func), window); },
|
||||||
BCLog::RATELIMIT_MAX_BYTES,
|
BCLog::RATELIMIT_MAX_BYTES,
|
||||||
BCLog::RATELIMIT_WINDOW));
|
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>));
|
memusage::MallocUsage(sizeof(memusage::list_node<BCLog::Logger::BufferedLog>));
|
||||||
}
|
}
|
||||||
|
|
||||||
BCLog::LogRateLimiter::LogRateLimiter(
|
BCLog::LogRateLimiter::LogRateLimiter(uint64_t max_bytes, std::chrono::seconds reset_window)
|
||||||
SchedulerFunction scheduler_func,
|
: m_max_bytes{max_bytes}, m_reset_window{reset_window} {}
|
||||||
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(
|
BCLog::LogRateLimiter::Status BCLog::LogRateLimiter::Consume(
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <source_location>
|
#include <source_location>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -130,6 +131,7 @@ namespace BCLog {
|
|||||||
std::unordered_map<std::source_location, Stats, SourceLocationHasher, SourceLocationEqual> m_source_locations GUARDED_BY(m_mutex);
|
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.
|
//! Whether any log locations are suppressed. Cached view on m_source_locations for performance reasons.
|
||||||
std::atomic<bool> m_suppression_active{false};
|
std::atomic<bool> m_suppression_active{false};
|
||||||
|
LogRateLimiter(uint64_t max_bytes, std::chrono::seconds reset_window);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using SchedulerFunction = std::function<void(std::function<void()>, std::chrono::milliseconds)>;
|
using SchedulerFunction = std::function<void(std::function<void()>, std::chrono::milliseconds)>;
|
||||||
@@ -141,7 +143,10 @@ namespace BCLog {
|
|||||||
* location.
|
* location.
|
||||||
* @param reset_window Time window after which the stats are reset.
|
* @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.
|
//! Maximum number of bytes logged per location per window.
|
||||||
const uint64_t m_max_bytes;
|
const uint64_t m_max_bytes;
|
||||||
//! Interval after which the window is reset.
|
//! Interval after which the window is reset.
|
||||||
@@ -186,7 +191,7 @@ namespace BCLog {
|
|||||||
size_t m_buffer_lines_discarded GUARDED_BY(m_cs){0};
|
size_t m_buffer_lines_discarded GUARDED_BY(m_cs){0};
|
||||||
|
|
||||||
//! Manages the rate limiting of each log location.
|
//! 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`.
|
//! Category-specific log level. Overrides `m_log_level`.
|
||||||
std::unordered_map<LogFlags, Level> m_category_log_levels GUARDED_BY(m_cs);
|
std::unordered_map<LogFlags, Level> m_category_log_levels GUARDED_BY(m_cs);
|
||||||
@@ -255,7 +260,7 @@ namespace BCLog {
|
|||||||
/** Only for testing */
|
/** Only for testing */
|
||||||
void DisconnectTestLogger() EXCLUSIVE_LOCKS_REQUIRED(!m_cs);
|
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);
|
StdLockGuard scoped_lock(m_cs);
|
||||||
m_limiter = std::move(limiter);
|
m_limiter = std::move(limiter);
|
||||||
|
@@ -69,6 +69,7 @@ struct LogSetup : public BasicTestingSetup {
|
|||||||
|
|
||||||
LogInstance().SetLogLevel(BCLog::Level::Debug);
|
LogInstance().SetLogLevel(BCLog::Level::Debug);
|
||||||
LogInstance().SetCategoryLogLevel({});
|
LogInstance().SetCategoryLogLevel({});
|
||||||
|
LogInstance().SetRateLimiting(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
~LogSetup()
|
~LogSetup()
|
||||||
@@ -82,6 +83,7 @@ struct LogSetup : public BasicTestingSetup {
|
|||||||
LogInstance().m_log_sourcelocations = prev_log_sourcelocations;
|
LogInstance().m_log_sourcelocations = prev_log_sourcelocations;
|
||||||
LogInstance().SetLogLevel(prev_log_level);
|
LogInstance().SetLogLevel(prev_log_level);
|
||||||
LogInstance().SetCategoryLogLevel(prev_category_levels);
|
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};
|
uint64_t max_bytes{1024};
|
||||||
auto reset_window{1min};
|
auto reset_window{1min};
|
||||||
auto sched_func = [&scheduler](auto func, auto window) { scheduler.scheduleEvery(std::move(func), window); };
|
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;
|
using Status = BCLog::LogRateLimiter::Status;
|
||||||
auto source_loc_1{std::source_location::current()};
|
auto source_loc_1{std::source_location::current()};
|
||||||
@@ -405,8 +408,7 @@ BOOST_FIXTURE_TEST_CASE(logging_filesize_rate_limit, LogSetup)
|
|||||||
CScheduler scheduler{};
|
CScheduler scheduler{};
|
||||||
scheduler.m_service_thread = std::thread([&] { scheduler.serviceQueue(); });
|
scheduler.m_service_thread = std::thread([&] { scheduler.serviceQueue(); });
|
||||||
auto sched_func = [&scheduler](auto func, auto window) { scheduler.scheduleEvery(std::move(func), window); };
|
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(BCLog::LogRateLimiter::Create(sched_func, 1024 * 1024, 20s));
|
||||||
LogInstance().SetRateLimiting(std::move(limiter));
|
|
||||||
|
|
||||||
// Log 1024-character lines (1023 plus newline) to make the math simple.
|
// Log 1024-character lines (1023 plus newline) to make the math simple.
|
||||||
std::string log_message(1023, 'a');
|
std::string log_message(1023, 'a');
|
||||||
|
Reference in New Issue
Block a user