registry-inl.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
  2. // Distributed under the MIT License (http://opensource.org/licenses/MIT)
  3. #pragma once
  4. #ifndef SPDLOG_HEADER_ONLY
  5. #include <spdlog/details/registry.h>
  6. #endif
  7. #include <spdlog/common.h>
  8. #include <spdlog/details/periodic_worker.h>
  9. #include <spdlog/logger.h>
  10. #include <spdlog/pattern_formatter.h>
  11. #ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
  12. // support for the default stdout color logger
  13. #ifdef _WIN32
  14. #include <spdlog/sinks/wincolor_sink.h>
  15. #else
  16. #include <spdlog/sinks/ansicolor_sink.h>
  17. #endif
  18. #endif // SPDLOG_DISABLE_DEFAULT_LOGGER
  19. #include <chrono>
  20. #include <functional>
  21. #include <memory>
  22. #include <string>
  23. #include <unordered_map>
  24. namespace spdlog {
  25. namespace details {
  26. SPDLOG_INLINE registry::registry()
  27. : formatter_(new pattern_formatter()) {
  28. #ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
  29. // create default logger (ansicolor_stdout_sink_mt or wincolor_stdout_sink_mt in windows).
  30. #ifdef _WIN32
  31. auto color_sink = std::make_shared<sinks::wincolor_stdout_sink_mt>();
  32. #else
  33. auto color_sink = std::make_shared<sinks::ansicolor_stdout_sink_mt>();
  34. #endif
  35. const char *default_logger_name = "";
  36. default_logger_ = std::make_shared<spdlog::logger>(default_logger_name, std::move(color_sink));
  37. loggers_[default_logger_name] = default_logger_;
  38. #endif // SPDLOG_DISABLE_DEFAULT_LOGGER
  39. }
  40. SPDLOG_INLINE registry::~registry() = default;
  41. SPDLOG_INLINE void registry::register_logger(std::shared_ptr<logger> new_logger) {
  42. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  43. register_logger_(std::move(new_logger));
  44. }
  45. SPDLOG_INLINE void registry::initialize_logger(std::shared_ptr<logger> new_logger) {
  46. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  47. new_logger->set_formatter(formatter_->clone());
  48. if (err_handler_) {
  49. new_logger->set_error_handler(err_handler_);
  50. }
  51. // set new level according to previously configured level or default level
  52. auto it = log_levels_.find(new_logger->name());
  53. auto new_level = it != log_levels_.end() ? it->second : global_log_level_;
  54. new_logger->set_level(new_level);
  55. new_logger->flush_on(flush_level_);
  56. if (backtrace_n_messages_ > 0) {
  57. new_logger->enable_backtrace(backtrace_n_messages_);
  58. }
  59. if (automatic_registration_) {
  60. register_logger_(std::move(new_logger));
  61. }
  62. }
  63. SPDLOG_INLINE std::shared_ptr<logger> registry::get(const std::string &logger_name) {
  64. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  65. auto found = loggers_.find(logger_name);
  66. return found == loggers_.end() ? nullptr : found->second;
  67. }
  68. SPDLOG_INLINE std::shared_ptr<logger> registry::default_logger() {
  69. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  70. return default_logger_;
  71. }
  72. // Return raw ptr to the default logger.
  73. // To be used directly by the spdlog default api (e.g. spdlog::info)
  74. // This make the default API faster, but cannot be used concurrently with set_default_logger().
  75. // e.g do not call set_default_logger() from one thread while calling spdlog::info() from another.
  76. SPDLOG_INLINE logger *registry::get_default_raw() { return default_logger_.get(); }
  77. // set default logger.
  78. // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map.
  79. SPDLOG_INLINE void registry::set_default_logger(std::shared_ptr<logger> new_default_logger) {
  80. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  81. if (new_default_logger != nullptr) {
  82. loggers_[new_default_logger->name()] = new_default_logger;
  83. }
  84. default_logger_ = std::move(new_default_logger);
  85. }
  86. SPDLOG_INLINE void registry::set_tp(std::shared_ptr<thread_pool> tp) {
  87. std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
  88. tp_ = std::move(tp);
  89. }
  90. SPDLOG_INLINE std::shared_ptr<thread_pool> registry::get_tp() {
  91. std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
  92. return tp_;
  93. }
  94. // Set global formatter. Each sink in each logger will get a clone of this object
  95. SPDLOG_INLINE void registry::set_formatter(std::unique_ptr<formatter> formatter) {
  96. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  97. formatter_ = std::move(formatter);
  98. for (auto &l : loggers_) {
  99. l.second->set_formatter(formatter_->clone());
  100. }
  101. }
  102. SPDLOG_INLINE void registry::enable_backtrace(size_t n_messages) {
  103. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  104. backtrace_n_messages_ = n_messages;
  105. for (auto &l : loggers_) {
  106. l.second->enable_backtrace(n_messages);
  107. }
  108. }
  109. SPDLOG_INLINE void registry::disable_backtrace() {
  110. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  111. backtrace_n_messages_ = 0;
  112. for (auto &l : loggers_) {
  113. l.second->disable_backtrace();
  114. }
  115. }
  116. SPDLOG_INLINE void registry::set_level(level::level_enum log_level) {
  117. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  118. for (auto &l : loggers_) {
  119. l.second->set_level(log_level);
  120. }
  121. global_log_level_ = log_level;
  122. }
  123. SPDLOG_INLINE void registry::flush_on(level::level_enum log_level) {
  124. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  125. for (auto &l : loggers_) {
  126. l.second->flush_on(log_level);
  127. }
  128. flush_level_ = log_level;
  129. }
  130. SPDLOG_INLINE void registry::set_error_handler(err_handler handler) {
  131. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  132. for (auto &l : loggers_) {
  133. l.second->set_error_handler(handler);
  134. }
  135. err_handler_ = std::move(handler);
  136. }
  137. SPDLOG_INLINE void registry::apply_all(
  138. const std::function<void(const std::shared_ptr<logger>)> &fun) {
  139. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  140. for (auto &l : loggers_) {
  141. fun(l.second);
  142. }
  143. }
  144. SPDLOG_INLINE void registry::flush_all() {
  145. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  146. for (auto &l : loggers_) {
  147. l.second->flush();
  148. }
  149. }
  150. SPDLOG_INLINE void registry::drop(const std::string &logger_name) {
  151. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  152. auto is_default_logger = default_logger_ && default_logger_->name() == logger_name;
  153. loggers_.erase(logger_name);
  154. if (is_default_logger) {
  155. default_logger_.reset();
  156. }
  157. }
  158. SPDLOG_INLINE void registry::drop_all() {
  159. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  160. loggers_.clear();
  161. default_logger_.reset();
  162. }
  163. // clean all resources and threads started by the registry
  164. SPDLOG_INLINE void registry::shutdown() {
  165. {
  166. std::lock_guard<std::mutex> lock(flusher_mutex_);
  167. periodic_flusher_.reset();
  168. }
  169. drop_all();
  170. {
  171. std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
  172. tp_.reset();
  173. }
  174. }
  175. SPDLOG_INLINE std::recursive_mutex &registry::tp_mutex() { return tp_mutex_; }
  176. SPDLOG_INLINE void registry::set_automatic_registration(bool automatic_registration) {
  177. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  178. automatic_registration_ = automatic_registration;
  179. }
  180. SPDLOG_INLINE void registry::set_levels(log_levels levels, level::level_enum *global_level) {
  181. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  182. log_levels_ = std::move(levels);
  183. auto global_level_requested = global_level != nullptr;
  184. global_log_level_ = global_level_requested ? *global_level : global_log_level_;
  185. for (auto &logger : loggers_) {
  186. auto logger_entry = log_levels_.find(logger.first);
  187. if (logger_entry != log_levels_.end()) {
  188. logger.second->set_level(logger_entry->second);
  189. } else if (global_level_requested) {
  190. logger.second->set_level(*global_level);
  191. }
  192. }
  193. }
  194. SPDLOG_INLINE registry &registry::instance() {
  195. static registry s_instance;
  196. return s_instance;
  197. }
  198. SPDLOG_INLINE void registry::apply_logger_env_levels(std::shared_ptr<logger> new_logger) {
  199. std::lock_guard<std::mutex> lock(logger_map_mutex_);
  200. auto it = log_levels_.find(new_logger->name());
  201. auto new_level = it != log_levels_.end() ? it->second : global_log_level_;
  202. new_logger->set_level(new_level);
  203. }
  204. SPDLOG_INLINE void registry::throw_if_exists_(const std::string &logger_name) {
  205. if (loggers_.find(logger_name) != loggers_.end()) {
  206. throw_spdlog_ex("logger with name '" + logger_name + "' already exists");
  207. }
  208. }
  209. SPDLOG_INLINE void registry::register_logger_(std::shared_ptr<logger> new_logger) {
  210. auto logger_name = new_logger->name();
  211. throw_if_exists_(logger_name);
  212. loggers_[logger_name] = std::move(new_logger);
  213. }
  214. } // namespace details
  215. } // namespace spdlog