From 365d895482c70077c02aa36155c612ed158f0e18 Mon Sep 17 00:00:00 2001 From: Denis Ivaykin Date: Wed, 14 Jan 2015 15:35:01 -0600 Subject: [PATCH] discard policies on queue overflow --- include/spdlog/async_logger.h | 7 ++++--- include/spdlog/details/async_log_helper.h | 10 +++++++--- include/spdlog/details/async_logger_impl.h | 12 ++++++------ include/spdlog/details/registry.h | 10 ++++++---- include/spdlog/details/spdlog_impl.h | 4 ++-- include/spdlog/spdlog.h | 7 ++++++- 6 files changed, 31 insertions(+), 19 deletions(-) diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h index 7cb5cf13..94a0d100 100644 --- a/include/spdlog/async_logger.h +++ b/include/spdlog/async_logger.h @@ -38,6 +38,7 @@ #include #include "common.h" #include "logger.h" +#include "spdlog.h" namespace spdlog @@ -52,9 +53,9 @@ class async_logger :public logger { public: template - async_logger(const std::string& name, const It& begin, const It& end, size_t queue_size, const std::function& worker_warmup_cb = nullptr); - async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const std::function& worker_warmup_cb = nullptr); - async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size, const std::function& worker_warmup_cb = nullptr); + async_logger(const std::string& name, const It& begin, const It& end, size_t queue_size, const async_queue_overflow_policy overflow_policy = async_queue_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr); + async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const async_queue_overflow_policy overflow_policy = async_queue_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr); + async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size, const async_queue_overflow_policy overflow_policy = async_queue_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr); protected: diff --git a/include/spdlog/details/async_log_helper.h b/include/spdlog/details/async_log_helper.h index eecf804a..f82371b2 100644 --- a/include/spdlog/details/async_log_helper.h +++ b/include/spdlog/details/async_log_helper.h @@ -109,7 +109,7 @@ public: using clock = std::chrono::steady_clock; - async_log_helper(formatter_ptr formatter, const std::vector& sinks, size_t queue_size, const std::function& worker_warmup_cb = nullptr); + async_log_helper(formatter_ptr formatter, const std::vector& sinks, size_t queue_size, const async_queue_overflow_policy overflow_policy = async_queue_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr); void log(const details::log_msg& msg); //Stop logging and join the back thread @@ -125,6 +125,9 @@ private: // last exception thrown from the worker thread std::shared_ptr _last_workerthread_ex; + + // overflow policy + const async_queue_overflow_policy _overflow_policy; // worker thread warmup callback - one can set thread priority, affinity, etc const std::function _worker_warmup_cb; @@ -150,10 +153,11 @@ 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 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_queue_overflow_policy overflow_policy, const std::function& worker_warmup_cb): _formatter(formatter), _sinks(sinks), _q(queue_size), + _overflow_policy(overflow_policy), _worker_warmup_cb(worker_warmup_cb), _worker_thread(&async_log_helper::worker_loop, this) {} @@ -178,7 +182,7 @@ inline void spdlog::details::async_log_helper::log(const details::log_msg& msg) { throw_if_bad_worker(); async_msg new_msg(msg); - if (!_q.enqueue(std::move(new_msg))) + if (!_q.enqueue(std::move(new_msg)) && _overflow_policy != async_queue_overflow_policy::discard_log_msg) { auto last_op_time = clock::now(); do diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h index ec341578..ad84c76a 100644 --- a/include/spdlog/details/async_logger_impl.h +++ b/include/spdlog/details/async_logger_impl.h @@ -34,17 +34,17 @@ template -inline spdlog::async_logger::async_logger(const std::string& logger_name, const It& begin, const It& end, size_t queue_size, const std::function& worker_warmup_cb) : +inline spdlog::async_logger::async_logger(const std::string& logger_name, const It& begin, const It& end, size_t queue_size, const async_queue_overflow_policy overflow_policy, const std::function& worker_warmup_cb) : logger(logger_name, begin, end), - _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, worker_warmup_cb)) + _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, overflow_policy, worker_warmup_cb)) { } -inline spdlog::async_logger::async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const std::function& worker_warmup_cb) : - async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, worker_warmup_cb) {} +inline spdlog::async_logger::async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const async_queue_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) {} -inline spdlog::async_logger::async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size, const std::function& worker_warmup_cb) : - async_logger(logger_name, { single_sink }, queue_size, worker_warmup_cb) {} +inline spdlog::async_logger::async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size, const async_queue_overflow_policy overflow_policy, const std::function& worker_warmup_cb) : + async_logger(logger_name, { single_sink }, queue_size, overflow_policy, worker_warmup_cb) {} inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 9c25845f..0ac60dd0 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -62,7 +62,7 @@ public: return found->second; std::shared_ptr new_logger; if (_async_mode) - new_logger = std::make_shared(logger_name, sinks_begin, sinks_end, _async_q_size, _worker_warmup_cb); + new_logger = std::make_shared(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb); else new_logger = std::make_shared(logger_name, sinks_begin, sinks_end); @@ -120,12 +120,13 @@ public: l.second->set_level(log_level); } - void set_async_mode(size_t q_size, const std::function& worker_warmup_cb = nullptr) + void set_async_mode(size_t q_size, const async_queue_overflow_policy overflow_policy, const std::function& worker_warmup_cb) { std::lock_guard lock(_mutex); _async_mode = true; _async_q_size = q_size; - _worker_warmup_cb = worker_warmup_cb; + _overflow_policy = overflow_policy; + _worker_warmup_cb = worker_warmup_cb; } void set_sync_mode() @@ -151,7 +152,8 @@ private: level::level_enum _level = level::info; bool _async_mode = false; size_t _async_q_size = 0; - std::function _worker_warmup_cb = nullptr; + async_queue_overflow_policy _overflow_policy = async_queue_overflow_policy::block_retry; + std::function _worker_warmup_cb = nullptr; }; } } diff --git a/include/spdlog/details/spdlog_impl.h b/include/spdlog/details/spdlog_impl.h index e1e6a5d4..3dddecd2 100644 --- a/include/spdlog/details/spdlog_impl.h +++ b/include/spdlog/details/spdlog_impl.h @@ -132,9 +132,9 @@ inline void spdlog::set_level(level::level_enum log_level) } -inline void spdlog::set_async_mode(size_t queue_size, const std::function& worker_warmup_cb) +inline void spdlog::set_async_mode(size_t queue_size, const async_queue_overflow_policy overflow_policy, const std::function& worker_warmup_cb) { - details::registry::instance().set_async_mode(queue_size, worker_warmup_cb); + details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb); } inline void spdlog::set_sync_mode() diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 92894b85..b6df62a2 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -61,9 +61,14 @@ void set_level(level::level_enum log_level); // Async mode - off by default. // +enum class async_queue_overflow_policy { + block_retry, // Block / yield / sleep until message can be enqueued + discard_log_msg // Discard the message it enqueue fails +}; + // Turn on async mode and set the queue size for each async_logger -void set_async_mode(size_t queue_size, const std::function& worker_warmup_cb = nullptr); +void set_async_mode(size_t queue_size, const async_queue_overflow_policy overflow_policy = async_queue_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr); // Turn off async mode void set_sync_mode();