diff --git a/.gitignore b/.gitignore index 39b75483..5524d609 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ example/* !example/example.sln !example/example.vcxproj !example/CMakeLists.txt +!example/multisink.cpp # generated files generated diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 1944acaa..7859e4d5 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -40,6 +40,9 @@ target_link_libraries(example spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT}) add_executable(benchmark bench.cpp) target_link_libraries(benchmark spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT}) +add_executable(multisink multisink.cpp) +target_link_libraries(multisink spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT}) + enable_testing() file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs") add_test(NAME RunExample COMMAND example) diff --git a/example/multisink.cpp b/example/multisink.cpp new file mode 100644 index 00000000..fe6539b5 --- /dev/null +++ b/example/multisink.cpp @@ -0,0 +1,47 @@ +#include "spdlog/spdlog.h" + +#include +#include + +namespace spd = spdlog; +int main(int, char*[]) +{ + bool enable_debug = true; + try + { + // This other example use a single logger with multiple sinks. + // This means that the same log_msg is forwarded to multiple sinks; + // Each sink can have it's own log level and a message will be logged. + std::vector sinks; + sinks.push_back( std::make_shared() ); + sinks.push_back( std::make_shared("./log_regular_file.txt") ); + sinks.push_back( std::make_shared("./log_debug_file.txt") ); + + spdlog::logger console_multisink("multisink", sinks.begin(), sinks.end() ); + console_multisink.set_level( spdlog::level::warn); + + sinks[0]->set_level( spdlog::level::trace); // console. Allow everything. Default value + sinks[1]->set_level( spdlog::level::trace); // regular file. Allow everything. Default value + sinks[2]->set_level( spdlog::level::off); // regular file. Ignore everything. + + console_multisink.warn("warn: will print only on console and regular file"); + + if( enable_debug ) + { + console_multisink.set_level( spdlog::level::debug); // level of the logger + sinks[1]->set_level( spdlog::level::debug); // regular file + sinks[2]->set_level( spdlog::level::debug); // debug file + } + console_multisink.debug("Debug: you should see this on console and both files"); + + // Release and close all loggers + spdlog::drop_all(); + } + // Exceptions will only be thrown upon failed logger or sink construction (not during logging) + catch (const spd::spdlog_ex& ex) + { + std::cout << "Log init failed: " << ex.what() << std::endl; + return 1; + } +} + diff --git a/include/spdlog/details/async_log_helper.h b/include/spdlog/details/async_log_helper.h index 3a467258..9d02f563 100644 --- a/include/spdlog/details/async_log_helper.h +++ b/include/spdlog/details/async_log_helper.h @@ -303,8 +303,11 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_ log_msg incoming_log_msg; incoming_async_msg.fill_log_msg(incoming_log_msg); _formatter->format(incoming_log_msg); - for (auto &s : _sinks) - s->log(incoming_log_msg); + for (auto &s : _sinks){ + if(s->should_log( incoming_log_msg.level)){ + s->log(incoming_log_msg); + } + } } return true; } @@ -317,7 +320,6 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_ handle_flush_interval(now, last_flush); sleep_or_yield(now, last_pop); return !_terminate_requested; - } } diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index ada8d8de..212369f7 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -245,8 +245,11 @@ inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) cons inline void spdlog::logger::_sink_it(details::log_msg& msg) { _formatter->format(msg); - for (auto &sink : _sinks) - sink->log(msg); + for (auto &sink : _sinks){ + if( sink->should_log( msg.level)){ + sink->log(msg); + } + } if(_should_flush_on(msg)) flush(); diff --git a/include/spdlog/sinks/dist_sink.h b/include/spdlog/sinks/dist_sink.h index 3498a742..9967e403 100644 --- a/include/spdlog/sinks/dist_sink.h +++ b/include/spdlog/sinks/dist_sink.h @@ -35,11 +35,13 @@ protected: void _sink_it(const details::log_msg& msg) override { - for (auto &sink : _sinks) - sink->log(msg); + for (auto &sink : _sinks){ + if( sink->should_log( msg.level)){ + sink->log(msg); + } + } } - public: void flush() override { diff --git a/include/spdlog/sinks/sink.h b/include/spdlog/sinks/sink.h index 39dc771a..2c22ad99 100644 --- a/include/spdlog/sinks/sink.h +++ b/include/spdlog/sinks/sink.h @@ -15,10 +15,33 @@ namespace sinks class sink { public: + sink(): _level( level::trace ) {} + virtual ~sink() {} virtual void log(const details::log_msg& msg) = 0; virtual void flush() = 0; + + bool should_log(level::level_enum msg_level) const; + void set_level(level::level_enum log_level); + level::level_enum level() const; + +private: + level_t _level; + }; + +inline bool sink::should_log(level::level_enum msg_level) const { + return msg_level >= _level.load(std::memory_order_relaxed); +} + +inline void sink::set_level(level::level_enum log_level) { + _level.store(log_level); +} + +inline level::level_enum sink::level() const { + return static_cast(_level.load(std::memory_order_relaxed)); +} + } }