diff --git a/example/example.cpp b/example/example.cpp index 4b416cd7..01227247 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -7,6 +7,7 @@ // // +#include "spdlog/spdlog.h" #include "spdlog/logger.h" spdlog::logger *get_logger(); @@ -14,5 +15,5 @@ spdlog::logger *get_logger(); int main(int, char *[]) { auto *l = get_logger(); - l->info(L"HEllo {}", L"HGFS"); + l->info("HEllo {}", "HG FS"); } \ No newline at end of file diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 252f44df..7a1ad1f2 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -11,28 +11,20 @@ // This class is thread safe #include "spdlog/common.h" -#include "spdlog/details/periodic_worker.h" -#include "spdlog/logger.h" -#include "spdlog/details/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 #include #include +#include namespace spdlog { +class logger; + namespace details { class thread_pool; +class periodic_worker; class registry { @@ -40,240 +32,67 @@ public: registry(const registry &) = delete; registry &operator=(const registry &) = delete; - void register_logger(std::shared_ptr new_logger) - { - std::lock_guard lock(logger_map_mutex_); - register_logger_(std::move(new_logger)); - } - - void 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_); - } - - new_logger->set_level(level_); - new_logger->flush_on(flush_level_); - - if (automatic_registration_) - { - register_logger_(std::move(new_logger)); - } - } - - std::shared_ptr 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 default_logger() - { - std::lock_guard lock(logger_map_mutex_); - return default_logger_; - } + 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 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() - { - return default_logger_.get(); - } + logger *get_default_raw(); + // 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) - { - 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 set_tp(std::shared_ptr tp) - { - std::lock_guard lock(tp_mutex_); - tp_ = std::move(tp); - } - - std::shared_ptr get_tp() - { - std::lock_guard lock(tp_mutex_); - return tp_; - } + 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) - { - std::lock_guard lock(logger_map_mutex_); - formatter_ = std::move(formatter); - for (auto &l : loggers_) - { - l.second->set_formatter(formatter_->clone()); - } - } + void set_formatter(std::unique_ptr formatter); - void set_level(level::level_enum log_level) - { - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) - { - l.second->set_level(log_level); - } - level_ = log_level; - } - - void flush_on(level::level_enum log_level) - { - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) - { - l.second->flush_on(log_level); - } - flush_level_ = log_level; - } - - void flush_every(std::chrono::seconds interval) - { - std::lock_guard lock(flusher_mutex_); - std::function clbk = std::bind(®istry::flush_all, this); - periodic_flusher_ = details::make_unique(clbk, interval); - } - - void set_error_handler(void (*handler)(const std::string &msg)) - { - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) - { - l.second->set_error_handler(handler); - } - err_handler_ = handler; - } - - void apply_all(const std::function)> &fun) - { - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) - { - fun(l.second); - } - } - - void flush_all() - { - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) - { - l.second->flush(); - } - } - - void drop(const std::string &logger_name) - { - std::lock_guard lock(logger_map_mutex_); - loggers_.erase(logger_name); - if (default_logger_ && default_logger_->name() == logger_name) - { - default_logger_.reset(); - } - } - - void drop_all() - { - std::lock_guard lock(logger_map_mutex_); - loggers_.clear(); - default_logger_.reset(); - } + void set_level(level::level_enum log_level); + + void flush_on(level::level_enum log_level); + + void flush_every(std::chrono::seconds interval); + + void set_error_handler(void (*handler)(const std::string &msg)); + + 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::lock_guard lock(flusher_mutex_); - periodic_flusher_.reset(); - } + void shutdown(); - drop_all(); - - { - std::lock_guard lock(tp_mutex_); - tp_.reset(); - } - } - - std::recursive_mutex &tp_mutex() - { - return tp_mutex_; - } - - void set_automatic_registration(bool automatic_regsistration) - { - std::lock_guard lock(logger_map_mutex_); - automatic_registration_ = automatic_regsistration; - } - - static registry &instance() - { - static registry s_instance; - return s_instance; - } + std::recursive_mutex &tp_mutex(); + + void set_automatic_registration(bool automatic_regsistration); + + static registry &instance(); private: - 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 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 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); - } - + 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_; std::unique_ptr formatter_; - level::level_enum level_ = spdlog::logger::default_level(); + level::level_enum level_ = level::info; level::level_enum flush_level_ = level::off; void (*err_handler_)(const std::string &msg); std::shared_ptr tp_; @@ -284,3 +103,7 @@ private: } // namespace details } // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY +#include "../src/registry.cpp" +#endif // SPDLOG_HEADER_ONLY diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index a70a7aa7..cc4c8a47 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -11,6 +11,7 @@ #include "spdlog/common.h" #include "spdlog/details/registry.h" +#include "spdlog/details/pattern_formatter.h" #include "spdlog/logger.h" #include "spdlog/version.h" diff --git a/src/registry.cpp b/src/registry.cpp new file mode 100644 index 00000000..51f184ed --- /dev/null +++ b/src/registry.cpp @@ -0,0 +1,259 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// +#ifndef SPDLOG_HEADER_ONLY +#include "spdlog/details/registry.h" +#endif + + +#include "spdlog/common.h" +#include "spdlog/details/periodic_worker.h" +#include "spdlog/logger.h" +#include "spdlog/details/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 +#include +#include + +namespace spdlog { +namespace details { + +registry::registry() + : formatter_(new pattern_formatter()) + , level_(spdlog::logger::default_level()) +{ + +#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 +} +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_); + } + + new_logger->set_level(level_); + new_logger->flush_on(flush_level_); + + 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::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(); +} + +// 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_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_enum log_level) +{ + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) + { + l.second->set_level(log_level); + } + level_ = log_level; +} + +void registry::flush_on(level::level_enum log_level) +{ + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) + { + l.second->flush_on(log_level); + } + flush_level_ = log_level; +} + +void registry::flush_every(std::chrono::seconds interval) +{ + std::lock_guard lock(flusher_mutex_); + std::function clbk = std::bind(®istry::flush_all, this); + periodic_flusher_ = details::make_unique(clbk, interval); +} + +void registry::set_error_handler(void (*handler)(const std::string &msg)) +{ + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) + { + l.second->set_error_handler(handler); + } + err_handler_ = 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_); + loggers_.erase(logger_name); + if (default_logger_ && default_logger_->name() == logger_name) + { + 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_regsistration) +{ + std::lock_guard lock(logger_map_mutex_); + automatic_registration_ = automatic_regsistration; +} + +registry ®istry::instance() +{ + static registry s_instance; + return s_instance; +} + +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