diff --git a/CMakeLists.txt b/CMakeLists.txt index f09474459..64c81f70f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ endif() option(SPDLOG_PREVENT_CHILD_FD "Prevent from child processes to inherit log file descriptors" OFF) option(SPDLOG_NO_THREAD_ID "prevent spdlog from querying the thread id on each log call if thread id is not needed" OFF) -option(SPDLOG_DISABLE_DEFAULT_LOGGER "Disable default logger creation" OFF) +option(SPDLOG_DISABLE_GLOBAL_LOGGER "Disable global logger creation" OFF) option(SPDLOG_NO_TLS "Disable thread local storage" OFF) # clang-tidy @@ -150,9 +150,6 @@ set(SPDLOG_HEADERS "include/spdlog/spdlog.h" "include/spdlog/stopwatch.h" "include/spdlog/version.h" - "include/spdlog/cfg/argv.h" - "include/spdlog/cfg/env.h" - "include/spdlog/cfg/helpers.h" "include/spdlog/details/circular_q.h" "include/spdlog/details/file_helper.h" "include/spdlog/details/fmt_helper.h" @@ -162,7 +159,7 @@ set(SPDLOG_HEADERS "include/spdlog/details/null_mutex.h" "include/spdlog/details/os.h" "include/spdlog/details/periodic_worker.h" - "include/spdlog/details/registry.h" + "include/spdlog/details/context.h" "include/spdlog/details/synchronous_factory.h" "include/spdlog/details/thread_pool.h" "include/spdlog/fmt/bin_to_hex.h" @@ -197,13 +194,11 @@ set(SPDLOG_SRCS "src/logger.cpp" "src/pattern_formatter.cpp" "src/spdlog.cpp" - "src/cfg/helpers.cpp" "src/details/file_helper.cpp" "src/details/os_filesystem.cpp" "src/details/log_msg.cpp" "src/details/log_msg_buffer.cpp" - "src/details/periodic_worker.cpp" - "src/details/registry.cpp" + "src/details/context.cpp" "src/details/thread_pool.cpp" "src/sinks/base_sink.cpp" "src/sinks/basic_file_sink.cpp" @@ -309,11 +304,11 @@ endif() # --------------------------------------------------------------------------------------- # spdlog private defines according to the options # --------------------------------------------------------------------------------------- -foreach(SPDLOG_OPTION +foreach(SPDLOG_OPTION SPDLOG_CLOCK_COARSE SPDLOG_PREVENT_CHILD_FD SPDLOG_NO_THREAD_ID - SPDLOG_DISABLE_DEFAULT_LOGGER + SPDLOG_DISABLE_GLOBAL_LOGGER SPDLOG_NO_TLS SPDLOG_FWRITE_UNLOCKED) if(${SPDLOG_OPTION}) diff --git a/README.md b/README.md index 257908ca2..31c845bb3 100644 --- a/README.md +++ b/README.md @@ -195,18 +195,6 @@ void binary_example() ``` ---- -#### Mapped diagnostic context (MDC) -MDC is a map of contextual information that can be used to enrich log messages. -It is a map of key-value pairs that can be set on a per-thread basis since it is stored in thread-local storage. -```c++ -#include "spdlog/spdlog.h" -#include "spdlog/mdc" -... -spdlog::mdc::put("key1", "value1"); -spdlog::mdc::put("key2", "value2"); -``` - --- #### Logger with multi sinks - each with a different format and log level ```c++ @@ -410,10 +398,10 @@ void file_events_example() --- #### Replace the Default Logger ```c++ -void replace_default_logger_example() +void replace_global_logger_example() { - auto new_logger = spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true); - spdlog::set_default_logger(new_logger); + auto new_logger = spdlog::basic_logger_mt("new_global_logger", "logs/new-default-log.txt", true); + spdlog::set_global_logger(new_logger); spdlog::info("new logger log message"); } ``` diff --git a/bench/async_bench.cpp b/bench/async_bench.cpp index 60de0386c..4eb6ce4a7 100644 --- a/bench/async_bench.cpp +++ b/bench/async_bench.cpp @@ -150,5 +150,5 @@ void bench_mt(int howmany, std::shared_ptr logger, int thread_co auto delta = high_resolution_clock::now() - start; auto delta_d = duration_cast>(delta).count(); - spdlog::info("Elapsed: {} secs\t {:L}/sec", delta_d, int(howmany / delta_d)); + spdlog::info("Elapsed: {} secs\t {:L}/sec", delta_d, static_cast(howmany / delta_d)); } diff --git a/bench/bench.cpp b/bench/bench.cpp index 66d1621d9..2885f4f97 100644 --- a/bench/bench.cpp +++ b/bench/bench.cpp @@ -77,8 +77,7 @@ void bench_single_threaded(int iters) { } int main(int argc, char *argv[]) { - spdlog::set_automatic_registration(false); - spdlog::default_logger()->set_pattern("[%^%l%$] %v"); + spdlog::global_logger()->set_pattern("[%^%l%$] %v"); int iters = 250000; size_t threads = 4; try { @@ -117,8 +116,7 @@ void bench(int howmany, std::shared_ptr log) { auto delta_d = duration_cast>(delta).count(); spdlog::info(spdlog::fmt_lib::format(std::locale("en_US.UTF-8"), "{:<30} Elapsed: {:0.2f} secs {:>16L}/sec", log->name(), - delta_d, size_t(howmany / delta_d))); - spdlog::drop(log->name()); + delta_d, static_cast(howmany / delta_d))); } void bench_mt(int howmany, std::shared_ptr log, size_t thread_count) { @@ -144,8 +142,7 @@ void bench_mt(int howmany, std::shared_ptr log, size_t thread_co auto delta = high_resolution_clock::now() - start; auto delta_d = duration_cast>(delta).count(); spdlog::info(spdlog::fmt_lib::format(std::locale("en_US.UTF-8"), "{:<30} Elapsed: {:0.2f} secs {:>16L}/sec", log->name(), - delta_d, size_t(howmany / delta_d))); - spdlog::drop(log->name()); + delta_d, static_cast(howmany / delta_d))); } /* @@ -155,8 +152,8 @@ void bench_default_api(int howmany, std::shared_ptr log) using std::chrono::duration; using std::chrono::duration_cast; - auto orig_default = spdlog::default_logger(); - spdlog::set_default_logger(log); + auto orig_default = spdlog::global_logger(); + spdlog::set_global_logger(log); auto start = high_resolution_clock::now(); for (auto i = 0; i < howmany; ++i) { @@ -166,7 +163,7 @@ void bench_default_api(int howmany, std::shared_ptr log) auto delta = high_resolution_clock::now() - start; auto delta_d = duration_cast>(delta).count(); spdlog::drop(log->name()); - spdlog::set_default_logger(std::move(orig_default)); + spdlog::set_global_logger(std::move(orig_default)); spdlog::info("{:<30} Elapsed: {:0.2f} secs {:>16}/sec", log->name(), delta_d, int(howmany / delta_d)); } @@ -184,8 +181,8 @@ non dapibus eros. Donec fringilla dui sed " "augue pretium, nec scelerisque est convallis, sem nec blandit maximus, nisi turpis ornare " "nisl, sit amet volutpat neque massa eu odio. Maecenas malesuada quam ex, posuere congue nibh turpis duis."; - auto orig_default = spdlog::default_logger(); - spdlog::set_default_logger(log); + auto orig_default = spdlog::global_logger(); + spdlog::set_global_logger(log); auto start = high_resolution_clock::now(); for (auto i = 0; i < howmany; ++i) { @@ -195,7 +192,7 @@ odio. Maecenas malesuada quam ex, posuere congue nibh turpis duis."; auto delta = high_resolution_clock::now() - start; auto delta_d = duration_cast>(delta).count(); spdlog::drop(log->name()); - spdlog::set_default_logger(std::move(orig_default)); + spdlog::set_global_logger(std::move(orig_default)); spdlog::info("{:<30} Elapsed: {:0.2f} secs {:>16}/sec", log->name(), delta_d, int(howmany / delta_d)); } diff --git a/bench/latency.cpp b/bench/latency.cpp index c859e9e20..ea746d3a8 100644 --- a/bench/latency.cpp +++ b/bench/latency.cpp @@ -40,7 +40,7 @@ void bench_logger(benchmark::State &state, std::shared_ptr logge } void bench_global_logger(benchmark::State &state, std::shared_ptr logger) { - spdlog::set_default_logger(std::move(logger)); + spdlog::set_global_logger(std::move(logger)); int i = 0; for (auto _ : state) { spdlog::info("Hello logger: msg number {}...............", ++i); @@ -57,7 +57,7 @@ void bench_disabled_macro(benchmark::State &state, std::shared_ptr logger) { - spdlog::set_default_logger(std::move(logger)); + spdlog::set_global_logger(std::move(logger)); int i = 0; benchmark::DoNotOptimize(i); // prevent unused warnings benchmark::DoNotOptimize(logger); // prevent unused warnings @@ -71,11 +71,9 @@ void bench_disabled_macro_global_logger(benchmark::State &state, std::shared_ptr void bench_dev_null() { auto dev_null_st = spdlog::basic_logger_st("/dev/null_st", "/dev/null"); benchmark::RegisterBenchmark("/dev/null_st", bench_logger, std::move(dev_null_st))->UseRealTime(); - spdlog::drop("/dev/null_st"); auto dev_null_mt = spdlog::basic_logger_mt("/dev/null_mt", "/dev/null"); benchmark::RegisterBenchmark("/dev/null_mt", bench_logger, std::move(dev_null_mt))->UseRealTime(); - spdlog::drop("/dev/null_mt"); } #endif // __linux__ @@ -84,7 +82,6 @@ void bench_dev_null() { // for this test we create multiple null loggers and then call spdlog::get() on one of them multiple times // create multiple null loggers and return name of the one to test static std::string prepare_null_loggers() { - spdlog::drop_all(); const std::string some_logger_name = "Some logger name"; const int null_logger_count = 9; for (int i = 0; i < null_logger_count; i++) { @@ -93,41 +90,6 @@ static std::string prepare_null_loggers() { return some_logger_name + std::to_string(null_logger_count / 2); } -// benchmark spdlog::get() with const char* -void bench_get_logger_const_char(benchmark::State &state) { - std::string str_name = prepare_null_loggers(); - const char *name = str_name.c_str(); - for (auto _ : state) { - auto rv = spdlog::get(name); - if (rv == nullptr) { - state.SkipWithError("get() returned nullptr"); - } - } -} - -// benchmark spdlog::get() with std::string_view -void bench_get_logger_sv(benchmark::State &state) { - auto str_name = prepare_null_loggers(); - auto sv_name = std::string_view{str_name}; - for (auto _ : state) { - auto rv = spdlog::get(sv_name); - if (rv == nullptr) { - state.SkipWithError("get() returned nullptr"); - } - } -} - -// benchmark spdlog::get() with std::string -void bench_get_logger_string(benchmark::State &state) { - auto str_name = prepare_null_loggers(); - for (auto _ : state) { - auto rv = spdlog::get(str_name); - if (rv == nullptr) { - state.SkipWithError("get() returned nullptr"); - } - } -} - int main(int argc, char *argv[]) { using spdlog::sinks::null_sink_mt; using spdlog::sinks::null_sink_st; @@ -159,17 +121,14 @@ int main(int argc, char *argv[]) { // basic_st auto basic_st = spdlog::basic_logger_st("basic_st", "latency_logs/basic_st.log", true); benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st))->UseRealTime(); - spdlog::drop("basic_st"); // rotating st auto rotating_st = spdlog::rotating_logger_st("rotating_st", "latency_logs/rotating_st.log", file_size, rotating_files); benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st))->UseRealTime(); - spdlog::drop("rotating_st"); // daily st auto daily_st = spdlog::daily_logger_mt("daily_st", "latency_logs/daily_st.log"); benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st))->UseRealTime(); - spdlog::drop("daily_st"); // // Multi threaded bench, 10 loggers using same logger concurrently @@ -180,17 +139,14 @@ int main(int argc, char *argv[]) { // basic_mt auto basic_mt = spdlog::basic_logger_mt("basic_mt", "latency_logs/basic_mt.log", true); benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt))->Threads(n_threads)->UseRealTime(); - spdlog::drop("basic_mt"); // rotating mt auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "latency_logs/rotating_mt.log", file_size, rotating_files); benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt))->Threads(n_threads)->UseRealTime(); - spdlog::drop("rotating_mt"); // daily mt auto daily_mt = spdlog::daily_logger_mt("daily_mt", "latency_logs/daily_mt.log"); benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt))->Threads(n_threads)->UseRealTime(); - spdlog::drop("daily_mt"); } // async @@ -200,10 +156,6 @@ int main(int argc, char *argv[]) { spdlog::async_overflow_policy::overrun_oldest); benchmark::RegisterBenchmark("async_logger", bench_logger, async_logger)->Threads(n_threads)->UseRealTime(); - benchmark::RegisterBenchmark("spdlog::get(const char* name)", bench_get_logger_const_char); - benchmark::RegisterBenchmark("spdlog::get(std::string_view name)", bench_get_logger_sv); - benchmark::RegisterBenchmark("spdlog::get(const std::string &name)", bench_get_logger_string); - benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); } diff --git a/example/example.cpp b/example/example.cpp index 1de2b0636..032e62c53 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -1,4 +1,4 @@ -// +// // Copyright(c) 2015 Gabi Melman. // Distributed under the MIT License (http://opensource.org/licenses/MIT) @@ -7,7 +7,6 @@ #include #include -void load_levels_example(); void stdout_logger_example(); void basic_example(); void rotating_example(); @@ -25,16 +24,12 @@ void syslog_example(); void udp_example(); void custom_flags_example(); void file_events_example(); -void replace_default_logger_example(); +void replace_global_logger_example(); -#include "spdlog/cfg/env.h" // support for loading levels from the environment variable #include "spdlog/spdlog.h" #include "spdlog/version.h" int main(int, char *[]) { - // Log levels can be loaded from argv/env using "SPDLOG_LEVEL" - load_levels_example(); - SPDLOG_INFO("This message should be displayed.."); spdlog::info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH); spdlog::warn("Easy padding in numbers like {:08d}", 12); spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); @@ -71,16 +66,9 @@ int main(int, char *[]) { udp_example(); custom_flags_example(); file_events_example(); - replace_default_logger_example(); + replace_global_logger_example(); - // Flush all *registered* loggers using a worker thread every 3 seconds. - // note: registered loggers *must* be thread safe for this to work correctly! - spdlog::flush_every(std::chrono::seconds(3)); - - // Apply some function on all registered loggers - spdlog::apply_all([&](std::shared_ptr l) { l->info("End of example."); }); - - // Release all spdlog resources, and drop all loggers in the registry. + // Release all spdlog resources // This is optional (only mandatory if using windows + async log). spdlog::shutdown(); } @@ -127,17 +115,6 @@ void callback_example() { }); } -void load_levels_example() { - // Set the log level to "info" and mylogger to "trace": - // SPDLOG_LEVEL=info,mylogger=trace && ./example - // must #include "spdlog/cfg/env.h" - spdlog::cfg::load_env_levels(); - // or from command line: - // ./example SPDLOG_LEVEL=info,mylogger=trace - // #include "spdlog/cfg/argv.h" // for loading levels from argv - // spdlog::cfg::load_argv_levels(args, argv); -} - #include "spdlog/async.h" void async_example() { // Default thread pool settings can be modified *before* creating the async logger: @@ -188,14 +165,10 @@ void vector_example() { // Compile time log levels. // define SPDLOG_ACTIVE_LEVEL to required level (e.g. SPDLOG_LEVEL_TRACE) void trace_example() { - // trace from default logger + // trace from global logger SPDLOG_TRACE("Some trace message.. {} ,{}", 1, 3.23); - // debug from default logger + // debug from global logger SPDLOG_DEBUG("Some debug message.. {} ,{}", 1, 3.23); - - // trace from logger object - auto logger = spdlog::get("file_logger"); - SPDLOG_LOGGER_TRACE(logger, "another trace message"); } // stopwatch example @@ -299,30 +272,30 @@ void custom_flags_example() { void file_events_example() { // pass the spdlog::file_event_handlers to file sinks for open/close log file notifications spdlog::file_event_handlers handlers; - handlers.before_open = [](spdlog::filename_t) { spdlog::info("Before opening logfile"); }; + handlers.before_open = [](spdlog::filename_t) { spdlog::trace("Before opening logfile"); }; handlers.after_open = [](spdlog::filename_t, std::FILE *fstream) { - spdlog::info("After opening logfile"); + spdlog::trace("After opening logfile"); fputs("After opening\n", fstream); }; handlers.before_close = [](spdlog::filename_t, std::FILE *fstream) { - spdlog::info("Before closing logfile"); + spdlog::trace("Before closing logfile"); fputs("Before closing\n", fstream); }; - handlers.after_close = [](spdlog::filename_t) { spdlog::info("After closing logfile"); }; + handlers.after_close = [](spdlog::filename_t) { spdlog::trace("After closing logfile"); }; auto file_sink = std::make_shared("logs/events-sample.txt", true, handlers); spdlog::logger my_logger("some_logger", file_sink); - my_logger.info("Some log line"); + my_logger.trace("Some log line"); } -void replace_default_logger_example() { +void replace_global_logger_example() { // store the old logger so we don't break other examples. - auto old_logger = spdlog::default_logger(); + auto old_logger = spdlog::global_logger(); - auto new_logger = spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true); - spdlog::set_default_logger(new_logger); + auto new_logger = spdlog::basic_logger_mt("new_global_logger", "logs/new-default-log.txt", true); + spdlog::set_global_logger(new_logger); spdlog::set_level(spdlog::level::info); spdlog::debug("This message should not be displayed!"); spdlog::set_level(spdlog::level::trace); spdlog::debug("This message should be displayed.."); - spdlog::set_default_logger(old_logger); + spdlog::set_global_logger(old_logger); } diff --git a/include/spdlog/async.h b/include/spdlog/async.h index fbecff47d..8dcb54622 100644 --- a/include/spdlog/async.h +++ b/include/spdlog/async.h @@ -19,13 +19,13 @@ #include #include "./async_logger.h" -#include "./details/registry.h" +#include "./details/context.h" #include "./details/thread_pool.h" +#include "spdlog.h" namespace spdlog { - namespace details { -static const size_t default_async_q_size = 8192; +static constexpr size_t default_async_q_size = 8192; } // async logger factory - creates async loggers backed with thread pool. @@ -35,20 +35,17 @@ template struct async_factory_impl { template static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) { - auto ®istry_inst = details::registry::instance(); - + auto context = spdlog::context(); // create global thread pool if not already exists - auto &mutex = registry_inst.tp_mutex(); + auto &mutex = context->tp_mutex(); std::lock_guard tp_lock(mutex); - auto tp = registry_inst.get_tp(); + auto tp = context->get_tp(); if (tp == nullptr) { tp = std::make_shared(details::default_async_q_size, 1U); - registry_inst.set_tp(tp); + context->set_tp(tp); } - auto sink = std::make_shared(std::forward(args)...); auto new_logger = std::make_shared(std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy); - registry_inst.initialize_logger(new_logger); return new_logger; } }; @@ -72,7 +69,7 @@ inline void init_thread_pool(size_t q_size, std::function on_thread_start, std::function on_thread_stop) { auto tp = std::make_shared(q_size, thread_count, on_thread_start, on_thread_stop); - details::registry::instance().set_tp(std::move(tp)); + spdlog::context()->set_tp(std::move(tp)); } inline void init_thread_pool(size_t q_size, size_t thread_count, std::function on_thread_start) { @@ -84,5 +81,5 @@ inline void init_thread_pool(size_t q_size, size_t thread_count) { } // get the global thread pool. -inline std::shared_ptr thread_pool() { return details::registry::instance().get_tp(); } +inline std::shared_ptr thread_pool() { return spdlog::context()->get_tp(); } } // namespace spdlog diff --git a/include/spdlog/cfg/argv.h b/include/spdlog/cfg/argv.h deleted file mode 100644 index 556ab7360..000000000 --- a/include/spdlog/cfg/argv.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once -#include "./helpers.h" - -// -// Init log levels using each argv entry that starts with "SPDLOG_LEVEL=" -// -// set all loggers to debug level: -// example.exe "SPDLOG_LEVEL=debug" - -// set logger1 to trace level -// example.exe "SPDLOG_LEVEL=logger1=trace" - -// turn off all logging except for logger1 and logger2: -// example.exe "SPDLOG_LEVEL=off,logger1=debug,logger2=info" - -namespace spdlog { -namespace cfg { - -// search for SPDLOG_LEVEL= in the args and use it to init the levels -inline void load_argv_levels(int argc, const char **argv) { - const std::string spdlog_level_prefix = "SPDLOG_LEVEL="; - for (int i = 1; i < argc; i++) { - std::string arg = argv[i]; - if (arg.find(spdlog_level_prefix) == 0) { - auto levels_string = arg.substr(spdlog_level_prefix.size()); - helpers::load_levels(levels_string); - } - } -} - -inline void load_argv_levels(int argc, char **argv) { load_argv_levels(argc, const_cast(argv)); } - -} // namespace cfg -} // namespace spdlog diff --git a/include/spdlog/cfg/env.h b/include/spdlog/cfg/env.h deleted file mode 100644 index 918ce662e..000000000 --- a/include/spdlog/cfg/env.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once -#include "../details/os.h" -#include "../details/registry.h" -#include "./helpers.h" - -// -// Init levels and patterns from env variables SPDLOG_LEVEL -// Inspired from Rust's "env_logger" crate (https://crates.io/crates/env_logger). -// Note - fallback to "info" level on unrecognized levels -// -// Examples: -// -// set global level to debug: -// export SPDLOG_LEVEL=debug -// -// turn off all logging except for logger1: -// export SPDLOG_LEVEL="*=off,logger1=debug" -// - -// turn off all logging except for logger1 and logger2: -// export SPDLOG_LEVEL="off,logger1=debug,logger2=info" - -namespace spdlog { -namespace cfg { -inline void load_env_levels() { - auto env_val = details::os::getenv("SPDLOG_LEVEL"); - if (!env_val.empty()) { - helpers::load_levels(env_val); - } -} - -} // namespace cfg -} // namespace spdlog diff --git a/include/spdlog/cfg/helpers.h b/include/spdlog/cfg/helpers.h deleted file mode 100644 index c9acf7dd4..000000000 --- a/include/spdlog/cfg/helpers.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -#include - -#include "../common.h" - -namespace spdlog { -namespace cfg { -namespace helpers { -// -// Init levels from given string -// -// Examples: -// -// set global level to debug: "debug" -// turn off all logging except for logger1: "off,logger1=debug" -// turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info" -// -SPDLOG_API void load_levels(const std::string &input); -} // namespace helpers -} // namespace cfg -} // namespace spdlog diff --git a/include/spdlog/common.h b/include/spdlog/common.h index 36c58c4ad..8b70901f4 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -5,13 +5,12 @@ #include #include -#include +#include #include #include #include #include #include -#include #include #include "./source_loc.h" diff --git a/include/spdlog/details/context.h b/include/spdlog/details/context.h new file mode 100644 index 000000000..6059c7b5b --- /dev/null +++ b/include/spdlog/details/context.h @@ -0,0 +1,59 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Loggers registry of unique name->logger pointer +// An attempt to create a logger with an already existing name will result with spdlog_ex exception. +// If user requests a non-existing logger, nullptr will be returned +// This class is thread safe + +#include +#include +#include + +#include "../common.h" +#include "./periodic_worker.h" + +namespace spdlog { +class logger; + +namespace details { +class thread_pool; + +class SPDLOG_API context { +public: + context() = default; + explicit context(std::unique_ptr global_logger); + ~context() = default; + context(const context &) = delete; + context &operator=(const context &) = delete; + + [[nodiscard]] std::shared_ptr global_logger(); + + // Return raw ptr to the global logger. + // To be used directly by the spdlog global api (e.g. spdlog::info) + // This make the global API faster, but cannot be used concurrently with set_global_logger(). + // e.g do not call set_global_logger() from one thread while calling spdlog::info() from + // another. + [[nodiscard]] logger *global_logger_raw() const noexcept; + + // set logger instance. + void set_logger(std::shared_ptr new_logger); + + void set_tp(std::shared_ptr tp); + + [[nodiscard]] std::shared_ptr get_tp(); + + // clean all resources + void shutdown(); + [[nodiscard]] std::recursive_mutex &tp_mutex(); + +private: + std::recursive_mutex tp_mutex_; + std::shared_ptr tp_; + std::shared_ptr global_logger_; +}; + +} // namespace details +} // namespace spdlog diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h index f6c6d4454..346e442d6 100644 --- a/include/spdlog/details/os.h +++ b/include/spdlog/details/os.h @@ -5,6 +5,7 @@ #include // std::time_t #include + #include "../common.h" #include "../filename_t.h" @@ -66,7 +67,6 @@ SPDLOG_API void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); SPDLOG_API void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target); #endif - // non thread safe, cross platform getenv/getenv_s // return empty string if field not found SPDLOG_API std::string getenv(const char *field); @@ -106,7 +106,6 @@ SPDLOG_API bool rename(const filename_t &filename1, const filename_t &filename2) // Return if file exists. SPDLOG_API bool path_exists(const filename_t &filename) noexcept; - // Return file path and its extension: // // "mylog.txt" => ("mylog", ".txt") @@ -124,7 +123,6 @@ SPDLOG_API std::tuple split_by_extension(const filename_ // Try tp convert filename to string. Return "??" if failed SPDLOG_API std::string filename_to_str(const filename_t &filename); - } // namespace os } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h deleted file mode 100644 index 30ff88ea6..000000000 --- a/include/spdlog/details/registry.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -// Loggers registry of unique name->logger pointer -// An attempt to create a logger with an already existing name will result with spdlog_ex exception. -// If user requests a non-existing logger, nullptr will be returned -// This class is thread safe - -#include -#include -#include -#include -#include -#include -#include - -#include "../common.h" -#include "./periodic_worker.h" - -namespace spdlog { -class logger; - -namespace details { -class thread_pool; - -class SPDLOG_API registry { -public: - using log_levels = std::unordered_map; - - static registry &instance(); - registry(const registry &) = delete; - registry &operator=(const registry &) = delete; - - void register_logger(std::shared_ptr new_logger); - void initialize_logger(std::shared_ptr new_logger); - std::shared_ptr get(const std::string &logger_name); - std::shared_ptr get(std::string_view logger_name); - std::shared_ptr get(const char *logger_name); - std::shared_ptr default_logger(); - - // Return raw ptr to the default logger. - // To be used directly by the spdlog default api (e.g. spdlog::info) - // This make the default API faster, but cannot be used concurrently with set_default_logger(). - // e.g do not call set_default_logger() from one thread while calling spdlog::info() from - // another. - logger *get_default_raw() const; - - // set default logger. - // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. - void set_default_logger(std::shared_ptr new_default_logger); - - void set_tp(std::shared_ptr tp); - - std::shared_ptr get_tp(); - - // Set global formatter. Each sink in each logger will get a clone of this object - void set_formatter(std::unique_ptr formatter); - - void set_level(level level); - - void flush_on(level level); - - template - void flush_every(std::chrono::duration interval) { - std::lock_guard lock(flusher_mutex_); - auto clbk = [this]() { this->flush_all(); }; - periodic_flusher_ = std::make_unique(clbk, interval); - } - - std::unique_ptr &get_flusher() { - std::lock_guard lock(flusher_mutex_); - return periodic_flusher_; - } - - void set_error_handler(err_handler handler); - - void apply_all(const std::function)> &fun); - - void flush_all(); - - void drop(const std::string &logger_name); - - void drop_all(); - - // clean all resources and threads started by the registry - void shutdown(); - - std::recursive_mutex &tp_mutex(); - - void set_automatic_registration(bool automatic_registration); - - // set levels for all existing/future loggers. global_level can be null if should not set. - void set_levels(log_levels levels, level *global_level); - - void apply_logger_env_levels(std::shared_ptr new_logger); - -private: - registry(); - ~registry(); - - void throw_if_exists_(const std::string &logger_name); - void register_logger_(std::shared_ptr new_logger); - std::mutex logger_map_mutex_, flusher_mutex_; - std::recursive_mutex tp_mutex_; - std::unordered_map> loggers_; - log_levels log_levels_; - std::unique_ptr formatter_; - spdlog::level global_log_level_ = level::info; - level flush_level_ = level::off; - err_handler err_handler_; - std::shared_ptr tp_; - std::unique_ptr periodic_flusher_; - std::shared_ptr default_logger_; - bool automatic_registration_ = true; -}; - -} // namespace details -} // namespace spdlog diff --git a/include/spdlog/details/synchronous_factory.h b/include/spdlog/details/synchronous_factory.h index 6baff7d12..3aee14c6e 100644 --- a/include/spdlog/details/synchronous_factory.h +++ b/include/spdlog/details/synchronous_factory.h @@ -3,7 +3,7 @@ #pragma once -#include "./registry.h" +#include "./context.h" namespace spdlog { @@ -15,7 +15,6 @@ struct synchronous_factory { static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) { auto sink = std::make_shared(std::forward(args)...); auto new_logger = std::make_shared(std::move(logger_name), std::move(sink)); - details::registry::instance().initialize_logger(new_logger); return new_logger; } }; diff --git a/include/spdlog/file_event_handlers.h b/include/spdlog/file_event_handlers.h index 4a53df7f2..f244f6d78 100644 --- a/include/spdlog/file_event_handlers.h +++ b/include/spdlog/file_event_handlers.h @@ -1,6 +1,7 @@ #pragma once #include + #include "./filename_t.h" namespace spdlog { diff --git a/include/spdlog/fmt/bin_to_hex.h b/include/spdlog/fmt/bin_to_hex.h index ae3c15885..86bfed1ec 100644 --- a/include/spdlog/fmt/bin_to_hex.h +++ b/include/spdlog/fmt/bin_to_hex.h @@ -88,10 +88,8 @@ inline details::dump_info to_hex(const It range_begin, const It range_end, s } // namespace spdlog -namespace fmt { - template -struct formatter, char> { +struct fmt::formatter, char> { const char delimiter = ' '; bool put_newlines = true; bool put_delimiters = true; @@ -123,6 +121,7 @@ struct formatter, char> { show_ascii = true; } break; + default:; } ++it; @@ -202,5 +201,4 @@ struct formatter, char> { spdlog::fmt_lib::format_to(inserter, SPDLOG_FMT_STRING("{:04X}: "), pos); } } -}; -} // namespace fmt +}; // namespace fmt diff --git a/include/spdlog/sinks/daily_file_sink.h b/include/spdlog/sinks/daily_file_sink.h index 684777074..80145dbb5 100644 --- a/include/spdlog/sinks/daily_file_sink.h +++ b/include/spdlog/sinks/daily_file_sink.h @@ -11,13 +11,12 @@ #include #include "../common.h" -#include "./base_sink.h" #include "../details/circular_q.h" #include "../details/file_helper.h" #include "../details/null_mutex.h" #include "../details/os.h" #include "../details/synchronous_factory.h" - +#include "./base_sink.h" namespace spdlog { namespace sinks { @@ -25,21 +24,21 @@ namespace sinks { /* * Generator of daily log file names in format basename_YYYY-MM-DD.ext */ -struct daily_filename_calculator { +struct daily_filename_calculator { static filename_t calc_filename(const filename_t &filename, const tm &now_tm) { filename_t basename, ext; std::tie(basename, ext) = details::os::split_by_extension(filename); - std::basic_ostringstream oss; + std::basic_ostringstream oss; oss << basename.native() << '_' << std::setfill(SPDLOG_FILENAME_T('0')) << std::setw(4) << now_tm.tm_year + 1900 << '-' << std::setw(2) << now_tm.tm_mon + 1 << '-' << std::setw(2) << now_tm.tm_mday << ext.native(); - return oss.str(); + return oss.str(); } }; /* * Generator of daily log file names with strftime format. * Usages: - * + * * std::make_shared("myapp-%Y-%m-%d:%H:%M:%S.log", hour, minute); * or * spdlog::daily_logger_format_mt("loggername, "myapp-%Y-%m-%d:%X.log", hour, minute)" diff --git a/include/spdlog/sinks/dup_filter_sink.h b/include/spdlog/sinks/dup_filter_sink.h index 896f6e0b1..f0530d578 100644 --- a/include/spdlog/sinks/dup_filter_sink.h +++ b/include/spdlog/sinks/dup_filter_sink.h @@ -37,7 +37,7 @@ namespace spdlog { namespace sinks { template -class dup_filter_sink : public dist_sink { +class dup_filter_sink final : public dist_sink { public: template explicit dup_filter_sink(std::chrono::duration max_skip_duration, level notification_level = level::info) diff --git a/include/spdlog/sinks/hourly_file_sink.h b/include/spdlog/sinks/hourly_file_sink.h index d1460113a..cff218f08 100644 --- a/include/spdlog/sinks/hourly_file_sink.h +++ b/include/spdlog/sinks/hourly_file_sink.h @@ -28,11 +28,11 @@ struct hourly_filename_calculator { static filename_t calc_filename(const filename_t &filename, const tm &now_tm) { filename_t basename, ext; std::tie(basename, ext) = details::os::split_by_extension(filename); - std::basic_ostringstream oss; + std::basic_ostringstream oss; oss << basename.native() << '_' << std::setfill(SPDLOG_FILENAME_T('0')) << std::setw(4) << now_tm.tm_year + 1900 << '-' << std::setw(2) << now_tm.tm_mon + 1 << '-' << std::setw(2) << now_tm.tm_mday << '_' << std::setw(2) << now_tm.tm_hour << ext.native(); - return oss.str(); + return oss.str(); } }; @@ -47,10 +47,10 @@ template class hourly_file_sink final : public base_sink { public: // create hourly file sink which rotates on given time - hourly_file_sink(filename_t base_filename, - bool truncate = false, - uint16_t max_files = 0, - const file_event_handlers &event_handlers = {}) + explicit hourly_file_sink(filename_t base_filename, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) : base_filename_(std::move(base_filename)), file_helper_{event_handlers}, truncate_(truncate), diff --git a/include/spdlog/sinks/msvc_sink.h b/include/spdlog/sinks/msvc_sink.h index 4b1535c0e..e2e0dd139 100644 --- a/include/spdlog/sinks/msvc_sink.h +++ b/include/spdlog/sinks/msvc_sink.h @@ -21,7 +21,7 @@ template class msvc_sink final : public base_sink { public: msvc_sink() = default; - msvc_sink(bool check_debugger_present) + explicit msvc_sink(bool check_debugger_present) : check_debugger_present_{check_debugger_present} {} protected: diff --git a/include/spdlog/sinks/syslog_sink.h b/include/spdlog/sinks/syslog_sink.h index cb7249347..65f74bfab 100644 --- a/include/spdlog/sinks/syslog_sink.h +++ b/include/spdlog/sinks/syslog_sink.h @@ -17,7 +17,7 @@ namespace sinks { * Sink that write to syslog using the `syscall()` library call. */ template -class syslog_sink : public base_sink { +class syslog_sink final : public base_sink { public: syslog_sink(std::string ident, int syslog_option, int syslog_facility, bool enable_formatting) : enable_formatting_{enable_formatting}, diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 590e4a6fb..eb6ba4b2d 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -9,14 +9,12 @@ #pragma once -#include -#include #include #include #include #include "./common.h" -#include "./details/registry.h" +#include "./details/context.h" #include "./details/synchronous_factory.h" #include "./logger.h" @@ -24,153 +22,107 @@ namespace spdlog { using default_factory = synchronous_factory; -// Create and register a logger with a templated sink type -// The logger's level, formatter and flush level will be set according the -// global settings. -// +SPDLOG_API void set_context(std::shared_ptr context); +SPDLOG_API std::shared_ptr context(); +SPDLOG_API const std::shared_ptr &context_ref(); + +// Create a logger with a templated sink type // Example: // spdlog::create("logger_name", "dailylog_filename", 11, 59); template -inline std::shared_ptr create(std::string logger_name, SinkArgs &&...sink_args) { +std::shared_ptr create(std::string logger_name, SinkArgs &&...sink_args) { return default_factory::create(std::move(logger_name), std::forward(sink_args)...); } -// Initialize and register a logger, -// formatter and flush level will be set according the global settings. -// -// Useful for initializing manually created loggers with the global settings. -// -// Example: -// auto mylogger = std::make_shared("mylogger", ...); -// spdlog::initialize_logger(mylogger); -SPDLOG_API void initialize_logger(std::shared_ptr logger); - -// Return an existing logger or nullptr if a logger with such name doesn't -// exist. -// example: spdlog::get("my_logger")->info("hello {}", "world"); -SPDLOG_API std::shared_ptr get(const std::string &name); -SPDLOG_API std::shared_ptr get(std::string_view name); -SPDLOG_API std::shared_ptr get(const char *name); +// Set formatter of the global logger. Each sink in each logger will get a clone of this object +SPDLOG_API void set_formatter(std::unique_ptr formatter); -// Set global formatter. Each sink in each logger will get a clone of this object -SPDLOG_API void set_formatter(std::unique_ptr formatter); - -// Set global format string. +// Set format string of the global logger. // example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v"); SPDLOG_API void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local); -// Get global logging level +// Get logging level of the global logger SPDLOG_API level get_level(); -// Set global logging level +// Set logging level of the global logger SPDLOG_API void set_level(level level); -// Determine whether the default logger should log messages with a certain level +// Determine whether the global logger should log messages with a certain level SPDLOG_API bool should_log(level level); -// Set global flush level +// Set flush level of the global logger. SPDLOG_API void flush_on(level level); -// Start/Restart a periodic flusher thread -// Warning: Use only if all your loggers are thread safe! -template -inline void flush_every(std::chrono::duration interval) { - details::registry::instance().flush_every(interval); -} - -// Set global error handler +// Set error handler for the global logger SPDLOG_API void set_error_handler(void (*handler)(const std::string &msg)); -// Register the given logger with the given name -SPDLOG_API void register_logger(std::shared_ptr logger); - -// Apply a user defined function on all registered loggers -// Example: -// spdlog::apply_all([&](std::shared_ptr l) {l->flush();}); -SPDLOG_API void apply_all(const std::function)> &fun); - -// Drop the reference to the given logger -SPDLOG_API void drop(const std::string &name); - -// Drop all references from the registry -SPDLOG_API void drop_all(); - -// stop any running threads started by spdlog and clean registry loggers +// calls context::shutdown() to perform final cleanups SPDLOG_API void shutdown(); -// Automatic registration of loggers when using spdlog::create() or spdlog::create_async -SPDLOG_API void set_automatic_registration(bool automatic_registration); - -// API for using default logger (stdout_color_mt), +// API for using global logger (stdout_color_mt), // e.g: spdlog::info("Message {}", 1); // -// The default logger object can be accessed using the spdlog::default_logger(): +// The global logger object can be accessed using the spdlog::global_logger(): // For example, to add another sink to it: -// spdlog::default_logger()->sinks().push_back(some_sink); +// spdlog::global_logger()->sinks().push_back(some_sink); // -// The default logger can replaced using spdlog::set_default_logger(new_logger). +// The global logger can be replaced using spdlog::set_global_logger(new_logger). // For example, to replace it with a file logger. // // IMPORTANT: -// The default API is thread safe (for _mt loggers), but: -// set_default_logger() *should not* be used concurrently with the default API. -// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another. - -SPDLOG_API std::shared_ptr default_logger(); +// Do not call set_global_logger() from one thread while calling spdlog::info() from another. +SPDLOG_API std::shared_ptr global_logger(); -SPDLOG_API spdlog::logger *default_logger_raw(); +// Set the global logger. (for example, to replace the global logger with a custom logger) +SPDLOG_API void set_global_logger(std::shared_ptr global_logger); -SPDLOG_API void set_default_logger(std::shared_ptr default_logger); - -// Initialize logger level based on environment configs. -// -// Useful for applying SPDLOG_LEVEL to manually created loggers. -// -// Example: -// auto mylogger = std::make_shared("mylogger", ...); -// spdlog::apply_logger_env_levels(mylogger); -SPDLOG_API void apply_logger_env_levels(std::shared_ptr logger); +// Return the global logger raw pointer. +// To be used directly by the spdlog default API (e.g. spdlog::info) +// This make the default API faster, but cannot be used concurrently with set_global_logger(). +// e.g do not call set_global_logger() from one thread while calling spdlog::info() from another. +SPDLOG_API logger *global_logger_raw() noexcept; template -inline void log(source_loc source, level lvl, format_string_t fmt, Args &&...args) { - default_logger_raw()->log(source, lvl, fmt, std::forward(args)...); +void log(source_loc source, level lvl, format_string_t fmt, Args &&...args) { + global_logger_raw()->log(source, lvl, fmt, std::forward(args)...); } template -inline void log(level lvl, format_string_t fmt, Args &&...args) { - default_logger_raw()->log(lvl, fmt, std::forward(args)...); +void log(level lvl, format_string_t fmt, Args &&...args) { + global_logger_raw()->log(lvl, fmt, std::forward(args)...); } -inline void log(level lvl, std::string_view msg) { default_logger_raw()->log(lvl, msg); } -inline void log(source_loc loc, level lvl, std::string_view msg) { default_logger_raw()->log(loc, lvl, msg); } +inline void log(level lvl, std::string_view msg) { global_logger_raw()->log(lvl, msg); } + +inline void log(source_loc loc, level lvl, std::string_view msg) { global_logger_raw()->log(loc, lvl, msg); } template -inline void trace(format_string_t fmt, Args &&...args) { +void trace(format_string_t fmt, Args &&...args) { log(level::trace, fmt, std::forward(args)...); } template -inline void debug(format_string_t fmt, Args &&...args) { +void debug(format_string_t fmt, Args &&...args) { log(level::debug, fmt, std::forward(args)...); } template -inline void info(format_string_t fmt, Args &&...args) { +void info(format_string_t fmt, Args &&...args) { log(level::info, fmt, std::forward(args)...); } template -inline void warn(format_string_t fmt, Args &&...args) { +void warn(format_string_t fmt, Args &&...args) { log(level::warn, fmt, std::forward(args)...); } template -inline void error(format_string_t fmt, Args &&...args) { +void error(format_string_t fmt, Args &&...args) { log(level::err, fmt, std::forward(args)...); } template -inline void critical(format_string_t fmt, Args &&...args) { +void critical(format_string_t fmt, Args &&...args) { log(level::critical, fmt, std::forward(args)...); } @@ -211,7 +163,7 @@ inline void critical(std::string_view msg) { log(level::critical, msg); } #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE #define SPDLOG_LOGGER_TRACE(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::trace, __VA_ARGS__) - #define SPDLOG_TRACE(...) SPDLOG_LOGGER_TRACE(spdlog::default_logger_raw(), __VA_ARGS__) + #define SPDLOG_TRACE(...) SPDLOG_LOGGER_TRACE(spdlog::global_logger_raw(), __VA_ARGS__) #else #define SPDLOG_LOGGER_TRACE(logger, ...) (void)0 #define SPDLOG_TRACE(...) (void)0 @@ -219,7 +171,7 @@ inline void critical(std::string_view msg) { log(level::critical, msg); } #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_DEBUG #define SPDLOG_LOGGER_DEBUG(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::debug, __VA_ARGS__) - #define SPDLOG_DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__) + #define SPDLOG_DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::global_logger(), __VA_ARGS__) #else #define SPDLOG_LOGGER_DEBUG(logger, ...) (void)0 #define SPDLOG_DEBUG(...) (void)0 @@ -227,7 +179,7 @@ inline void critical(std::string_view msg) { log(level::critical, msg); } #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_INFO #define SPDLOG_LOGGER_INFO(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::info, __VA_ARGS__) - #define SPDLOG_INFO(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__) + #define SPDLOG_INFO(...) SPDLOG_LOGGER_INFO(spdlog::global_logger(), __VA_ARGS__) #else #define SPDLOG_LOGGER_INFO(logger, ...) (void)0 #define SPDLOG_INFO(...) (void)0 @@ -235,7 +187,7 @@ inline void critical(std::string_view msg) { log(level::critical, msg); } #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_WARN #define SPDLOG_LOGGER_WARN(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::warn, __VA_ARGS__) - #define SPDLOG_WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__) + #define SPDLOG_WARN(...) SPDLOG_LOGGER_WARN(spdlog::global_logger(), __VA_ARGS__) #else #define SPDLOG_LOGGER_WARN(logger, ...) (void)0 #define SPDLOG_WARN(...) (void)0 @@ -243,7 +195,7 @@ inline void critical(std::string_view msg) { log(level::critical, msg); } #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_ERROR #define SPDLOG_LOGGER_ERROR(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::err, __VA_ARGS__) - #define SPDLOG_ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__) + #define SPDLOG_ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::global_logger(), __VA_ARGS__) #else #define SPDLOG_LOGGER_ERROR(logger, ...) (void)0 #define SPDLOG_ERROR(...) (void)0 @@ -251,7 +203,7 @@ inline void critical(std::string_view msg) { log(level::critical, msg); } #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_CRITICAL #define SPDLOG_LOGGER_CRITICAL(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::critical, __VA_ARGS__) - #define SPDLOG_CRITICAL(...) SPDLOG_LOGGER_CRITICAL(spdlog::default_logger_raw(), __VA_ARGS__) + #define SPDLOG_CRITICAL(...) SPDLOG_LOGGER_CRITICAL(spdlog::global_logger(), __VA_ARGS__) #else #define SPDLOG_LOGGER_CRITICAL(logger, ...) (void)0 #define SPDLOG_CRITICAL(...) (void)0 diff --git a/include/spdlog/stopwatch.h b/include/spdlog/stopwatch.h index f101749e6..cdd9b8b48 100644 --- a/include/spdlog/stopwatch.h +++ b/include/spdlog/stopwatch.h @@ -51,13 +51,10 @@ class stopwatch { } // namespace spdlog // Support for fmt formatting (e.g. "{:012.9}" or just "{}") -namespace fmt { - template <> -struct formatter : formatter { +struct fmt::formatter : formatter { template auto format(const spdlog::stopwatch &sw, FormatContext &ctx) const -> decltype(ctx.out()) { return formatter::format(sw.elapsed().count(), ctx); } -}; -} // namespace fmt +}; // namespace fmt diff --git a/logos/jetbrains-variant-4.svg b/logos/jetbrains-variant-4.svg index e02b55951..5231032c7 100644 --- a/logos/jetbrains-variant-4.svg +++ b/logos/jetbrains-variant-4.svg @@ -1,4 +1,4 @@ - + diff --git a/src/cfg/helpers.cpp b/src/cfg/helpers.cpp deleted file mode 100644 index 29e9c961d..000000000 --- a/src/cfg/helpers.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#include "spdlog/cfg/helpers.h" - -#include -#include -#include -#include - -#include "spdlog/details/registry.h" - -namespace spdlog { -namespace cfg { -namespace helpers { - -// inplace convert to lowercase -inline std::string &to_lower_(std::string &str) { - std::transform(str.begin(), str.end(), str.begin(), - [](char ch) { return static_cast((ch >= 'A' && ch <= 'Z') ? ch + ('a' - 'A') : ch); }); - return str; -} - -// inplace trim spaces -inline std::string &trim_(std::string &str) { - const char *spaces = " \n\r\t"; - str.erase(str.find_last_not_of(spaces) + 1); - str.erase(0, str.find_first_not_of(spaces)); - return str; -} - -// return (name,value) trimmed pair from given "name=value" string. -// return empty string on missing parts -// "key=val" => ("key", "val") -// " key = val " => ("key", "val") -// "key=" => ("key", "") -// "val" => ("", "val") - -inline std::pair extract_kv_(char sep, const std::string &str) { - auto n = str.find(sep); - std::string k, v; - if (n == std::string::npos) { - v = str; - } else { - k = str.substr(0, n); - v = str.substr(n + 1); - } - return std::make_pair(trim_(k), trim_(v)); -} - -// return vector of key/value pairs from sequence of "K1=V1,K2=V2,.." -// "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...} -inline std::unordered_map extract_key_vals_(const std::string &str) { - std::string token; - std::istringstream token_stream(str); - std::unordered_map rv{}; - while (std::getline(token_stream, token, ',')) { - if (token.empty()) { - continue; - } - auto kv = extract_kv_('=', token); - rv[kv.first] = kv.second; - } - return rv; -} - -void load_levels(const std::string &input) { - if (input.empty() || input.size() > 512) { - return; - } - - auto key_vals = extract_key_vals_(input); - std::unordered_map levels; - level global_level = level::info; - bool global_level_found = false; - - for (auto &name_level : key_vals) { - const auto &logger_name = name_level.first; - auto level_name = to_lower_(name_level.second); - auto level = level_from_str(level_name); - // ignore unrecognized level names - if (level == level::off && level_name != "off") { - continue; - } - if (logger_name.empty()) // no logger name indicate global level - { - global_level_found = true; - global_level = level; - } else { - levels[logger_name] = level; - } - } - - details::registry::instance().set_levels(std::move(levels), global_level_found ? &global_level : nullptr); -} - -} // namespace helpers -} // namespace cfg -} // namespace spdlog diff --git a/src/details/context.cpp b/src/details/context.cpp new file mode 100644 index 000000000..580a5e219 --- /dev/null +++ b/src/details/context.cpp @@ -0,0 +1,49 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#include "spdlog/details/context.h" + +#include "spdlog/logger.h" + +#ifndef SPDLOG_DISABLE_GLOBAL_LOGGER + #include "spdlog/sinks/stdout_color_sinks.h" +#endif // SPDLOG_DISABLE_GLOBAL_LOGGER + +#include + +namespace spdlog { +namespace details { + +context::context(std::unique_ptr global_logger) { global_logger_ = std::move(global_logger); } + +std::shared_ptr context::global_logger() { return global_logger_; } + +// Return raw ptr to the global logger. +// To be used directly by the spdlog default api (e.g. spdlog::info) +// This make the default API faster, but cannot be used concurrently with set_global_logger(). +// e.g do not call set_global_logger() from one thread while calling spdlog::info() from another. +logger *context::global_logger_raw() const noexcept { return global_logger_.get(); } + +// set global logger +void context::set_logger(std::shared_ptr new_global_logger) { global_logger_ = std::move(new_global_logger); } + +void context::set_tp(std::shared_ptr tp) { + std::lock_guard lock(tp_mutex_); + tp_ = std::move(tp); +} + +std::shared_ptr context::get_tp() { + std::lock_guard lock(tp_mutex_); + return tp_; +} + +// clean all resources and threads started by the registry +void context::shutdown() { + std::lock_guard lock(tp_mutex_); + tp_.reset(); +} + +std::recursive_mutex &context::tp_mutex() { return tp_mutex_; } + +} // namespace details +} // namespace spdlog diff --git a/src/details/file_helper.cpp b/src/details/file_helper.cpp index efc3160a4..dd4060758 100644 --- a/src/details/file_helper.cpp +++ b/src/details/file_helper.cpp @@ -1,13 +1,13 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) +#include "spdlog/details/file_helper.h" #include #include -#include #include +#include -#include "spdlog/details/file_helper.h" #include "spdlog/common.h" #include "spdlog/details/os.h" @@ -29,9 +29,11 @@ void file_helper::open(const filename_t &fname, bool truncate) { if (event_handlers_.before_open) { event_handlers_.before_open(filename_); } + + // create containing folder if not exists already. + os::create_dir(os::dir_name(fname)); + for (int tries = 0; tries < open_tries_; ++tries) { - // create containing folder if not exists already. - os::create_dir(os::dir_name(fname)); if (truncate) { // Truncate by opening-and-closing a tmp file in "wb" mode, always // opening the actual log-we-write-to in "ab" mode, since that @@ -108,6 +110,5 @@ size_t file_helper::size() const { const filename_t &file_helper::filename() const { return filename_; } - } // namespace details } // namespace spdlog diff --git a/src/details/os_filesystem.cpp b/src/details/os_filesystem.cpp index f811cb543..45c53c55e 100644 --- a/src/details/os_filesystem.cpp +++ b/src/details/os_filesystem.cpp @@ -11,9 +11,7 @@ namespace spdlog { namespace details { namespace os { -bool remove(const filename_t &filename) { - return std::filesystem::remove(filename); -} +bool remove(const filename_t &filename) { return std::filesystem::remove(filename); } bool remove_if_exists(const filename_t &filename) { if (path_exists(filename)) { @@ -42,7 +40,6 @@ bool path_exists(const filename_t &filename) noexcept { return std::filesystem:: // "abc///" => "abc//" filename_t dir_name(const filename_t &path) { return path.parent_path(); } - // Create the given directory - and all directories leading to it // return true on success or if the directory already exists bool create_dir(const filename_t &path) { @@ -50,19 +47,13 @@ bool create_dir(const filename_t &path) { return std::filesystem::create_directories(path, ec) || !ec; } - // Return file path and its extension: // // "mylog.txt" => ("mylog", ".txt") // "mylog" => ("mylog", "") // "mylog." => ("mylog", ".") // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") -// -// the starting dot in filenames is ignored (hidden files): -// -// ".mylog" => (".mylog". "") -// "my_folder/.mylog" => ("my_folder/.mylog", "") -// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") +// ".mylog" => (".mylog", "") std::tuple split_by_extension(const filename_t &fname) { const auto ext = fname.extension(); auto without_ext = filename_t(fname).replace_extension(); diff --git a/src/details/os_unix.cpp b/src/details/os_unix.cpp index 98550bc3a..5149828b1 100644 --- a/src/details/os_unix.cpp +++ b/src/details/os_unix.cpp @@ -99,7 +99,6 @@ bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) { return *fp == nullptr; } - // Return file size according to open FILE* object size_t filesize(FILE *f) { if (f == nullptr) { @@ -231,9 +230,9 @@ void sleep_for_millis(unsigned int milliseconds) noexcept { std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); } -std::string filename_to_str(const filename_t &filename) { +std::string filename_to_str(const filename_t &filename) { static_assert(std::is_same_v, "filename_t type must be char"); - return filename; + return filename; } int pid() noexcept { return static_cast(::getpid()); } diff --git a/src/details/os_windows.cpp b/src/details/os_windows.cpp index c827a897d..e9ea0b15e 100644 --- a/src/details/os_windows.cpp +++ b/src/details/os_windows.cpp @@ -6,7 +6,7 @@ #endif // clang-format off -#include "spdlog/details/windows_include.h" +#include "spdlog/details/windows_include.h" // must be included before fileapi.h etc. // clang-format on #include // for FlushFileBuffers @@ -75,8 +75,6 @@ bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) { return *fp == nullptr; } - - #ifdef _MSC_VER // avoid warning about unreachable statement at the end of filesize() #pragma warning(push) @@ -151,15 +149,13 @@ void sleep_for_millis(unsigned int milliseconds) noexcept { ::Sleep(milliseconds // Try tp convert wstring filename to string. Return "???" if failed std::string filename_to_str(const filename_t &filename) { static_assert(std::is_same_v, "filename_t type must be wchar_t"); - try { + try { memory_buf_t buf; wstr_to_utf8buf(filename.wstring(), buf); return std::string(buf.data(), buf.size()); + } catch (...) { + return "???"; } - catch (...) { - return "???"; - } - } int pid() noexcept { return static_cast(::GetCurrentProcessId()); } @@ -224,7 +220,6 @@ void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target) { throw_spdlog_ex(fmt_lib::format("MultiByteToWideChar failed. Last error: {}", ::GetLastError())); } - std::string getenv(const char *field) { #if defined(_MSC_VER) #if defined(__cplusplus_winrt) diff --git a/src/details/periodic_worker.cpp b/src/details/periodic_worker.cpp deleted file mode 100644 index 9a54b2658..000000000 --- a/src/details/periodic_worker.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#include "spdlog/details/periodic_worker.h" - -namespace spdlog { -namespace details { - -// stop the worker thread and join it -periodic_worker::~periodic_worker() { - if (worker_thread_.joinable()) { - { - std::lock_guard lock(mutex_); - active_ = false; - } - cv_.notify_one(); - worker_thread_.join(); - } -} - -} // namespace details -} // namespace spdlog diff --git a/src/details/registry.cpp b/src/details/registry.cpp deleted file mode 100644 index 2055b739c..000000000 --- a/src/details/registry.cpp +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#include "spdlog/details/registry.h" - -#include "spdlog/common.h" -#include "spdlog/logger.h" -#include "spdlog/pattern_formatter.h" - -#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER - // support for the default stdout color logger - #ifdef _WIN32 - #include "spdlog/sinks/wincolor_sink.h" - #else - - #include "spdlog/sinks/ansicolor_sink.h" - - #endif -#endif // SPDLOG_DISABLE_DEFAULT_LOGGER - -#include -#include -#include - -static constexpr size_t small_map_threshold = 10; - -namespace spdlog { -namespace details { - -registry::registry() - : formatter_(new pattern_formatter()) { -#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER - // create default logger (ansicolor_stdout_sink_mt or wincolor_stdout_sink_mt in windows). - #ifdef _WIN32 - auto color_sink = std::make_shared(); - #else - auto color_sink = std::make_shared(); - #endif - const char *default_logger_name = ""; - default_logger_ = std::make_shared(default_logger_name, std::move(color_sink)); - loggers_[default_logger_name] = default_logger_; - -#endif // SPDLOG_DISABLE_DEFAULT_LOGGER -} - -registry::~registry() = default; - -void registry::register_logger(std::shared_ptr new_logger) { - std::lock_guard lock(logger_map_mutex_); - register_logger_(std::move(new_logger)); -} - -void registry::initialize_logger(std::shared_ptr new_logger) { - std::lock_guard lock(logger_map_mutex_); - new_logger->set_formatter(formatter_->clone()); - - if (err_handler_) { - new_logger->set_error_handler(err_handler_); - } - - // set new level according to previously configured level or default level - auto it = log_levels_.find(new_logger->name()); - auto new_level = it != log_levels_.end() ? it->second : global_log_level_; - new_logger->set_level(new_level); - - new_logger->flush_on(flush_level_); - - if (automatic_registration_) { - register_logger_(std::move(new_logger)); - } -} - -// if the map is small do a sequential search, otherwise use the standard find() -std::shared_ptr registry::get(const std::string &logger_name) { - std::lock_guard lock(logger_map_mutex_); - if (loggers_.size() <= small_map_threshold) { - for (const auto &[key, val] : loggers_) { - if (logger_name == key) { - return val; - } - } - return nullptr; - } - auto found = loggers_.find(logger_name); - return found == loggers_.end() ? nullptr : found->second; -} - -// if the map is small do a sequential search and avoid creating string for find(logger_name) -// otherwise use the standard find() -std::shared_ptr registry::get(std::string_view logger_name) { - std::lock_guard lock(logger_map_mutex_); - if (loggers_.size() <= small_map_threshold) { - for (const auto &[key, val] : loggers_) { - if (logger_name == key) { - return val; - } - } - return nullptr; - } - // otherwise use the normal map lookup - const auto found = loggers_.find(std::string(logger_name)); - return found == loggers_.end() ? nullptr : found->second; -} - -std::shared_ptr registry::get(const char *logger_name) { return get(std::string_view(logger_name)); } - -std::shared_ptr registry::default_logger() { - std::lock_guard lock(logger_map_mutex_); - return default_logger_; -} - -// Return raw ptr to the default logger. -// To be used directly by the spdlog default api (e.g. spdlog::info) -// This make the default API faster, but cannot be used concurrently with set_default_logger(). -// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another. -logger *registry::get_default_raw() const { return default_logger_.get(); } - -// set default logger. -// default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. -void registry::set_default_logger(std::shared_ptr new_default_logger) { - std::lock_guard lock(logger_map_mutex_); - if (new_default_logger != nullptr) { - loggers_[new_default_logger->name()] = new_default_logger; - } - default_logger_ = std::move(new_default_logger); -} - -void registry::set_tp(std::shared_ptr tp) { - std::lock_guard lock(tp_mutex_); - tp_ = std::move(tp); -} - -std::shared_ptr registry::get_tp() { - std::lock_guard lock(tp_mutex_); - return tp_; -} - -// Set global formatter. Each sink in each logger will get a clone of this object -void registry::set_formatter(std::unique_ptr formatter) { - std::lock_guard lock(logger_map_mutex_); - formatter_ = std::move(formatter); - for (auto &l : loggers_) { - l.second->set_formatter(formatter_->clone()); - } -} - -void registry::set_level(level level) { - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) { - l.second->set_level(level); - } - global_log_level_ = level; -} - -void registry::flush_on(level level) { - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) { - l.second->flush_on(level); - } - flush_level_ = level; -} - -void registry::set_error_handler(err_handler handler) { - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) { - l.second->set_error_handler(handler); - } - err_handler_ = std::move(handler); -} - -void registry::apply_all(const std::function)> &fun) { - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) { - fun(l.second); - } -} - -void registry::flush_all() { - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) { - l.second->flush(); - } -} - -void registry::drop(const std::string &logger_name) { - std::lock_guard lock(logger_map_mutex_); - auto is_default_logger = default_logger_ && default_logger_->name() == logger_name; - loggers_.erase(logger_name); - if (is_default_logger) { - default_logger_.reset(); - } -} - -void registry::drop_all() { - std::lock_guard lock(logger_map_mutex_); - loggers_.clear(); - default_logger_.reset(); -} - -// clean all resources and threads started by the registry -void registry::shutdown() { - { - std::lock_guard lock(flusher_mutex_); - periodic_flusher_.reset(); - } - - drop_all(); - - { - std::lock_guard lock(tp_mutex_); - tp_.reset(); - } -} - -std::recursive_mutex ®istry::tp_mutex() { return tp_mutex_; } - -void registry::set_automatic_registration(bool automatic_registration) { - std::lock_guard lock(logger_map_mutex_); - automatic_registration_ = automatic_registration; -} - -void registry::set_levels(log_levels levels, level *global_level) { - std::lock_guard lock(logger_map_mutex_); - log_levels_ = std::move(levels); - auto global_level_requested = global_level != nullptr; - global_log_level_ = global_level_requested ? *global_level : global_log_level_; - - for (auto &logger : loggers_) { - auto logger_entry = log_levels_.find(logger.first); - if (logger_entry != log_levels_.end()) { - logger.second->set_level(logger_entry->second); - } else if (global_level_requested) { - logger.second->set_level(*global_level); - } - } -} - -registry ®istry::instance() { - static registry s_instance; - return s_instance; -} - -void registry::apply_logger_env_levels(std::shared_ptr new_logger) { - std::lock_guard lock(logger_map_mutex_); - auto it = log_levels_.find(new_logger->name()); - auto new_level = it != log_levels_.end() ? it->second : global_log_level_; - new_logger->set_level(new_level); -} - -void registry::throw_if_exists_(const std::string &logger_name) { - if (loggers_.find(logger_name) != loggers_.end()) { - throw_spdlog_ex("logger with name '" + logger_name + "' already exists"); - } -} - -void registry::register_logger_(std::shared_ptr new_logger) { - auto logger_name = new_logger->name(); - throw_if_exists_(logger_name); - loggers_[logger_name] = std::move(new_logger); -} - -} // namespace details -} // namespace spdlog diff --git a/src/sinks/rotating_file_sink.cpp b/src/sinks/rotating_file_sink.cpp index e55845c63..776dbf0f0 100644 --- a/src/sinks/rotating_file_sink.cpp +++ b/src/sinks/rotating_file_sink.cpp @@ -5,9 +5,9 @@ #include #include +#include #include #include -#include #include "spdlog/common.h" #include "spdlog/details/file_helper.h" @@ -51,10 +51,10 @@ filename_t rotating_file_sink::calc_filename(const filename_t &filename, filename_t basename; filename_t ext; - std::tie(basename, ext) = details::os::split_by_extension(filename); + std::tie(basename, ext) = details::os::split_by_extension(filename); std::basic_ostringstream oss; oss << basename.native() << '.' << index << ext.native(); - return oss.str(); + return oss.str(); } template @@ -132,7 +132,7 @@ void rotating_file_sink::rotate_() { // delete the target if exists, and rename the src file to target // return true on success, false otherwise. template -bool rotating_file_sink::rename_file_(const filename_t &src_filename, const filename_t &target_filename) noexcept{ +bool rotating_file_sink::rename_file_(const filename_t &src_filename, const filename_t &target_filename) noexcept { return details::os::rename(src_filename, target_filename); } diff --git a/src/spdlog.cpp b/src/spdlog.cpp index f7e125ff3..f364fa3c1 100644 --- a/src/spdlog.cpp +++ b/src/spdlog.cpp @@ -3,6 +3,7 @@ #include "spdlog/spdlog.h" +#include #include #include "spdlog/common.h" @@ -12,55 +13,45 @@ namespace spdlog { -void initialize_logger(std::shared_ptr logger) { details::registry::instance().initialize_logger(std::move(logger)); } +static std::shared_ptr s_context = +#ifndef SPDLOG_DISABLE_GLOBAL_LOGGER + std::make_unique(std::make_unique(std::string(), std::make_unique())); +#else + std::make_unique(); // empty context +#endif -std::shared_ptr get(const std::string &name) { return details::registry::instance().get(name); } +void set_context(std::shared_ptr context) { s_context = std::move(context); } -std::shared_ptr get(std::string_view name) { return details::registry::instance().get(name); } +std::shared_ptr context() { return s_context; } -std::shared_ptr get(const char *name) { return details::registry::instance().get(name); } +const std::shared_ptr &context_ref() { return s_context; } -void set_formatter(std::unique_ptr formatter) { - details::registry::instance().set_formatter(std::move(formatter)); -} - -void set_pattern(std::string pattern, pattern_time_type time_type) { - set_formatter(std::make_unique(std::move(pattern), time_type)); -} - -level get_level() { return default_logger_raw()->log_level(); } - -bool should_log(level level) { return default_logger_raw()->should_log(level); } - -void set_level(level level) { details::registry::instance().set_level(level); } +std::shared_ptr global_logger() { return context_ref()->global_logger(); } -void flush_on(level level) { details::registry::instance().flush_on(level); } +void set_global_logger(std::shared_ptr global_logger) { context()->set_logger(std::move(global_logger)); } -void set_error_handler(void (*handler)(const std::string &msg)) { details::registry::instance().set_error_handler(handler); } +logger *global_logger_raw() noexcept { + auto *rv = context_ref()->global_logger_raw(); + assert(rv != nullptr); + return rv; +} -void register_logger(std::shared_ptr logger) { details::registry::instance().register_logger(std::move(logger)); } +void set_formatter(std::unique_ptr formatter) { global_logger()->set_formatter(std::move(formatter)); } -void apply_all(const std::function)> &fun) { details::registry::instance().apply_all(fun); } +void set_pattern(std::string pattern, pattern_time_type time_type) { + set_formatter(std::make_unique(std::move(pattern), time_type)); +} -void drop(const std::string &name) { details::registry::instance().drop(name); } +level get_level() { return global_logger()->log_level(); } -void drop_all() { details::registry::instance().drop_all(); } +bool should_log(level level) { return global_logger()->should_log(level); } -void shutdown() { details::registry::instance().shutdown(); } +void set_level(level level) { global_logger()->set_level(level); } -void set_automatic_registration(bool automatic_registration) { - details::registry::instance().set_automatic_registration(automatic_registration); -} +void flush_on(level level) { global_logger()->flush_on(level); } -std::shared_ptr default_logger() { return details::registry::instance().default_logger(); } +void set_error_handler(void (*handler)(const std::string &msg)) { global_logger()->set_error_handler(handler); } -spdlog::logger *default_logger_raw() { return details::registry::instance().get_default_raw(); } +void shutdown() { s_context.reset(); } -void set_default_logger(std::shared_ptr default_logger) { - details::registry::instance().set_default_logger(std::move(default_logger)); -} - -void apply_logger_env_levels(std::shared_ptr logger) { - details::registry::instance().apply_logger_env_levels(std::move(logger)); -} } // namespace spdlog diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 647fff0f7..acd02d024 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -34,8 +34,7 @@ set(SPDLOG_UTESTS_SOURCES test_misc.cpp test_pattern_formatter.cpp test_async.cpp - test_registry.cpp - test_macros.cpp + test_macros.cpp utils.cpp main.cpp test_mpmc_q.cpp @@ -44,8 +43,7 @@ set(SPDLOG_UTESTS_SOURCES test_stdout_api.cpp test_create_dir.cpp test_custom_callbacks.cpp - test_cfg.cpp - test_time_point.cpp + test_time_point.cpp test_stopwatch.cpp test_circular_q.cpp test_ringbuffer_sink.cpp diff --git a/tests/test_async.cpp b/tests/test_async.cpp index e31ec953d..8c8a7e667 100644 --- a/tests/test_async.cpp +++ b/tests/test_async.cpp @@ -68,7 +68,6 @@ TEST_CASE("discard policy using factory ", "[async]") { } REQUIRE(test_sink->msg_counter() < messages); - spdlog::drop_all(); } TEST_CASE("flush", "[async]") { @@ -89,17 +88,6 @@ TEST_CASE("flush", "[async]") { REQUIRE(test_sink->flush_counter() == 1); } -TEST_CASE("async periodic flush", "[async]") { - auto logger = spdlog::create_async("as"); - auto test_sink = std::static_pointer_cast(logger->sinks()[0]); - - spdlog::flush_every(std::chrono::seconds(1)); - std::this_thread::sleep_for(std::chrono::milliseconds(1700)); - REQUIRE(test_sink->flush_counter() == 1); - spdlog::flush_every(std::chrono::seconds(0)); - spdlog::drop_all(); -} - TEST_CASE("tp->wait_empty() ", "[async]") { auto test_sink = std::make_shared(); test_sink->set_delay(std::chrono::milliseconds(5)); diff --git a/tests/test_cfg.cpp b/tests/test_cfg.cpp deleted file mode 100644 index 9cfec7b5b..000000000 --- a/tests/test_cfg.cpp +++ /dev/null @@ -1,168 +0,0 @@ - -#include "includes.h" -#include "spdlog/cfg/argv.h" -#include "spdlog/cfg/env.h" -#include "test_sink.h" - -using spdlog::cfg::load_argv_levels; -using spdlog::cfg::load_env_levels; -using spdlog::sinks::test_sink_st; - -TEST_CASE("env", "[cfg]") { - spdlog::drop("l1"); - auto l1 = spdlog::create("l1"); -#ifdef CATCH_PLATFORM_WINDOWS - _putenv_s("SPDLOG_LEVEL", "l1=warn"); -#else - setenv("SPDLOG_LEVEL", "l1=warn", 1); -#endif - load_env_levels(); - REQUIRE(l1->log_level() == spdlog::level::warn); - spdlog::set_default_logger(spdlog::create("cfg-default")); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::info); -} - -TEST_CASE("argv1", "[cfg]") { - spdlog::drop("l1"); - const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=warn"}; - load_argv_levels(2, argv); - auto l1 = spdlog::create("l1"); - REQUIRE(l1->log_level() == spdlog::level::warn); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::info); -} - -TEST_CASE("argv2", "[cfg]") { - spdlog::drop("l1"); - const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=warn,trace"}; - load_argv_levels(2, argv); - auto l1 = spdlog::create("l1"); - REQUIRE(l1->log_level() == spdlog::level::warn); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::trace); -} - -TEST_CASE("argv3", "[cfg]") { - spdlog::set_level(spdlog::level::trace); - - spdlog::drop("l1"); - const char *argv[] = {"ignore", "SPDLOG_LEVEL=junk_name=warn"}; - load_argv_levels(2, argv); - auto l1 = spdlog::create("l1"); - REQUIRE(l1->log_level() == spdlog::level::trace); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::trace); -} - -TEST_CASE("argv4", "[cfg]") { - spdlog::set_level(spdlog::level::info); - spdlog::drop("l1"); - const char *argv[] = {"ignore", "SPDLOG_LEVEL=junk"}; - load_argv_levels(2, argv); - auto l1 = spdlog::create("l1"); - REQUIRE(l1->log_level() == spdlog::level::info); -} - -TEST_CASE("argv5", "[cfg]") { - spdlog::set_level(spdlog::level::info); - spdlog::drop("l1"); - const char *argv[] = {"ignore", "ignore", "SPDLOG_LEVEL=l1=warn,trace"}; - load_argv_levels(3, argv); - auto l1 = spdlog::create("l1"); - REQUIRE(l1->log_level() == spdlog::level::warn); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::trace); - spdlog::set_level(spdlog::level::info); -} - -TEST_CASE("argv6", "[cfg]") { - spdlog::set_level(spdlog::level::err); - const char *argv[] = {""}; - load_argv_levels(1, argv); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::err); - spdlog::set_level(spdlog::level::info); -} - -TEST_CASE("argv7", "[cfg]") { - spdlog::set_level(spdlog::level::err); - const char *argv[] = {""}; - load_argv_levels(0, argv); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::err); - spdlog::set_level(spdlog::level::info); -} - -TEST_CASE("level-not-set-test1", "[cfg]") { - spdlog::drop("l1"); - const char *argv[] = {"ignore", ""}; - load_argv_levels(2, argv); - auto l1 = spdlog::create("l1"); - l1->set_level(spdlog::level::trace); - REQUIRE(l1->log_level() == spdlog::level::trace); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::info); -} - -TEST_CASE("level-not-set-test2", "[cfg]") { - spdlog::drop("l1"); - spdlog::drop("l2"); - const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=trace"}; - - auto l1 = spdlog::create("l1"); - l1->set_level(spdlog::level::warn); - auto l2 = spdlog::create("l2"); - l2->set_level(spdlog::level::warn); - - load_argv_levels(2, argv); - - REQUIRE(l1->log_level() == spdlog::level::trace); - REQUIRE(l2->log_level() == spdlog::level::warn); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::info); -} - -TEST_CASE("level-not-set-test3", "[cfg]") { - spdlog::drop("l1"); - spdlog::drop("l2"); - const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=trace"}; - - load_argv_levels(2, argv); - - auto l1 = spdlog::create("l1"); - auto l2 = spdlog::create("l2"); - - REQUIRE(l1->log_level() == spdlog::level::trace); - REQUIRE(l2->log_level() == spdlog::level::info); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::info); -} - -TEST_CASE("level-not-set-test4", "[cfg]") { - spdlog::drop("l1"); - spdlog::drop("l2"); - const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=trace,warn"}; - - load_argv_levels(2, argv); - - auto l1 = spdlog::create("l1"); - auto l2 = spdlog::create("l2"); - - REQUIRE(l1->log_level() == spdlog::level::trace); - REQUIRE(l2->log_level() == spdlog::level::warn); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::warn); -} - -TEST_CASE("level-not-set-test5", "[cfg]") { - spdlog::drop("l1"); - spdlog::drop("l2"); - const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=junk,warn"}; - - load_argv_levels(2, argv); - - auto l1 = spdlog::create("l1"); - auto l2 = spdlog::create("l2"); - - REQUIRE(l1->log_level() == spdlog::level::warn); - REQUIRE(l2->log_level() == spdlog::level::warn); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::warn); -} - -TEST_CASE("restore-to-default", "[cfg]") { - spdlog::drop("l1"); - spdlog::drop("l2"); - const char *argv[] = {"ignore", "SPDLOG_LEVEL=info"}; - load_argv_levels(2, argv); - REQUIRE(spdlog::default_logger()->log_level() == spdlog::level::info); -} diff --git a/tests/test_create_dir.cpp b/tests/test_create_dir.cpp index 55b8e2556..0ae46d0b5 100644 --- a/tests/test_create_dir.cpp +++ b/tests/test_create_dir.cpp @@ -43,8 +43,8 @@ TEST_CASE("create_invalid_dir", "[create_dir]") { } TEST_CASE("dir_name", "[create_dir]") { - using spdlog::details::os::dir_name; -#ifdef WIN32 + using spdlog::details::os::dir_name; +#ifdef WIN32 REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\)")) == SPDLOG_FILENAME_T("dir")); REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\\\)")) == SPDLOG_FILENAME_T(R"(dir)")); REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\file)")) == SPDLOG_FILENAME_T("dir")); @@ -60,19 +60,19 @@ TEST_CASE("dir_name", "[create_dir]") { REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(c://a/b/c/d/file.txt)")) == SPDLOG_FILENAME_T(R"(c://a/b/c/d)")); #endif REQUIRE(dir_name(SPDLOG_FILENAME_T("")).empty()); - REQUIRE(dir_name(SPDLOG_FILENAME_T("dir")).empty()); + REQUIRE(dir_name(SPDLOG_FILENAME_T("dir")).empty()); REQUIRE(dir_name(SPDLOG_FILENAME_T("dir/")) == SPDLOG_FILENAME_T("dir")); REQUIRE(dir_name(SPDLOG_FILENAME_T("dir///")) == SPDLOG_FILENAME_T("dir")); REQUIRE(dir_name(SPDLOG_FILENAME_T("dir/file")) == SPDLOG_FILENAME_T("dir")); REQUIRE(dir_name(SPDLOG_FILENAME_T("dir/file.txt")) == SPDLOG_FILENAME_T("dir")); REQUIRE(dir_name(SPDLOG_FILENAME_T("dir/file.txt/")) == SPDLOG_FILENAME_T("dir/file.txt")); - REQUIRE(dir_name(SPDLOG_FILENAME_T("/dir/file.txt")) == SPDLOG_FILENAME_T("/dir")); + REQUIRE(dir_name(SPDLOG_FILENAME_T("/dir/file.txt")) == SPDLOG_FILENAME_T("/dir")); REQUIRE(dir_name(SPDLOG_FILENAME_T("../file.txt")) == SPDLOG_FILENAME_T("..")); REQUIRE(dir_name(SPDLOG_FILENAME_T("./file.txt")) == SPDLOG_FILENAME_T(".")); -#ifdef _WIN32 +#ifdef _WIN32 REQUIRE(dir_name(SPDLOG_FILENAME_T("//dir/file.txt")) == SPDLOG_FILENAME_T("//dir/")); -#else +#else REQUIRE(dir_name(SPDLOG_FILENAME_T("//dir/file.txt")) == SPDLOG_FILENAME_T("//dir")); #endif } diff --git a/tests/test_custom_callbacks.cpp b/tests/test_custom_callbacks.cpp index 6bd923680..5f5a9d07c 100644 --- a/tests/test_custom_callbacks.cpp +++ b/tests/test_custom_callbacks.cpp @@ -30,5 +30,4 @@ TEST_CASE("custom_callback_logger", "[custom_callback_logger]") { REQUIRE(lines[0] == ref_lines[0]); REQUIRE(lines[1] == ref_lines[1]); REQUIRE(lines[2] == ref_lines[2]); - spdlog::drop_all(); } diff --git a/tests/test_daily_and_rotation_loggers.cpp b/tests/test_daily_and_rotation_loggers.cpp index 757404b55..0bc21444a 100644 --- a/tests/test_daily_and_rotation_loggers.cpp +++ b/tests/test_daily_and_rotation_loggers.cpp @@ -4,8 +4,8 @@ */ #include "includes.h" #include "spdlog/sinks/daily_file_sink.h" -#include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/sinks/hourly_file_sink.h" +#include "spdlog/sinks/rotating_file_sink.h" using filename_memory_buf_t = spdlog::memory_buf_t; @@ -48,8 +48,7 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger]") { std::tm tm = spdlog::details::os::localtime(); auto w = spdlog::fmt_lib::format(SPDLOG_FILENAME_T("{}{:04d}{:02d}{:02d}"), basename.native(), tm.tm_year + 1900, - tm.tm_mon + 1, - tm.tm_mday); + tm.tm_mon + 1, tm.tm_mday); auto logger = spdlog::create("logger", basename, 0, 0); for (int i = 0; i < 10; ++i) { @@ -82,26 +81,24 @@ TEST_CASE("rotating_file_sink::calc_filename3", "[rotating_file_sink]") { // regex supported only from gcc 4.9 and above #if defined(_MSC_VER) || !(__GNUC__ <= 4 && __GNUC_MINOR__ < 9) -#include + #include TEST_CASE("daily_file_sink::daily_filename_calculator", "[daily_file_sink]") { // daily_YYYY-MM-DD_hh-mm.txt - auto filename = - spdlog::sinks::daily_filename_calculator::calc_filename(SPDLOG_FILENAME_T("daily.txt"), - spdlog::details::os::localtime()); + auto filename = + spdlog::sinks::daily_filename_calculator::calc_filename(SPDLOG_FILENAME_T("daily.txt"), spdlog::details::os::localtime()); // date regex based on https://www.regular-expressions.info/dates.html - std::basic_regex re( - SPDLOG_FILENAME_T(R"(^daily_(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])\.txt$)")); - - std::match_results match; - REQUIRE(std::regex_match(filename.native(), match, re)); -} + std::basic_regex re( + SPDLOG_FILENAME_T(R"(^daily_(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])\.txt$)")); + std::match_results match; + REQUIRE(std::regex_match(filename.native(), match, re)); +} TEST_CASE("hourly_file_sink::hourly_filename_calculator", "[hrouly_file_sink]") { // daily_YYYY-MM-DD_hh-mm.txt - auto filename = - spdlog::sinks::hourly_filename_calculator::calc_filename(SPDLOG_FILENAME_T("hourly.txt"), spdlog::details::os::localtime()); + auto filename = spdlog::sinks::hourly_filename_calculator::calc_filename(SPDLOG_FILENAME_T("hourly.txt"), + spdlog::details::os::localtime()); // date regex based on https://www.regular-expressions.info/dates.html std::basic_regex re( SPDLOG_FILENAME_T(R"(^hourly_(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])_\d\d\.txt$)")); diff --git a/tests/test_errors.cpp b/tests/test_errors.cpp index 25d0f335c..e3914e5dd 100644 --- a/tests/test_errors.cpp +++ b/tests/test_errors.cpp @@ -10,7 +10,7 @@ #define SIMPLE_LOG "test_logs/simple_log.txt" #define SIMPLE_ASYNC_LOG "test_logs/simple_async_log.txt" -class failing_sink : public spdlog::sinks::base_sink { +class failing_sink final : public spdlog::sinks::base_sink { protected: void sink_it_(const spdlog::details::log_msg &) final { throw std::runtime_error("some error happened during log"); } @@ -21,8 +21,7 @@ struct custom_ex {}; TEST_CASE("default_error_handler", "[errors]") { prepare_logdir(); spdlog::filename_t filename = SPDLOG_FILENAME_T(SIMPLE_LOG); - - auto logger = spdlog::create("test-error", filename, true); + auto logger = spdlog::basic_logger_mt("test-error", filename); logger->set_pattern("%v"); logger->info(SPDLOG_FMT_RUNTIME("Test message {} {}"), 1); logger->info("Test message {}", 2); @@ -35,25 +34,22 @@ TEST_CASE("default_error_handler", "[errors]") { TEST_CASE("custom_error_handler", "[errors]") { prepare_logdir(); spdlog::filename_t filename = SPDLOG_FILENAME_T(SIMPLE_LOG); - auto logger = spdlog::create("logger", filename, true); + auto logger = spdlog::basic_logger_mt("test-error", filename); logger->flush_on(spdlog::level::info); logger->set_error_handler([=](const std::string &) { throw custom_ex(); }); logger->info("Good message #1"); - REQUIRE_THROWS_AS(logger->info(SPDLOG_FMT_RUNTIME("Bad format msg {} {}"), "xxx"), custom_ex); logger->info("Good message #2"); require_message_count(SIMPLE_LOG, 2); } TEST_CASE("default_error_handler2", "[errors]") { - spdlog::drop_all(); - auto logger = spdlog::create("failed_logger"); + auto logger = std::make_shared("failed_logger", std::make_shared()); logger->set_error_handler([=](const std::string &) { throw custom_ex(); }); REQUIRE_THROWS_AS(logger->info("Some message"), custom_ex); } TEST_CASE("flush_error_handler", "[errors]") { - spdlog::drop_all(); auto logger = spdlog::create("failed_logger"); logger->set_error_handler([=](const std::string &) { throw custom_ex(); }); REQUIRE_THROWS_AS(logger->flush(), custom_ex); @@ -77,7 +73,6 @@ TEST_CASE("async_error_handler", "[errors]") { logger->info("Good message #1"); logger->info(SPDLOG_FMT_RUNTIME("Bad format msg {} {}"), "xxx"); logger->info("Good message #2"); - spdlog::drop("logger"); // force logger to drain the queue and shutdown } spdlog::init_thread_pool(128, 1); require_message_count(SIMPLE_ASYNC_LOG, 2); @@ -98,7 +93,6 @@ TEST_CASE("async_error_handler2", "[errors]") { ofs << err_msg; }); logger->info("Hello failure"); - spdlog::drop("failed_logger"); // force logger to drain the queue and shutdown } spdlog::init_thread_pool(128, 1); diff --git a/tests/test_file_helper.cpp b/tests/test_file_helper.cpp index bd5c18fe6..3b61ff2cf 100644 --- a/tests/test_file_helper.cpp +++ b/tests/test_file_helper.cpp @@ -9,7 +9,7 @@ using spdlog::details::file_helper; -static void write_with_helper(file_helper &helper, size_t howmany) { +static void write_with_helper(const file_helper &helper, size_t howmany) { spdlog::memory_buf_t formatted; spdlog::fmt_lib::format_to(std::back_inserter(formatted), "{}", std::string(howmany, '1')); helper.write(formatted); diff --git a/tests/test_file_logging.cpp b/tests/test_file_logging.cpp index 50a6baec2..3ef4a3b4c 100644 --- a/tests/test_file_logging.cpp +++ b/tests/test_file_logging.cpp @@ -12,13 +12,10 @@ TEST_CASE("simple_file_logger", "[simple_logger]") { prepare_logdir(); spdlog::filename_t filename = SPDLOG_FILENAME_T(SIMPLE_LOG); - - auto logger = spdlog::create("logger", filename); + auto logger = spdlog::basic_logger_mt("logger", filename); logger->set_pattern("%v"); - logger->info("Test message {}", 1); logger->info("Test message {}", 2); - logger->flush(); require_message_count(SIMPLE_LOG, 2); using spdlog::details::os::default_eol; @@ -28,17 +25,14 @@ TEST_CASE("simple_file_logger", "[simple_logger]") { TEST_CASE("flush_on", "[flush_on]") { prepare_logdir(); spdlog::filename_t filename = SPDLOG_FILENAME_T(SIMPLE_LOG); - - auto logger = spdlog::create("logger", filename); + auto logger = spdlog::basic_logger_mt("test-error", filename); logger->set_pattern("%v"); logger->set_level(spdlog::level::trace); logger->flush_on(spdlog::level::info); logger->trace("Should not be flushed"); REQUIRE(count_lines(SIMPLE_LOG) == 0); - logger->info("Test message {}", 1); logger->info("Test message {}", 2); - require_message_count(SIMPLE_LOG, 3); using spdlog::details::os::default_eol; REQUIRE(file_contents(SIMPLE_LOG) == spdlog::fmt_lib::format("Should not be flushed{}Test message 1{}Test message 2{}", @@ -70,9 +64,6 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]") { for (int i = 0; i < 10; ++i) { logger->info("Test message {}", i); } - // drop causes the logger destructor to be called, which is required so the - // next logger can rename the first output file. - spdlog::drop(logger->name()); } auto logger = spdlog::rotating_logger_mt("logger", basename, max_size, 2, true); diff --git a/tests/test_macros.cpp b/tests/test_macros.cpp index b0991eff2..cffa998a9 100644 --- a/tests/test_macros.cpp +++ b/tests/test_macros.cpp @@ -15,8 +15,7 @@ TEST_CASE("debug and trace w/o format string", "[macros]") { prepare_logdir(); spdlog::filename_t filename = SPDLOG_FILENAME_T(TEST_FILENAME); - - auto logger = spdlog::create("logger", filename); + auto logger = spdlog::basic_logger_mt("logger", filename); logger->set_pattern("%v"); logger->set_level(spdlog::level::trace); @@ -28,8 +27,8 @@ TEST_CASE("debug and trace w/o format string", "[macros]") { REQUIRE(ends_with(file_contents(TEST_FILENAME), spdlog::fmt_lib::format("Test message 2{}", default_eol))); REQUIRE(count_lines(TEST_FILENAME) == 1); - auto orig_default_logger = spdlog::default_logger(); - spdlog::set_default_logger(logger); + auto orig_global_logger = spdlog::global_logger(); + spdlog::set_global_logger(logger); SPDLOG_TRACE("Test message 3"); SPDLOG_DEBUG("Test message {}", 4); @@ -37,7 +36,7 @@ TEST_CASE("debug and trace w/o format string", "[macros]") { require_message_count(TEST_FILENAME, 2); REQUIRE(ends_with(file_contents(TEST_FILENAME), spdlog::fmt_lib::format("Test message 4{}", default_eol))); - spdlog::set_default_logger(std::move(orig_default_logger)); + spdlog::set_global_logger(std::move(orig_global_logger)); } TEST_CASE("disable param evaluation", "[macros]") { @@ -45,7 +44,7 @@ TEST_CASE("disable param evaluation", "[macros]") { } TEST_CASE("pass logger pointer", "[macros]") { - auto logger = spdlog::create("refmacro"); + auto logger = spdlog::null_logger_mt("refmacro"); auto &ref = *logger; SPDLOG_LOGGER_TRACE(&ref, "Test message 1"); SPDLOG_LOGGER_DEBUG(&ref, "Test message 2"); diff --git a/tests/test_misc.cpp b/tests/test_misc.cpp index a2b335c25..f172536bc 100644 --- a/tests/test_misc.cpp +++ b/tests/test_misc.cpp @@ -73,18 +73,6 @@ TEST_CASE("to_level_enum", "[convert_to_level_enum]") { REQUIRE(spdlog::level_from_str("null") == spdlog::level::off); } -TEST_CASE("periodic flush", "[periodic_flush]") { - using spdlog::sinks::test_sink_mt; - auto logger = spdlog::create("periodic_flush"); - auto test_sink = std::static_pointer_cast(logger->sinks()[0]); - - spdlog::flush_every(std::chrono::seconds(1)); - std::this_thread::sleep_for(std::chrono::milliseconds(1250)); - REQUIRE(test_sink->flush_counter() == 1); - spdlog::flush_every(std::chrono::seconds(0)); - spdlog::drop_all(); -} - TEST_CASE("clone-logger", "[clone]") { using spdlog::sinks::test_sink_mt; auto test_sink = std::make_shared(); @@ -102,8 +90,6 @@ TEST_CASE("clone-logger", "[clone]") { REQUIRE(test_sink->lines().size() == 2); REQUIRE(test_sink->lines()[0] == "Some message 1"); REQUIRE(test_sink->lines()[1] == "Some message 2"); - - spdlog::drop_all(); } TEST_CASE("clone async", "[clone]") { @@ -127,18 +113,16 @@ TEST_CASE("clone async", "[clone]") { REQUIRE(test_sink->lines().size() == 2); REQUIRE(test_sink->lines()[0] == "Some message 1"); REQUIRE(test_sink->lines()[1] == "Some message 2"); - - spdlog::drop_all(); } -TEST_CASE("default logger API", "[default logger]") { +TEST_CASE("global logger API", "[global logger]") { std::ostringstream oss; auto oss_sink = std::make_shared(oss); - spdlog::set_default_logger(std::make_shared("oss", oss_sink)); + spdlog::set_global_logger(std::make_shared("oss", oss_sink)); spdlog::set_pattern("*** %v"); - spdlog::default_logger()->set_level(spdlog::level::trace); + spdlog::global_logger()->set_level(spdlog::level::trace); spdlog::trace("hello trace"); REQUIRE(oss.str() == "*** hello trace" + std::string(spdlog::details::os::default_eol)); @@ -162,7 +146,6 @@ TEST_CASE("default logger API", "[default logger]") { spdlog::set_level(spdlog::level::info); spdlog::debug("should not be logged"); REQUIRE(oss.str().empty()); - spdlog::drop_all(); spdlog::set_pattern("%v"); } diff --git a/tests/test_pattern_formatter.cpp b/tests/test_pattern_formatter.cpp index fd75cb978..85f2114b9 100644 --- a/tests/test_pattern_formatter.cpp +++ b/tests/test_pattern_formatter.cpp @@ -292,7 +292,7 @@ TEST_CASE("clone-formatter-2", "[pattern_formatter]") { REQUIRE(to_string_view(formatted_1) == to_string_view(formatted_2)); } -class custom_test_flag : public spdlog::custom_flag_formatter { +class custom_test_flag final : public spdlog::custom_flag_formatter { public: explicit custom_test_flag(std::string txt) : some_txt{std::move(txt)} {} diff --git a/tests/test_registry.cpp b/tests/test_registry.cpp deleted file mode 100644 index 467d944f6..000000000 --- a/tests/test_registry.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#include - -#include "includes.h" -#include "spdlog/sinks/daily_file_sink.h" -#include "spdlog/sinks/rotating_file_sink.h" - -static const char *const tested_logger_name = "null_logger"; -static const char *const tested_logger_name2 = "null_logger2"; - -TEST_CASE("register_drop", "[registry]") { - spdlog::drop_all(); - spdlog::create(tested_logger_name); - REQUIRE(spdlog::get(tested_logger_name) != nullptr); - // Throw if registering existing name - REQUIRE_THROWS_AS(spdlog::create(tested_logger_name), spdlog::spdlog_ex); -} - -TEST_CASE("explicit register", "[registry]") { - spdlog::drop_all(); - auto logger = std::make_shared(tested_logger_name, std::make_shared()); - spdlog::register_logger(logger); - REQUIRE(spdlog::get(tested_logger_name) != nullptr); - // Throw if registering existing name - REQUIRE_THROWS_AS(spdlog::create(tested_logger_name), spdlog::spdlog_ex); -} - -TEST_CASE("apply_all", "[registry]") { - spdlog::drop_all(); - auto logger = std::make_shared(tested_logger_name, std::make_shared()); - spdlog::register_logger(logger); - auto logger2 = std::make_shared(tested_logger_name2, std::make_shared()); - spdlog::register_logger(logger2); - - int counter = 0; - spdlog::apply_all([&counter](std::shared_ptr) { counter++; }); - REQUIRE(counter == 2); - - counter = 0; - spdlog::drop(tested_logger_name2); - spdlog::apply_all([&counter](std::shared_ptr l) { - REQUIRE(l->name() == tested_logger_name); - counter++; - }); - REQUIRE(counter == 1); -} - -TEST_CASE("drop", "[registry]") { - spdlog::drop_all(); - spdlog::create(tested_logger_name); - spdlog::drop(tested_logger_name); - REQUIRE_FALSE(spdlog::get(tested_logger_name)); -} - -TEST_CASE("drop-default", "[registry]") { - spdlog::set_default_logger(spdlog::null_logger_st(tested_logger_name)); - spdlog::drop(tested_logger_name); - REQUIRE_FALSE(spdlog::default_logger()); - REQUIRE_FALSE(spdlog::get(tested_logger_name)); -} - -TEST_CASE("drop_all", "[registry]") { - spdlog::drop_all(); - spdlog::create(tested_logger_name); - spdlog::create(tested_logger_name2); - spdlog::drop_all(); - REQUIRE_FALSE(spdlog::get(tested_logger_name)); - REQUIRE_FALSE(spdlog::get(tested_logger_name2)); - REQUIRE_FALSE(spdlog::default_logger()); -} - -TEST_CASE("drop non existing", "[registry]") { - spdlog::drop_all(); - spdlog::create(tested_logger_name); - spdlog::drop("some_name"); - REQUIRE_FALSE(spdlog::get("some_name")); - REQUIRE(spdlog::get(tested_logger_name)); - spdlog::drop_all(); -} - -TEST_CASE("default logger", "[registry]") { - spdlog::drop_all(); - spdlog::set_default_logger(spdlog::null_logger_st(tested_logger_name)); - REQUIRE(spdlog::get(tested_logger_name) == spdlog::default_logger()); - spdlog::drop_all(); -} - -TEST_CASE("set_default_logger(nullptr)", "[registry]") { - spdlog::set_default_logger(nullptr); - REQUIRE_FALSE(spdlog::default_logger()); -} - -TEST_CASE("disable automatic registration", "[registry]") { - // set some global parameters - spdlog::level level = spdlog::level::warn; - spdlog::set_level(level); - // but disable automatic registration - spdlog::set_automatic_registration(false); - auto logger1 = spdlog::create(tested_logger_name, SPDLOG_FILENAME_T("filename"), 11, 59); - auto logger2 = spdlog::create_async(tested_logger_name2); - // loggers should not be part of the registry - REQUIRE_FALSE(spdlog::get(tested_logger_name)); - REQUIRE_FALSE(spdlog::get(tested_logger_name2)); - // but make sure they are still initialized according to global defaults - REQUIRE(logger1->log_level() == level); - REQUIRE(logger2->log_level() == level); - spdlog::set_level(spdlog::level::info); - spdlog::set_automatic_registration(true); -} - -TEST_CASE("get(const char* name)", "[registry]") { - spdlog::drop_all(); - spdlog::create(tested_logger_name); - REQUIRE(spdlog::get(tested_logger_name) != nullptr); - spdlog::drop_all(); -} - -TEST_CASE("get(std::string_view name)", "[registry]") { - spdlog::drop_all(); - spdlog::create(tested_logger_name); - REQUIRE(spdlog::get(std::string_view(tested_logger_name)) != nullptr); - spdlog::drop_all(); -} - -TEST_CASE("get(std::string name)", "[registry]") { - spdlog::drop_all(); - spdlog::create(tested_logger_name); - REQUIRE(spdlog::get(std::string(tested_logger_name)) != nullptr); - spdlog::drop_all(); -} diff --git a/tests/test_stdout_api.cpp b/tests/test_stdout_api.cpp index 92feb42f9..4db6f2184 100644 --- a/tests/test_stdout_api.cpp +++ b/tests/test_stdout_api.cpp @@ -16,7 +16,6 @@ TEST_CASE("stdout_st", "[stdout]") { l->warn("Test stdout_st"); l->error("Test stdout_st"); l->critical("Test stdout_st"); - spdlog::drop_all(); } TEST_CASE("stderr_st", "[stderr]") { @@ -28,7 +27,6 @@ TEST_CASE("stderr_st", "[stderr]") { l->warn("Test stderr_st"); l->error("Test stderr_st"); l->critical("Test stderr_st"); - spdlog::drop_all(); } TEST_CASE("stdout_mt", "[stdout]") { @@ -54,7 +52,6 @@ TEST_CASE("stdout_color_st", "[stdout]") { l->warn("Test stdout_color_st"); l->error("Test stdout_color_st"); l->critical("Test stdout_color_st"); - spdlog::drop_all(); } TEST_CASE("stdout_color_mt", "[stdout]") { @@ -67,7 +64,6 @@ TEST_CASE("stdout_color_mt", "[stdout]") { l->warn("Test stdout_color_mt"); l->error("Test stdout_color_mt"); l->critical("Test stdout_color_mt"); - spdlog::drop_all(); } TEST_CASE("stderr_color_st", "[stderr]") { @@ -75,7 +71,6 @@ TEST_CASE("stderr_color_st", "[stderr]") { l->set_pattern("%+"); l->set_level(spdlog::level::debug); l->debug("Test stderr_color_st"); - spdlog::drop_all(); } TEST_CASE("stderr_color_mt", "[stderr]") { @@ -85,5 +80,4 @@ TEST_CASE("stderr_color_mt", "[stderr]") { l->warn("Test stderr_color_mt"); l->error("Test stderr_color_mt"); l->critical("Test stderr_color_mt"); - spdlog::drop_all(); } diff --git a/tests/test_time_point.cpp b/tests/test_time_point.cpp index c43991895..b5e15a4ca 100644 --- a/tests/test_time_point.cpp +++ b/tests/test_time_point.cpp @@ -31,5 +31,4 @@ TEST_CASE("time_point1", "[time_point log_msg]") { REQUIRE(lines[4] == lines[5]); REQUIRE(lines[6] == lines[7]); REQUIRE(lines[8] != lines[9]); - spdlog::drop_all(); } diff --git a/tests/utils.cpp b/tests/utils.cpp index cd5946445..5a4a4d190 100644 --- a/tests/utils.cpp +++ b/tests/utils.cpp @@ -8,7 +8,6 @@ #endif void prepare_logdir() { - spdlog::drop_all(); #ifdef _WIN32 system("rmdir /S /Q test_logs"); #else diff --git a/tests/utils.h b/tests/utils.h index f935fb83d..af66a937d 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -1,8 +1,8 @@ #pragma once #include -#include #include +#include std::size_t count_files(const std::string &folder); @@ -10,7 +10,7 @@ void prepare_logdir(); std::string file_contents(const std::string &filename); -//std::size_t count_lines(const std::string &filename); +// std::size_t count_lines(const std::string &filename); std::size_t count_lines(const std::filesystem::path &filename); void require_message_count(const std::filesystem::path &filename, const std::size_t messages);