diff --git a/include/spdlog/details/registry-inl.h b/include/spdlog/details/registry-inl.h index d6d1aa07..a2205ebd 100644 --- a/include/spdlog/details/registry-inl.h +++ b/include/spdlog/details/registry-inl.h @@ -151,6 +151,16 @@ SPDLOG_INLINE void registry::enable_backtrace(size_t n_messages) } } +SPDLOG_INLINE void registry::disable_backtrace() +{ + std::lock_guard lock(logger_map_mutex_); + + for (auto &l : loggers_) + { + l.second->disable_backtrace(); + } +} + SPDLOG_INLINE void registry::set_level(level::level_enum log_level) { std::lock_guard lock(logger_map_mutex_); diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 73be7b28..35a117d9 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -54,6 +54,8 @@ public: void enable_backtrace(size_t n_messages); + void disable_backtrace(); + void set_level(level::level_enum log_level); void flush_on(level::level_enum log_level); diff --git a/include/spdlog/logger-inl.h b/include/spdlog/logger-inl.h index d0f5a0c7..34c9bc8a 100644 --- a/include/spdlog/logger-inl.h +++ b/include/spdlog/logger-inl.h @@ -22,13 +22,17 @@ SPDLOG_INLINE logger::logger(const logger &other) , level_(other.level_.load(std::memory_order_relaxed)) , flush_level_(other.flush_level_.load(std::memory_order_relaxed)) , custom_err_handler_(other.custom_err_handler_) + , backtrace_sink_(other.backtrace_sink_) {} -SPDLOG_INLINE logger::logger(logger &&other) SPDLOG_NOEXCEPT : name_(std::move(other.name_)), - sinks_(std::move(other.sinks_)), - level_(other.level_.load(std::memory_order_relaxed)), - flush_level_(other.flush_level_.load(std::memory_order_relaxed)), - custom_err_handler_(std::move(other.custom_err_handler_)) +SPDLOG_INLINE logger::logger(logger &&other) SPDLOG_NOEXCEPT : + name_(std::move(other.name_)), + sinks_(std::move(other.sinks_)), + level_(other.level_.load(std::memory_order_relaxed)), + flush_level_(other.flush_level_.load(std::memory_order_relaxed)), + custom_err_handler_(std::move(other.custom_err_handler_)), + backtrace_sink_(std::move(other.backtrace_sink_)) + {} SPDLOG_INLINE logger &logger::operator=(logger other) SPDLOG_NOEXCEPT @@ -53,6 +57,7 @@ SPDLOG_INLINE void logger::swap(spdlog::logger &other) SPDLOG_NOEXCEPT other.flush_level_.store(tmp); custom_err_handler_.swap(other.custom_err_handler_); + backtrace_sink_.swap(other.backtrace_sink_); } SPDLOG_INLINE void swap(logger &a, logger &b) @@ -83,7 +88,16 @@ SPDLOG_INLINE bool logger::should_log(level::level_enum msg_level) const SPDLOG_INLINE void logger::set_level(level::level_enum log_level) { - level_.store(log_level); + if(backtrace_sink_) + { + auto tracer = static_cast(backtrace_sink_.get()); + tracer->set_filter_level(log_level); + level_.store(level::trace); + } + else + { + level_.store(log_level); + } } SPDLOG_INLINE level::level_enum logger::level() const @@ -120,26 +134,37 @@ SPDLOG_INLINE void logger::set_pattern(std::string pattern, pattern_time_type ti set_formatter(std::move(new_formatter)); } -// create new backtrace sink and hand it all sinks +// create new backtrace sink and move to it all our child sinks SPDLOG_INLINE void logger::enable_backtrace(size_t n_messages) { - if (!backtrace_enabled_) + if (!backtrace_sink_) { - backtrace_enabled_ = true; - auto backtrace_sink = std::make_shared(n_messages); - backtrace_sink->set_sinks(std::move(sinks())); - sinks().push_back(std::move(backtrace_sink)); - this->set_level(spdlog::level::trace); + auto new_backtrace_sink = new spdlog::sinks::backtrace_sink_mt(level(), n_messages); + new_backtrace_sink->set_sinks(std::move(sinks_)); + backtrace_sink_.reset(new_backtrace_sink); + sinks().push_back(backtrace_sink_); + assert(sinks().size() == 1); + level_.store(level::trace); + } +} + +// restore orig sinks and level and delete the backtrace sink +SPDLOG_INLINE void logger::disable_backtrace() +{ + if (backtrace_sink_) + { + auto tracer = static_cast(backtrace_sink_.get()); + sinks_ = std::move(tracer->sinks()); + level_.store(tracer->get_filter_level()); + backtrace_sink_.reset(); } } SPDLOG_INLINE void logger::dump_backtrace() { - if (backtrace_enabled_) + if (backtrace_sink_) { - // auto backtrace_sink = static_cast>(sinks_[0]); - auto *first_sink = sinks_[0].get(); - auto tracer = static_cast(first_sink); + auto tracer = static_cast(backtrace_sink_.get()); tracer->dump_backtrace(); } } diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 62f8b729..96aed560 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -324,6 +324,7 @@ public: void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local); void enable_backtrace(size_t n_messages = 16); + void disable_backtrace(); void dump_backtrace(); @@ -349,7 +350,8 @@ protected: spdlog::level_t level_{level::info}; spdlog::level_t flush_level_{level::off}; err_handler custom_err_handler_{nullptr}; - bool backtrace_enabled_{false}; + sink_ptr backtrace_sink_; + //bool backtrace_enabled_{false}; virtual void sink_it_(const details::log_msg &msg); virtual void flush_(); diff --git a/include/spdlog/sinks/backtrace-sink.h b/include/spdlog/sinks/backtrace-sink.h index cb42bde9..d86652a9 100644 --- a/include/spdlog/sinks/backtrace-sink.h +++ b/include/spdlog/sinks/backtrace-sink.h @@ -4,6 +4,7 @@ #pragma once #include "dist_sink.h" +#include "spdlog/common.h" #include "spdlog/details/null_mutex.h" #include "spdlog/details/log_msg_buffer.h" #include "spdlog/details/circular_q.h" @@ -22,10 +23,23 @@ template class backtrace_sink : public dist_sink { public: - explicit backtrace_sink(size_t n_messages = 16) - : traceback_msgs_{n_messages} + explicit backtrace_sink(spdlog::level::level_enum filter_level, size_t n_messages) + : filter_level_{filter_level} + , traceback_msgs_{n_messages} {} + void set_filter_level(spdlog::level::level_enum filter_level) + { + std::lock_guard lock(base_sink::mutex_); + filter_level_ = filter_level; + } + + spdlog::level::level_enum get_filter_level() + { + std::lock_guard lock(base_sink::mutex_); + return filter_level_; + } + void dump_backtrace() { std::lock_guard lock(base_sink::mutex_); @@ -33,6 +47,7 @@ public: } protected: + spdlog::level::level_enum filter_level_; details::circular_q traceback_msgs_; // save the messages in a circular queue @@ -40,7 +55,7 @@ protected: { traceback_msgs_.push_back(details::log_msg_buffer(msg)); - if (msg.level > level::debug) + if (msg.level >= filter_level_) { dist_sink::sink_it_(msg); } diff --git a/include/spdlog/sinks/dist_sink.h b/include/spdlog/sinks/dist_sink.h index c7f207d7..00b908e1 100644 --- a/include/spdlog/sinks/dist_sink.h +++ b/include/spdlog/sinks/dist_sink.h @@ -45,6 +45,12 @@ public: sinks_ = std::move(sinks); } + std::vector>& sinks() + { + return sinks_; + } + + protected: void sink_it_(const details::log_msg &msg) override { diff --git a/include/spdlog/spdlog-inl.h b/include/spdlog/spdlog-inl.h index 2e4ee652..bbfb6e24 100644 --- a/include/spdlog/spdlog-inl.h +++ b/include/spdlog/spdlog-inl.h @@ -37,6 +37,16 @@ SPDLOG_INLINE void enable_backtrace(size_t n_messages) details::registry::instance().enable_backtrace(n_messages); } +SPDLOG_INLINE void disable_backtrace() +{ + details::registry::instance().disable_backtrace(); +} + +SPDLOG_INLINE void dump_backtrace() +{ + default_logger_raw()->dump_backtrace(); +} + SPDLOG_INLINE void set_level(level::level_enum log_level) { details::registry::instance().set_level(log_level); diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 4254f49d..4563c900 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -63,6 +63,12 @@ void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time // enable global backtrace support void enable_backtrace(size_t n_messages); +// disable global backtrace support +void disable_backtrace(); + +// call dump backtrace on default logger +void dump_backtrace(); + // Set global logging level void set_level(level::level_enum log_level);