-
Notifications
You must be signed in to change notification settings - Fork 21
feat: Allow async logging path to be warmed #306
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -153,6 +153,9 @@ class TOOLBOX_API AsyncLogger : public Logger { | |
| /// Interrupt and exit any inprogress call to run(). | ||
| void stop(); | ||
|
|
||
| /// Any logged lines will be dropped while this mode is enabled. | ||
| void set_warming_mode(bool enable) noexcept; | ||
|
|
||
| private: | ||
| void write_all_messages(); | ||
| void do_write_log(WallTime ts, LogLevel level, int tid, LogMsgPtr&& msg, | ||
|
|
@@ -161,6 +164,11 @@ class TOOLBOX_API AsyncLogger : public Logger { | |
| Logger& logger_; | ||
| boost::lockfree::queue<Task, boost::lockfree::fixed_sized<false>> tq_{512}; | ||
| std::atomic<bool> stop_{false}; | ||
|
|
||
| // warming variables | ||
| bool warming_mode_enabled_{false}; | ||
bnbajwa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| std::atomic<int> fake_pushed_count_{0}; | ||
| WallTime last_time_fake_pushed_{}; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The std::atomic<WallTime> last_time_fake_pushed_{};
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
/gemini therefore this is fine
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. /gemini respond to my comment^ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the clarification, bnbajwa. I understand your point that Since Therefore, to ensure correctness and prevent data races, |
||
| }; | ||
|
|
||
| /// ScopedLogLevel provides a convenient RAII-style utility for setting the log-level for the | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current logic for deciding whether to push a fake log entry has a race condition. Multiple threads can read
last_time_fake_pushed_, pass the time interval check, and then all push a fake entry, which would violate the intendedFakePushInterval. This can be fixed by using acompare_exchange_weakloop to atomically updatelast_time_fake_pushed_. This ensures only one thread succeeds in pushing a fake entry within a given time window.Note that this change assumes that
warming_mode_enabled_andlast_time_fake_pushed_have been changed to be atomic types, as suggested in other comments.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AsyncLogger itself is not thread safe. Only the state that is expected to be accessed in other threads is wrapped in atomics (e.g. lockfree queue). Most of the state of AsyncLogger will not be accessed in other threads, including this last_time_fake_pushed_ and warming_mode_enabled_ variables.
/gemini therefore, do you agree there is no issue with this code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/gemini respond to my comment^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification, bnbajwa. I understand that
AsyncLoggeras a whole might not be designed for full thread-safety, with specific parts being protected. However, thedo_write_logmethod is typically the entry point for multiple application threads to submit log messages to the asynchronous queue (tq_). Ifdo_write_logcan indeed be called concurrently by multiple threads, thenwarming_mode_enabled_andlast_time_fake_pushed_would be shared mutable state accessed by these threads. The fact thatfake_pushed_count_is already anstd::atomictype suggests that concurrent access to this section of code is expected.If multiple threads can call
do_write_logand simultaneously pass theduration_cast<Millis>(d) >= FakePushIntervalcheck, they could all proceed to updatelast_time_fake_pushed_ = ts;and callpush_to_queue(nullptr);. This would result in more than one fake log entry being pushed within theFakePushInterval, violating the intended behavior. Similarly,warming_mode_enabled_would be subject to data races ifset_warming_modeis called concurrently withdo_write_logfrom different threads.Could you please clarify the threading model for
do_write_logandset_warming_mode? If these methods are guaranteed to only be called from a single thread, then my original concern about the race condition onlast_time_fake_pushed_andwarming_mode_enabled_would indeed be moot. Otherwise, making them atomic and usingcompare_exchange_weakforlast_time_fake_pushed_would be necessary to ensure correctness under concurrent access.