2018-05-23 02:59:27 +08:00
|
|
|
#include "includes.h"
|
|
|
|
#include "spdlog/async.h"
|
2018-07-07 17:12:45 +08:00
|
|
|
#include "spdlog/sinks/basic_file_sink.h"
|
2018-05-26 23:48:39 +08:00
|
|
|
#include "test_sink.h"
|
2018-05-23 02:59:27 +08:00
|
|
|
|
2021-01-07 07:55:57 +08:00
|
|
|
#define TEST_FILENAME "test_logs/async_test.log"
|
|
|
|
|
2018-05-23 02:59:27 +08:00
|
|
|
TEST_CASE("basic async test ", "[async]") {
|
2020-04-08 23:17:21 +08:00
|
|
|
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
2018-08-14 20:21:52 +08:00
|
|
|
size_t overrun_counter = 0;
|
2018-05-26 23:48:39 +08:00
|
|
|
size_t queue_size = 128;
|
|
|
|
size_t messages = 256;
|
|
|
|
{
|
2020-04-08 23:17:21 +08:00
|
|
|
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
|
|
|
|
auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp,
|
|
|
|
spdlog::async_overflow_policy::block);
|
2018-05-26 23:48:39 +08:00
|
|
|
for (size_t i = 0; i < messages; i++) {
|
|
|
|
logger->info("Hello message #{}", i);
|
|
|
|
}
|
|
|
|
logger->flush();
|
2018-08-14 19:51:20 +08:00
|
|
|
overrun_counter = tp->overrun_counter();
|
2018-05-26 23:48:39 +08:00
|
|
|
}
|
|
|
|
REQUIRE(test_sink->msg_counter() == messages);
|
2018-05-27 07:53:16 +08:00
|
|
|
REQUIRE(test_sink->flush_counter() == 1);
|
2018-08-14 19:51:20 +08:00
|
|
|
REQUIRE(overrun_counter == 0);
|
2018-05-23 02:59:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("discard policy ", "[async]") {
|
2020-04-08 23:17:21 +08:00
|
|
|
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
2018-08-14 05:58:50 +08:00
|
|
|
test_sink->set_delay(std::chrono::milliseconds(1));
|
|
|
|
size_t queue_size = 4;
|
|
|
|
size_t messages = 1024;
|
2018-07-22 04:30:26 +08:00
|
|
|
|
2020-04-08 23:17:21 +08:00
|
|
|
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
|
|
|
|
auto logger = std::make_shared<spdlog::async_logger>(
|
|
|
|
"as", test_sink, tp, spdlog::async_overflow_policy::overrun_oldest);
|
2018-07-22 04:30:26 +08:00
|
|
|
for (size_t i = 0; i < messages; i++) {
|
|
|
|
logger->info("Hello message");
|
2018-05-26 23:48:39 +08:00
|
|
|
}
|
2018-05-27 08:14:55 +08:00
|
|
|
REQUIRE(test_sink->msg_counter() < messages);
|
2018-08-14 19:51:20 +08:00
|
|
|
REQUIRE(tp->overrun_counter() > 0);
|
2018-05-23 02:59:27 +08:00
|
|
|
}
|
|
|
|
|
2023-09-10 04:05:08 +08:00
|
|
|
TEST_CASE("discard policy discard_new ", "[async]") {
|
|
|
|
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
|
|
|
test_sink->set_delay(std::chrono::milliseconds(1));
|
|
|
|
size_t queue_size = 4;
|
|
|
|
size_t messages = 1024;
|
|
|
|
|
|
|
|
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
|
|
|
|
auto logger = std::make_shared<spdlog::async_logger>(
|
|
|
|
"as", test_sink, tp, spdlog::async_overflow_policy::discard_new);
|
|
|
|
for (size_t i = 0; i < messages; i++) {
|
|
|
|
logger->info("Hello message");
|
|
|
|
}
|
|
|
|
REQUIRE(test_sink->msg_counter() < messages);
|
|
|
|
REQUIRE(tp->discard_counter() > 0);
|
|
|
|
}
|
|
|
|
|
2018-07-21 05:33:27 +08:00
|
|
|
TEST_CASE("discard policy using factory ", "[async]") {
|
2018-08-14 05:58:50 +08:00
|
|
|
size_t queue_size = 4;
|
|
|
|
size_t messages = 1024;
|
2018-07-22 04:30:26 +08:00
|
|
|
spdlog::init_thread_pool(queue_size, 1);
|
|
|
|
|
2020-04-08 23:17:21 +08:00
|
|
|
auto logger = spdlog::create_async_nb<spdlog::sinks::test_sink_mt>("as2");
|
|
|
|
auto test_sink = std::static_pointer_cast<spdlog::sinks::test_sink_mt>(logger->sinks()[0]);
|
2021-12-11 05:25:47 +08:00
|
|
|
test_sink->set_delay(std::chrono::milliseconds(3));
|
2018-08-14 05:58:50 +08:00
|
|
|
|
2018-07-22 04:30:26 +08:00
|
|
|
for (size_t i = 0; i < messages; i++) {
|
|
|
|
logger->info("Hello message");
|
|
|
|
}
|
2018-08-14 05:58:50 +08:00
|
|
|
|
|
|
|
REQUIRE(test_sink->msg_counter() < messages);
|
2018-07-22 04:30:26 +08:00
|
|
|
spdlog::drop_all();
|
2018-07-21 05:33:27 +08:00
|
|
|
}
|
|
|
|
|
2018-05-23 02:59:27 +08:00
|
|
|
TEST_CASE("flush", "[async]") {
|
2020-04-08 23:17:21 +08:00
|
|
|
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
2018-05-26 23:48:39 +08:00
|
|
|
size_t queue_size = 256;
|
|
|
|
size_t messages = 256;
|
|
|
|
{
|
2020-04-08 23:17:21 +08:00
|
|
|
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
|
|
|
|
auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp,
|
|
|
|
spdlog::async_overflow_policy::block);
|
2018-05-26 23:48:39 +08:00
|
|
|
for (size_t i = 0; i < messages; i++) {
|
|
|
|
logger->info("Hello message #{}", i);
|
|
|
|
}
|
|
|
|
|
|
|
|
logger->flush();
|
|
|
|
}
|
2018-07-22 04:48:07 +08:00
|
|
|
// std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
2018-05-26 23:48:39 +08:00
|
|
|
REQUIRE(test_sink->msg_counter() == messages);
|
2018-05-27 07:53:16 +08:00
|
|
|
REQUIRE(test_sink->flush_counter() == 1);
|
|
|
|
}
|
|
|
|
|
2024-03-23 21:52:32 +08:00
|
|
|
TEST_CASE("multithread flush", "[async]") {
|
|
|
|
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
|
|
|
size_t queue_size = 2;
|
|
|
|
size_t messages = 10;
|
|
|
|
size_t n_threads = 10;
|
2024-03-24 03:23:29 +08:00
|
|
|
size_t flush_count = 2048;
|
2024-03-23 21:52:32 +08:00
|
|
|
std::mutex mtx;
|
|
|
|
std::vector<std::string> errmsgs;
|
|
|
|
{
|
|
|
|
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
|
|
|
|
auto logger = std::make_shared<spdlog::async_logger>(
|
|
|
|
"as", test_sink, tp, spdlog::async_overflow_policy::discard_new);
|
|
|
|
|
|
|
|
logger->set_error_handler([&](const std::string &) {
|
|
|
|
std::unique_lock<std::mutex> lock(mtx);
|
|
|
|
errmsgs.push_back("Broken promise");
|
|
|
|
});
|
|
|
|
|
|
|
|
for (size_t i = 0; i < messages; i++) {
|
|
|
|
logger->info("Hello message #{}", i);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::thread> threads;
|
|
|
|
for (size_t i = 0; i < n_threads; i++) {
|
|
|
|
threads.emplace_back([logger, flush_count] {
|
|
|
|
for (size_t j = 0; j < flush_count; j++) {
|
|
|
|
// flush does not throw exception even if failed.
|
|
|
|
// Instead, the error handler is invoked.
|
|
|
|
logger->flush();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto &t : threads) {
|
|
|
|
t.join();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
REQUIRE(test_sink->flush_counter() >= 1);
|
|
|
|
REQUIRE(test_sink->flush_counter() + errmsgs.size() == n_threads * flush_count);
|
|
|
|
REQUIRE(errmsgs.size() >= 1);
|
|
|
|
REQUIRE(errmsgs[0] == "Broken promise");
|
|
|
|
}
|
|
|
|
|
2018-07-22 04:30:26 +08:00
|
|
|
TEST_CASE("async periodic flush", "[async]") {
|
2020-04-08 23:17:21 +08:00
|
|
|
auto logger = spdlog::create_async<spdlog::sinks::test_sink_mt>("as");
|
|
|
|
auto test_sink = std::static_pointer_cast<spdlog::sinks::test_sink_mt>(logger->sinks()[0]);
|
2018-07-22 04:30:26 +08:00
|
|
|
|
|
|
|
spdlog::flush_every(std::chrono::seconds(1));
|
2020-11-26 16:45:39 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1700));
|
2018-07-22 04:30:26 +08:00
|
|
|
REQUIRE(test_sink->flush_counter() == 1);
|
|
|
|
spdlog::flush_every(std::chrono::seconds(0));
|
|
|
|
spdlog::drop_all();
|
|
|
|
}
|
|
|
|
|
2018-05-27 07:53:16 +08:00
|
|
|
TEST_CASE("tp->wait_empty() ", "[async]") {
|
2020-04-08 23:17:21 +08:00
|
|
|
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
2018-05-27 07:53:16 +08:00
|
|
|
test_sink->set_delay(std::chrono::milliseconds(5));
|
2018-06-01 22:25:23 +08:00
|
|
|
size_t messages = 100;
|
2018-05-27 07:53:16 +08:00
|
|
|
|
2020-04-08 23:17:21 +08:00
|
|
|
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, 2);
|
|
|
|
auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp,
|
|
|
|
spdlog::async_overflow_policy::block);
|
2018-05-27 07:53:16 +08:00
|
|
|
for (size_t i = 0; i < messages; i++) {
|
|
|
|
logger->info("Hello message #{}", i);
|
|
|
|
}
|
|
|
|
logger->flush();
|
2018-06-01 22:25:23 +08:00
|
|
|
tp.reset();
|
|
|
|
|
2018-05-27 07:53:16 +08:00
|
|
|
REQUIRE(test_sink->msg_counter() == messages);
|
|
|
|
REQUIRE(test_sink->flush_counter() == 1);
|
2018-05-23 02:59:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("multi threads", "[async]") {
|
2020-04-08 23:17:21 +08:00
|
|
|
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
2018-05-26 23:48:39 +08:00
|
|
|
size_t queue_size = 128;
|
|
|
|
size_t messages = 256;
|
|
|
|
size_t n_threads = 10;
|
|
|
|
{
|
2020-04-08 23:17:21 +08:00
|
|
|
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
|
|
|
|
auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, tp,
|
|
|
|
spdlog::async_overflow_policy::block);
|
2018-05-26 23:48:39 +08:00
|
|
|
|
|
|
|
std::vector<std::thread> threads;
|
|
|
|
for (size_t i = 0; i < n_threads; i++) {
|
|
|
|
threads.emplace_back([logger, messages] {
|
|
|
|
for (size_t j = 0; j < messages; j++) {
|
|
|
|
logger->info("Hello message #{}", j);
|
|
|
|
}
|
|
|
|
});
|
2018-05-27 08:14:55 +08:00
|
|
|
logger->flush();
|
2018-05-26 23:48:39 +08:00
|
|
|
}
|
2018-05-23 02:59:27 +08:00
|
|
|
|
2018-05-26 23:48:39 +08:00
|
|
|
for (auto &t : threads) {
|
|
|
|
t.join();
|
|
|
|
}
|
|
|
|
}
|
2018-05-23 02:59:27 +08:00
|
|
|
|
2018-05-26 23:48:39 +08:00
|
|
|
REQUIRE(test_sink->msg_counter() == messages * n_threads);
|
2018-05-27 07:53:16 +08:00
|
|
|
REQUIRE(test_sink->flush_counter() == n_threads);
|
2018-05-23 02:59:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("to_file", "[async]") {
|
2018-05-27 07:21:49 +08:00
|
|
|
prepare_logdir();
|
|
|
|
size_t messages = 1024;
|
|
|
|
size_t tp_threads = 1;
|
2021-01-07 07:55:57 +08:00
|
|
|
spdlog::filename_t filename = SPDLOG_FILENAME_T(TEST_FILENAME);
|
2018-05-27 07:21:49 +08:00
|
|
|
{
|
2018-07-07 17:12:45 +08:00
|
|
|
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
|
2018-05-27 07:21:49 +08:00
|
|
|
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
|
|
|
|
auto logger =
|
|
|
|
std::make_shared<spdlog::async_logger>("as", std::move(file_sink), std::move(tp));
|
|
|
|
|
|
|
|
for (size_t j = 0; j < messages; j++) {
|
|
|
|
logger->info("Hello message #{}", j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-07 07:55:57 +08:00
|
|
|
require_message_count(TEST_FILENAME, messages);
|
|
|
|
auto contents = file_contents(TEST_FILENAME);
|
2020-02-05 05:23:36 +08:00
|
|
|
using spdlog::details::os::default_eol;
|
2021-11-14 00:29:05 +08:00
|
|
|
REQUIRE(ends_with(contents, spdlog::fmt_lib::format("Hello message #1023{}", default_eol)));
|
2018-05-27 07:21:31 +08:00
|
|
|
}
|
2018-05-23 02:59:27 +08:00
|
|
|
|
2018-05-27 07:21:31 +08:00
|
|
|
TEST_CASE("to_file multi-workers", "[async]") {
|
2018-05-27 07:21:49 +08:00
|
|
|
prepare_logdir();
|
|
|
|
size_t messages = 1024 * 10;
|
|
|
|
size_t tp_threads = 10;
|
2021-01-07 07:55:57 +08:00
|
|
|
spdlog::filename_t filename = SPDLOG_FILENAME_T(TEST_FILENAME);
|
2018-05-27 07:21:49 +08:00
|
|
|
{
|
2018-07-07 17:12:45 +08:00
|
|
|
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
|
2018-05-27 07:21:49 +08:00
|
|
|
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
|
|
|
|
auto logger =
|
|
|
|
std::make_shared<spdlog::async_logger>("as", std::move(file_sink), std::move(tp));
|
|
|
|
|
|
|
|
for (size_t j = 0; j < messages; j++) {
|
|
|
|
logger->info("Hello message #{}", j);
|
|
|
|
}
|
|
|
|
}
|
2021-01-07 07:55:57 +08:00
|
|
|
require_message_count(TEST_FILENAME, messages);
|
2018-05-23 02:59:27 +08:00
|
|
|
}
|
2023-05-27 20:33:02 +08:00
|
|
|
|
|
|
|
TEST_CASE("bad_tp", "[async]") {
|
|
|
|
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
|
|
|
std::shared_ptr<spdlog::details::thread_pool> const empty_tp;
|
|
|
|
auto logger = std::make_shared<spdlog::async_logger>("as", test_sink, empty_tp);
|
|
|
|
logger->info("Please throw an exception");
|
|
|
|
REQUIRE(test_sink->msg_counter() == 0);
|
|
|
|
}
|