gabime / spdlog

Fast C++ logging library.
Other
24.34k stars 4.55k forks source link

async loggers output not in order #3190

Open rlabbe opened 1 month ago

rlabbe commented 1 month ago

I think this is probably a documentation/understanding issue.

I create an async log with

  auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
  auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename);
  std::vector<spdlog::sink_ptr> sinks{ console_sink, file_sink };
  log = std::make_shared<spdlog::async_logger>(name,
                                               sinks.begin(),
                                               sinks.end(),
                                               spdlog::thread_pool(),
                                               spdlog::async_overflow_policy::block);

and when I run my program the logs appear out of order.

For example,

log->info("1"); 
log->info("2");  

all in the same thread, no other threads accessing the logs or pool, it may output the 2 and then the 1.

I tracked it down to this call:

spdlog::init_thread_pool(8192, 2);

If I change the # of threads from 2 to 1 then I get the expected behavior - everything ordered as called.

There doesn't seem to be any info on how to choose # of threads in this call. There are 2 sinks, and so it seemed reasonable to create 2 threads here. But it seems like the 2 threads are just accessing a single queue, and so race conditions prevail? Dunno. It was unexpected. If this is by design, then some documentation on when/why you would want more than 1 thread would be useful.

tt4g commented 1 month ago

A similar question has been asked before (#1404) and a section has even been added to the Wiki.

https://github.com/gabime/spdlog/wiki/6.-Asynchronous-logging#spdlogs-thread-pool

spdlog's thread pool

By default, spdlog create a global thread pool with queue size of 8192 and 1 worker thread which to serve all async loggers.

This means that creating and destructing async loggers is cheap, since they do not own nor create any backing threads or queues- these are created and managed by the shared thread pool object.

https://github.com/gabime/spdlog/wiki/6.-Asynchronous-logging#message-ordering

Message ordering

By default, spdlog creates a single worker thread which preserves the order of the messages in the queue.

Please note that with thread pool with multiple workers threads, messages may be reordered after dequeuing.

If you want to keep the message order, create only one worker thread in the thread pool.