Added a function to add callbacks that are called when a logger is registered (#2883)
* Added a function to add callbacks that are called when a logger is registered * Fix non captured registration 2 not being properly tested for * Replace std::list by std::vector * Remove const refs to shared pointers * Fix missing header
This commit is contained in:
		@@ -259,6 +259,22 @@ SPDLOG_INLINE void registry::register_logger_(std::shared_ptr<logger> new_logger
 | 
				
			|||||||
    auto logger_name = new_logger->name();
 | 
					    auto logger_name = new_logger->name();
 | 
				
			||||||
    throw_if_exists_(logger_name);
 | 
					    throw_if_exists_(logger_name);
 | 
				
			||||||
    loggers_[logger_name] = std::move(new_logger);
 | 
					    loggers_[logger_name] = std::move(new_logger);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto& logger = loggers_[logger_name];
 | 
				
			||||||
 | 
					    for (const auto& on_registration_callback : on_registration_callbacks_) {
 | 
				
			||||||
 | 
					        on_registration_callback(logger);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SPDLOG_INLINE void registry::add_on_registration_callback(
 | 
				
			||||||
 | 
					    const std::function<void(std::shared_ptr<logger>)>& callback) {
 | 
				
			||||||
 | 
					    std::lock_guard<std::mutex> lock(logger_map_mutex_);
 | 
				
			||||||
 | 
					    on_registration_callbacks_.push_back(callback);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SPDLOG_INLINE void registry::drop_all_on_registration_callbacks() {
 | 
				
			||||||
 | 
					    std::lock_guard<std::mutex> lock(logger_map_mutex_);
 | 
				
			||||||
 | 
					    on_registration_callbacks_.clear();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace details
 | 
					}  // namespace details
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@
 | 
				
			|||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <unordered_map>
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace spdlog {
 | 
					namespace spdlog {
 | 
				
			||||||
class logger;
 | 
					class logger;
 | 
				
			||||||
@@ -92,6 +93,10 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void apply_logger_env_levels(std::shared_ptr<logger> new_logger);
 | 
					    void apply_logger_env_levels(std::shared_ptr<logger> new_logger);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void add_on_registration_callback(const std::function<void(std::shared_ptr<logger>)>& callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void drop_all_on_registration_callbacks();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    registry();
 | 
					    registry();
 | 
				
			||||||
    ~registry();
 | 
					    ~registry();
 | 
				
			||||||
@@ -112,6 +117,7 @@ private:
 | 
				
			|||||||
    std::shared_ptr<logger> default_logger_;
 | 
					    std::shared_ptr<logger> default_logger_;
 | 
				
			||||||
    bool automatic_registration_ = true;
 | 
					    bool automatic_registration_ = true;
 | 
				
			||||||
    size_t backtrace_n_messages_ = 0;
 | 
					    size_t backtrace_n_messages_ = 0;
 | 
				
			||||||
 | 
					    std::vector<std::function<void(std::shared_ptr<logger>)>> on_registration_callbacks_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace details
 | 
					}  // namespace details
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,4 +89,12 @@ SPDLOG_INLINE void apply_logger_env_levels(std::shared_ptr<logger> logger) {
 | 
				
			|||||||
    details::registry::instance().apply_logger_env_levels(std::move(logger));
 | 
					    details::registry::instance().apply_logger_env_levels(std::move(logger));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SPDLOG_INLINE void add_on_registration_callback(const std::function<void(const std::shared_ptr<logger>&)>& callback) {
 | 
				
			||||||
 | 
					    details::registry::instance().add_on_registration_callback(callback);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SPDLOG_INLINE void drop_all_on_registration_callbacks() {
 | 
				
			||||||
 | 
					    details::registry::instance().drop_all_on_registration_callbacks();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace spdlog
 | 
					}  // namespace spdlog
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -140,6 +140,21 @@ SPDLOG_API void set_default_logger(std::shared_ptr<spdlog::logger> default_logge
 | 
				
			|||||||
//   spdlog::apply_logger_env_levels(mylogger);
 | 
					//   spdlog::apply_logger_env_levels(mylogger);
 | 
				
			||||||
SPDLOG_API void apply_logger_env_levels(std::shared_ptr<logger> logger);
 | 
					SPDLOG_API void apply_logger_env_levels(std::shared_ptr<logger> logger);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Add a callback that is called whenever a logger is registered
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Useful for intercepting loggers that are dynamically created during the application's lifetime
 | 
				
			||||||
 | 
					// (e.g. from dynamically loaded libraries, etc.)
 | 
				
			||||||
 | 
					// Example:
 | 
				
			||||||
 | 
					// void my_on_registration_callback(const std::shared_ptr<spdlog::logger>& logger) {
 | 
				
			||||||
 | 
					//     logger->do_stuff();
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					// spdlog::add_on_registration_callback(my_on_registration_callback);
 | 
				
			||||||
 | 
					SPDLOG_API void add_on_registration_callback(const std::function<void(const std::shared_ptr<logger>&)>& callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Clear all callbacks that were added to intercept registrations (see "add_on_registration_callback")
 | 
				
			||||||
 | 
					SPDLOG_API void drop_all_on_registration_callbacks();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename... Args>
 | 
					template <typename... Args>
 | 
				
			||||||
inline void log(source_loc source,
 | 
					inline void log(source_loc source,
 | 
				
			||||||
                level::level_enum lvl,
 | 
					                level::level_enum lvl,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,3 +110,30 @@ TEST_CASE("disable automatic registration", "[registry]") {
 | 
				
			|||||||
    spdlog::set_level(spdlog::level::info);
 | 
					    spdlog::set_level(spdlog::level::info);
 | 
				
			||||||
    spdlog::set_automatic_registration(true);
 | 
					    spdlog::set_automatic_registration(true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE("add_on_registration_callback", "[registry]") {
 | 
				
			||||||
 | 
					    std::vector<std::string> registered_logger_names;
 | 
				
			||||||
 | 
					    auto on_registration_callback = [&](std::shared_ptr<spdlog::logger> logger)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        registered_logger_names.push_back(logger->name());
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    spdlog::add_on_registration_callback(on_registration_callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto captured_registration_logger1 = spdlog::create<spdlog::sinks::stdout_color_sink_mt>("captured_registration_logger1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spdlog::set_automatic_registration(false);
 | 
				
			||||||
 | 
					    auto non_captured_registration_logger1 = spdlog::create<spdlog::sinks::stdout_color_sink_mt>("non_captured_registration_logger1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto captured_registration_logger2 = spdlog::create<spdlog::sinks::stdout_color_sink_mt>("captured_registration_logger2");
 | 
				
			||||||
 | 
					    spdlog::register_logger(captured_registration_logger2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spdlog::drop_all_on_registration_callbacks();
 | 
				
			||||||
 | 
					    auto non_captured_registration_logger2 = spdlog::create<spdlog::sinks::stdout_color_sink_mt>("non_captured_registration_logger2");
 | 
				
			||||||
 | 
					    spdlog::register_logger(non_captured_registration_logger2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Check that only the automatically registered logged and the manually registered logger were captured
 | 
				
			||||||
 | 
					    REQUIRE(registered_logger_names == std::vector<std::string>({"captured_registration_logger1", "captured_registration_logger2"}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spdlog::set_level(spdlog::level::info);
 | 
				
			||||||
 | 
					    spdlog::set_automatic_registration(true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user