15 #include "../common.h" 16 #include "../details/log_msg.h" 17 #include "../details/mpmc_blocking_q.h" 18 #include "../details/os.h" 19 #include "../formatter.h" 20 #include "../sinks/sink.h" 23 #include <condition_variable> 39 enum class async_msg_type
48 level::level_enum level;
49 log_clock::time_point time;
52 async_msg_type msg_type;
55 async_msg() =
default;
56 ~async_msg() =
default;
58 explicit async_msg(async_msg_type m_type)
66 async_msg(async_msg &&other) =
default;
67 async_msg &operator=(async_msg &&other) =
default;
70 async_msg(
const async_msg &) =
delete;
71 async_msg &operator=(
const async_msg &other) =
delete;
77 , thread_id(m.thread_id)
79 , msg_type(async_msg_type::log)
85 void fill_log_msg(
log_msg &msg, std::string *logger_name)
87 msg.logger_name = logger_name;
90 msg.thread_id = thread_id;
98 using item_type = async_msg;
101 using clock = std::chrono::steady_clock;
104 const log_err_handler err_handler,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
105 std::function<
void()> worker_warmup_cb =
nullptr,
106 const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
107 std::function<
void()> worker_teardown_cb =
nullptr);
117 void set_formatter(formatter_ptr msg_formatter);
121 void set_error_handler(spdlog::log_err_handler err_handler);
124 std::string _logger_name;
125 formatter_ptr _formatter;
126 std::vector<std::shared_ptr<sinks::sink>> _sinks;
131 log_err_handler _err_handler;
133 std::chrono::time_point<log_clock> _last_flush;
136 const async_overflow_policy _overflow_policy;
139 const std::function<void()> _worker_warmup_cb;
142 const std::chrono::milliseconds _flush_interval_ms;
145 const std::function<void()> _worker_teardown_cb;
147 std::mutex null_mutex_;
149 std::condition_variable_any not_empty_cv_;
150 std::condition_variable_any not_full_cv_;
153 std::thread _worker_thread;
155 void enqueue_msg(async_msg &&new_msg, async_overflow_policy policy);
162 bool process_next_msg();
164 void handle_flush_interval();
174 inline spdlog::details::async_log_helper::async_log_helper(std::string logger_name, formatter_ptr
formatter, std::vector<sink_ptr> sinks,
175 size_t queue_size, log_err_handler err_handler,
const async_overflow_policy overflow_policy, std::function<
void()> worker_warmup_cb,
176 const std::chrono::milliseconds &flush_interval_ms, std::function<
void()> worker_teardown_cb)
177 : _logger_name(std::move(logger_name))
179 , _sinks(std::move(sinks))
181 , _err_handler(std::move(err_handler))
182 , _last_flush(os::now())
183 , _overflow_policy(overflow_policy)
184 , _worker_warmup_cb(std::move(worker_warmup_cb))
185 , _flush_interval_ms(flush_interval_ms)
186 , _worker_teardown_cb(std::move(worker_teardown_cb))
188 _worker_thread = std::thread(&async_log_helper::worker_loop,
this);
192 inline spdlog::details::async_log_helper::~async_log_helper()
196 enqueue_msg(async_msg(async_msg_type::terminate), async_overflow_policy::block_retry);
197 _worker_thread.join();
205 inline void spdlog::details::async_log_helper::log(
const details::log_msg &msg)
207 enqueue_msg(async_msg(msg), _overflow_policy);
210 inline void spdlog::details::async_log_helper::enqueue_msg(details::async_log_helper::async_msg &&new_msg, async_overflow_policy policy)
214 if (policy == async_overflow_policy::block_retry)
216 _q.enqueue(std::move(new_msg));
220 _q.enqueue_nowait(std::move(new_msg));
225 inline void spdlog::details::async_log_helper::flush()
227 enqueue_msg(async_msg(async_msg_type::flush), _overflow_policy);
230 inline void spdlog::details::async_log_helper::worker_loop()
232 if (_worker_warmup_cb)
241 active = process_next_msg();
243 SPDLOG_CATCH_AND_HANDLE
245 if (_worker_teardown_cb)
247 _worker_teardown_cb();
253 inline bool spdlog::details::async_log_helper::process_next_msg()
255 async_msg incoming_async_msg;
256 bool dequeued = _q.dequeue_for(incoming_async_msg, std::chrono::seconds(2));
259 handle_flush_interval();
263 switch (incoming_async_msg.msg_type)
265 case async_msg_type::flush:
269 case async_msg_type::terminate:
275 incoming_async_msg.fill_log_msg(incoming_log_msg, &_logger_name);
276 _formatter->format(incoming_log_msg);
277 for (
auto &s : _sinks)
279 if (s->should_log(incoming_log_msg.level))
283 s->log(incoming_log_msg);
285 SPDLOG_CATCH_AND_HANDLE
288 handle_flush_interval();
295 inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter)
297 _formatter = std::move(msg_formatter);
300 inline void spdlog::details::async_log_helper::set_error_handler(spdlog::log_err_handler err_handler)
302 _err_handler = std::move(err_handler);
306 inline void spdlog::details::async_log_helper::handle_flush_interval()
308 if (_flush_interval_ms == std::chrono::milliseconds::zero())
312 auto delta = details::os::now() - _last_flush;
314 if (delta >= _flush_interval_ms)
321 inline void spdlog::details::async_log_helper::flush_sinks()
324 for (
auto &s : _sinks)
330 SPDLOG_CATCH_AND_HANDLE
332 _last_flush = os::now();
const Char * data() const FMT_NOEXCEPT
Definition: format.h:3280
Definition: async_logger.h:26
std::size_t size() const
Definition: format.h:3271
Definition: async_log_helper.h:35