diff --git a/src/test/libslic3r/test_log.cpp b/src/test/libslic3r/test_log.cpp index 33d250331..bfe26eb36 100644 --- a/src/test/libslic3r/test_log.cpp +++ b/src/test/libslic3r/test_log.cpp @@ -588,3 +588,50 @@ SCENARIO( "_Log output set filtering with std::string methods" ) { } } } + +SCENARIO( "_Log output filtering on topic name" ) { + std::stringstream log; + std::unique_ptr<_Log> cut { _Log::make_log(log) }; + cut->set_inclusive(true); + cut->set_level(log_t::ALL); + WHEN("Topic is \"t1\"") { + cut->add_topic("t1"); + cut->debug("t1") << "TEXT FOR T1 "; + cut->debug("t2") << "TEXT FOR T2 "; + cut->debug("t3") << "TEXT FOR T3"; + THEN("Log text is \"TEXT FOR T1 \"") { + REQUIRE(log.str() == "t1 DEBUG: TEXT FOR T1 "); + } + } + + WHEN("Topic is \"t2\"") { + cut->add_topic("t2"); + cut->debug("t1") << "TEXT FOR T1 "; + cut->debug("t2") << "TEXT FOR T2 "; + cut->debug("t3") << "TEXT FOR T3"; + THEN("Log text is \"TEXT FOR T2 \"") { + REQUIRE(log.str() == "t2 DEBUG: TEXT FOR T2 "); + } + } + + WHEN("Topic is \"t3\"") { + cut->add_topic("t3"); + cut->debug("t1") << "TEXT FOR T1 "; + cut->debug("t2") << "TEXT FOR T2 "; + cut->debug("t3") << "TEXT FOR T3"; + THEN("Log text is \"TEXT FOR T3\"") { + REQUIRE(log.str() == "t3 DEBUG: TEXT FOR T3"); + } + } + + WHEN("Topic is \"t3\" and \"t2\"") { + cut->add_topic("t2"); + cut->add_topic("t3"); + cut->debug("t1") << "TEXT FOR T1 "; + cut->debug("t2") << "TEXT FOR T2 "; + cut->debug("t3") << "TEXT FOR T3"; + THEN("Log text is \"TEXT FOR T2 TEXT FOR T3\"") { + REQUIRE(log.str() == "t2 DEBUG: TEXT FOR T2 t3 DEBUG: TEXT FOR T3"); + } + } +} diff --git a/xs/src/libslic3r/Log.cpp b/xs/src/libslic3r/Log.cpp index f2548efd9..9e117d5f3 100644 --- a/xs/src/libslic3r/Log.cpp +++ b/xs/src/libslic3r/Log.cpp @@ -34,6 +34,10 @@ bool _Log::_has_log_level(log_t lvl) { return false; } +bool _Log::_has_topic(const std::string& topic) { + return this->_topics.find(topic) != this->_topics.end() || this->_topics.size() == 0; +} + void _Log::fatal_error(const std::string& topic, const std::wstring& message) { this->fatal_error(topic, this->converter.to_bytes(message)); } void _Log::error(const std::string& topic, const std::wstring& message) { this->error(topic, this->converter.to_bytes(message)); } void _Log::warn(const std::string& topic, const std::wstring& message) { this->warn(topic, this->converter.to_bytes(message)); } @@ -44,7 +48,7 @@ void _Log::fatal_error(const std::string& topic, const std::string& message) { this->fatal_error(topic) << message << std::endl; } std::ostream& _Log::fatal_error(const std::string& topic) { - if (this->_has_log_level(log_t::FERR)) { + if (this->_has_log_level(log_t::FERR) && this->_has_topic(topic)) { _out << topic << std::setfill(' ') << std::setw(6) << "FERR" << ": "; return _out; } @@ -55,7 +59,7 @@ void _Log::error(const std::string& topic, const std::string& message) { this->error(topic) << message << std::endl; } std::ostream& _Log::error(const std::string& topic) { - if (this->_has_log_level(log_t::ERR)) { + if (this->_has_log_level(log_t::ERR) && this->_has_topic(topic)) { _out << topic << std::setfill(' ') << std::setw(6) << "ERR" << ": "; return _out; } @@ -67,7 +71,7 @@ void _Log::info(const std::string& topic, const std::string& message) { } std::ostream& _Log::info(const std::string& topic) { - if (this->_has_log_level(log_t::INFO)) { + if (this->_has_log_level(log_t::INFO) && this->_has_topic(topic)) { _out << topic << std::setfill(' ') << std::setw(6) << "INFO" << ": "; return _out; } @@ -79,7 +83,7 @@ void _Log::warn(const std::string& topic, const std::string& message) { } std::ostream& _Log::warn(const std::string& topic) { - if (this->_has_log_level(log_t::WARN)) { + if (this->_has_log_level(log_t::WARN) && this->_has_topic(topic)) { _out << topic << std::setfill(' ') << std::setw(6) << "WARN" << ": "; return _out; } @@ -91,7 +95,7 @@ void _Log::debug(const std::string& topic, const std::string& message) { } std::ostream& _Log::debug(const std::string& topic) { - if (this->_has_log_level(log_t::DEBUG)) { + if (this->_has_log_level(log_t::DEBUG) && this->_has_topic(topic)) { _out << topic << std::setfill(' ') << std::setw(6) << "DEBUG" << ": "; return _out; } @@ -131,4 +135,12 @@ void _Log::clear_level(log_t level) { } } +void _Log::clear_topic(const std::string& topic) { + if (topic == "") { + this->_topics.clear(); + } else { + if (this->_topics.find(topic) != this->_topics.end()) this->_topics.erase(topic); + } +} + } // Slic3r diff --git a/xs/src/libslic3r/Log.hpp b/xs/src/libslic3r/Log.hpp index 0f0040c5a..48e309297 100644 --- a/xs/src/libslic3r/Log.hpp +++ b/xs/src/libslic3r/Log.hpp @@ -63,6 +63,8 @@ public: void set_level(log_t level); void clear_level(log_t level); void set_inclusive(bool v) { this->_inclusive_levels = v; } + void add_topic(const std::string& topic) { this->_topics.insert(topic); } + void clear_topic(const std::string& topic); // _Log(_Log const&) = delete; // void operator=(_Log const&) = delete; @@ -72,10 +74,12 @@ private: _Log(std::ostream& out); bool _inclusive_levels { true }; std::set _log_level { }; + std::set _topics { }; std::wstring_convert> converter; bool _has_log_level(log_t lvl); + bool _has_topic(const std::string& topic); }; @@ -183,6 +187,20 @@ public: static std::ostream& raw() { return slic3r_log->raw(); } + + /// Adds a topic to filter on with Slic3r's debug system. + /// \param topic [in] name of topic to filter on. + /// Only shows registered topics. + static void add_topic(const std::string& topic) { + slic3r_log->add_topic(topic); + } + + /// Removes a topic from the filter list with Slic3r's debug system. + /// \param topic [in] name of topic to remove from filter. + /// \note Default option removes all filters. + static void clear_topic(const std::string& topic = "") { + slic3r_log->clear_topic(topic); + } }; /// Utility debug function to transform a std::vector of anything that