-
Notifications
You must be signed in to change notification settings - Fork 4.6k
6. Asynchronous logging
To create async logger include spdlog/async.h and use the spdlog::async_logger template argument:
#include "spdlog/async.h"
void async_example()
{
// default thread pool settings can be modified *before* creating the async logger:
// spdlog::init_thread_pool(8192, 1); // queue with 8k items and 1 backing thread.
auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
// alternatively:
// auto async_file = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("async_file_logger", "logs/async_log.txt");
}
This will make spdlog to create and use async_logger objects
When the user logs a message to an async logger the following happen:
-
If the queue is not full, the log message is pushed into it. Otherwise, if the queue is full (the number of messages in it reached
max_size
), the call blocks until there is room again (or optionally, if the queue is full, it overrides oldest message and never blocks - see below) -
The worker thread(s) pops the message from the queue and logs the message using the logger's sinks.
by default, spdlog create a global thread pool with queue size of 8192 and 1 worker thread which to serve all async loggers.
The thread pool size and threads can be reset by
spdlog::init_thread_pool(queue_size, n_threads);
Note that this will drop the old global tp create a new thread pool - which means that any loggers that use the old tp will stop working, so it is advised calling it before any async loggers created.
If different loggers must have separate queues, you create different instances of pools, passing them to different loggers:
auto tp = std::make_shared<details::thread_pool>(128, 1);
auto logger = std::make_shared<async_logger>("as", some_sink, tp, async_overflow_policy::overrun_oldest);
auto tp2 = std::make_shared<details::thread_pool>(1024, 4); // create pool with queue of 1024 slots and 4 backing threads
auto logger2 = std::make_shared<async_logger>("as2", some_sink, tp2, async_overflow_policy::block);
User can decide what to do when the queue is full:
- Block the call until there is more room (default behaviour)
- Ovewrride oldset message the message and never block - by setting the
spdlog::async_overflow_policy
in the logger's contructor:
auto logger = std::make_shared<async_logger>("as", test_sink, spdlog::thread_pool(), spdlog::async_overflow_policy::overrun_oldest);
Another way to achieve this is to use the create_async_nb
factory method which will create a logger with the overrun_oldest
policy:
auto async_file = spdlog::create_async_nb<spdlog::sinks::basic_file_sink_mt>("async_file_logger", "logs/async_log.txt");
There is a bug in VS runtime that cause the application dead lock when it exits. If you use async logging, please make sure to call spdlog::drop_all() before main() exit. If some loggers are not in the registry, those should be released manually as well. stackoverflow: std::thread join hangs if called after main exits when using vs2012 rc