diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 1eb9aa2f..f2683f32 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "../common.h" @@ -35,6 +36,8 @@ public: 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. diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index f724b01f..76e28865 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "./common.h" #include "./details/registry.h" @@ -50,6 +51,8 @@ SPDLOG_API void initialize_logger(std::shared_ptr logger); // 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 global formatter. Each sink in each logger will get a clone of this object SPDLOG_API void set_formatter(std::unique_ptr formatter); diff --git a/src/details/registry.cpp b/src/details/registry.cpp index b3cfab14..99a46114 100644 --- a/src/details/registry.cpp +++ b/src/details/registry.cpp @@ -8,12 +8,14 @@ #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 +// 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 @@ -22,216 +24,230 @@ #include namespace spdlog { -namespace details { + namespace details { -registry::registry() - : formatter_(new pattern_formatter()) { + 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 + // 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_; + 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; + 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::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()); + 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_); - } + 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); + // 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_); + new_logger->flush_on(flush_level_); - if (automatic_registration_) { - register_logger_(std::move(new_logger)); - } -} + if (automatic_registration_) { + register_logger_(std::move(new_logger)); + } + } -std::shared_ptr registry::get(const std::string &logger_name) { - std::lock_guard lock(logger_map_mutex_); - auto found = loggers_.find(logger_name); - return found == loggers_.end() ? nullptr : found->second; -} + std::shared_ptr registry::get(const std::string &logger_name) { + std::lock_guard lock(logger_map_mutex_); + auto found = loggers_.find(logger_name); + return found == loggers_.end() ? nullptr : found->second; + } -std::shared_ptr registry::default_logger() { - std::lock_guard lock(logger_map_mutex_); - return default_logger_; -} + std::shared_ptr registry::get(std::string_view logger_name) { + std::lock_guard lock(logger_map_mutex_); + for (const auto &[key, val]: loggers_) { + if (key == logger_name) { + return val; + } + } + return nullptr; + } + + 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() { return default_logger_.get(); } + logger *registry::get_default_raw() { 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_); - // remove previous default logger from the map - if (default_logger_ != nullptr) { - loggers_.erase(default_logger_->name()); - } - if (new_default_logger != nullptr) { - loggers_[new_default_logger->name()] = new_default_logger; - } - default_logger_ = std::move(new_default_logger); -} + void registry::set_default_logger(std::shared_ptr new_default_logger) { + std::lock_guard lock(logger_map_mutex_); + // remove previous default logger from the map + if (default_logger_ != nullptr) { + loggers_.erase(default_logger_->name()); + } + 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); -} + 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_; -} + 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_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::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::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::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::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::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(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(); -} + 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(); - } + void registry::shutdown() { + { + std::lock_guard lock(flusher_mutex_); + periodic_flusher_.reset(); + } - drop_all(); + 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); + { + std::lock_guard lock(tp_mutex_); + tp_.reset(); + } } - } -} -registry ®istry::instance() { - static registry s_instance; - return s_instance; -} + std::recursive_mutex ®istry::tp_mutex() { return tp_mutex_; } -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::set_automatic_registration(bool automatic_registration) { + std::lock_guard lock(logger_map_mutex_); + automatic_registration_ = automatic_registration; + } -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::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_; -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); -} + 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); + } + } + } -} // namespace details + 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/spdlog.cpp b/src/spdlog.cpp index 825e85e5..daa7f4ba 100644 --- a/src/spdlog.cpp +++ b/src/spdlog.cpp @@ -16,6 +16,10 @@ void initialize_logger(std::shared_ptr logger) { details::registry::inst std::shared_ptr get(const std::string &name) { return details::registry::instance().get(name); } +std::shared_ptr get(std::string_view name) {return details::registry::instance().get(name); } + +std::shared_ptr get(const char *name) { return details::registry::instance().get(name); } + void set_formatter(std::unique_ptr formatter) { details::registry::instance().set_formatter(std::move(formatter)); } diff --git a/tests/test_registry.cpp b/tests/test_registry.cpp index 9ae17be7..c1e15ce4 100644 --- a/tests/test_registry.cpp +++ b/tests/test_registry.cpp @@ -1,4 +1,5 @@ #include "includes.h" +#include #include "spdlog/sinks/daily_file_sink.h" #include "spdlog/sinks/rotating_file_sink.h" @@ -106,3 +107,24 @@ TEST_CASE("disable automatic registration", "[registry]") { 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(); +}