From f363fff109757840410d8d7b18947cc53e8744a6 Mon Sep 17 00:00:00 2001 From: Denis Ivaykin Date: Sat, 9 May 2015 22:30:05 +0200 Subject: [PATCH] async auto flush --- include/spdlog/async_logger.h | 9 ++++-- include/spdlog/details/async_log_helper.h | 37 ++++++++++++++++------ include/spdlog/details/async_logger_impl.h | 15 +++++---- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h index 7bcde900..a802b03c 100644 --- a/include/spdlog/async_logger.h +++ b/include/spdlog/async_logger.h @@ -58,19 +58,22 @@ public: const It& end, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function& worker_warmup_cb = nullptr); + const std::function& worker_warmup_cb = nullptr, + const std::chrono::milliseconds auto_flush_millis = std::chrono::milliseconds::zero()); async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function& worker_warmup_cb = nullptr); + const std::function& worker_warmup_cb = nullptr, + const std::chrono::milliseconds auto_flush_millis = std::chrono::milliseconds::zero()); async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function& worker_warmup_cb = nullptr); + const std::function& worker_warmup_cb = nullptr, + const std::chrono::milliseconds auto_flush_millis = std::chrono::milliseconds::zero()); protected: diff --git a/include/spdlog/details/async_log_helper.h b/include/spdlog/details/async_log_helper.h index 657c70bb..9fe38cff 100644 --- a/include/spdlog/details/async_log_helper.h +++ b/include/spdlog/details/async_log_helper.h @@ -65,7 +65,7 @@ class async_log_helper async_msg() = default; ~async_msg() = default; -async_msg(async_msg&& other) SPDLOG_NOEXCEPT: + async_msg(async_msg&& other) SPDLOG_NOEXCEPT: logger_name(std::move(other.logger_name)), level(std::move(other.level)), time(std::move(other.time)), @@ -119,7 +119,8 @@ public: const std::vector& sinks, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function& worker_warmup_cb = nullptr); + const std::function& worker_warmup_cb = nullptr, + const std::chrono::milliseconds auto_flush_millis = std::chrono::milliseconds::zero()); void log(const details::log_msg& msg); @@ -145,6 +146,9 @@ private: // worker thread warmup callback - one can set thread priority, affinity, etc const std::function _worker_warmup_cb; + // auto periodic sink flush parameter + const std::chrono::milliseconds _auto_flush_millis; + // worker thread std::thread _worker_thread; @@ -159,7 +163,7 @@ private: bool process_next_msg(clock::time_point& last_pop); // sleep,yield or return immediatly using the time passed since last message as a hint - static void sleep_or_yield(const clock::time_point& last_op_time); + static std::chrono::nanoseconds sleep_or_yield(const clock::time_point& last_op_time); }; } @@ -168,12 +172,13 @@ private: /////////////////////////////////////////////////////////////////////////////// // async_sink class implementation /////////////////////////////////////////////////////////////////////////////// -inline spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatter, const std::vector& sinks, size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb): +inline spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatter, const std::vector& sinks, size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds auto_flush_millis): _formatter(formatter), _sinks(sinks), _q(queue_size), _overflow_policy(overflow_policy), _worker_warmup_cb(worker_warmup_cb), + _auto_flush_millis(auto_flush_millis), _worker_thread(&async_log_helper::worker_loop, this) {} @@ -249,7 +254,12 @@ inline bool spdlog::details::async_log_helper::process_next_msg(clock::time_poin } else //empty queue { - sleep_or_yield(last_pop); + auto time_since_op = sleep_or_yield(last_pop); + if (_auto_flush_millis > std::chrono::milliseconds::zero() && time_since_op > _auto_flush_millis) + { + for (auto &s : _sinks) + s->flush(); + } } return true; } @@ -261,7 +271,7 @@ inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_f // sleep,yield or return immediatly using the time passed since last message as a hint -inline void spdlog::details::async_log_helper::sleep_or_yield(const clock::time_point& last_op_time) +inline std::chrono::nanoseconds spdlog::details::async_log_helper::sleep_or_yield(const clock::time_point& last_op_time) { using std::chrono::milliseconds; using namespace std::this_thread; @@ -270,18 +280,25 @@ inline void spdlog::details::async_log_helper::sleep_or_yield(const clock::time_ // spin upto 1 ms if (time_since_op <= milliseconds(1)) - return; + return time_since_op; // yield upto 10ms if (time_since_op <= milliseconds(10)) - return yield(); + { + yield(); + return time_since_op; + } // sleep for half of duration since last op if (time_since_op <= milliseconds(100)) - return sleep_for(time_since_op / 2); + { + sleep_for(time_since_op / 2); + return time_since_op; + } - return sleep_for(milliseconds(100)); + sleep_for(milliseconds(100)); + return time_since_op; } // throw if the worker thread threw an exception or not active diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h index e113e1d2..e6c21ec3 100644 --- a/include/spdlog/details/async_logger_impl.h +++ b/include/spdlog/details/async_logger_impl.h @@ -39,9 +39,10 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name, const It& end, size_t queue_size, const async_overflow_policy overflow_policy, - const std::function& worker_warmup_cb) : + const std::function& worker_warmup_cb, + const std::chrono::milliseconds auto_flush_millis) : logger(logger_name, begin, end), - _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, overflow_policy, worker_warmup_cb)) + _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, overflow_policy, worker_warmup_cb, auto_flush_millis)) { } @@ -49,15 +50,17 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const async_overflow_policy overflow_policy, - const std::function& worker_warmup_cb) : - async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb) {} + const std::function& worker_warmup_cb, + const std::chrono::milliseconds auto_flush_millis) : + async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, auto_flush_millis) {} inline spdlog::async_logger::async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size, const async_overflow_policy overflow_policy, - const std::function& worker_warmup_cb) : - async_logger(logger_name, { single_sink }, queue_size, overflow_policy, worker_warmup_cb) {} + const std::function& worker_warmup_cb, + const std::chrono::milliseconds auto_flush_millis) : + async_logger(logger_name, { single_sink }, queue_size, overflow_policy, worker_warmup_cb, auto_flush_millis) {} inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)