diff --git a/opm/common/OpmLog/LogBackend.cpp b/opm/common/OpmLog/LogBackend.cpp index f24f04d5a..e94b82fa2 100644 --- a/opm/common/OpmLog/LogBackend.cpp +++ b/opm/common/OpmLog/LogBackend.cpp @@ -62,13 +62,19 @@ namespace Opm { // Use the message limiter (if any). MessageLimiter::Response res = m_limiter - ? m_limiter->handleMessageTag(messageTag) + ? m_limiter->handleMessageLimits(messageTag, messageFlag) : MessageLimiter::Response::PrintMessage; - if (res == MessageLimiter::Response::JustOverLimit) { + if (res == MessageLimiter::Response::JustOverTagLimit) { // Special case: add a message to this backend about limit being reached. std::string msg = "Message limit reached for message tag: " + messageTag; addTaggedMessage(messageFlag, "", msg); } + if (res == MessageLimiter::Response::JustOverCategoryLimit) { + // Special case: add a message to this backend about limit being reached. + std::string msg = "Message limit reached for message : " + Log::prefixMessage(messageFlag, ""); + addTaggedMessage(messageFlag, "", msg); + } + return res == MessageLimiter::Response::PrintMessage; } diff --git a/opm/common/OpmLog/MessageLimiter.hpp b/opm/common/OpmLog/MessageLimiter.hpp index a991efc37..ecdcd0962 100644 --- a/opm/common/OpmLog/MessageLimiter.hpp +++ b/opm/common/OpmLog/MessageLimiter.hpp @@ -22,7 +22,9 @@ #include #include - +#include +#include +#include namespace Opm { @@ -36,7 +38,13 @@ namespace Opm /// Default constructor, no limit to the number of messages. MessageLimiter() - : message_limit_(NoLimit) + : tag_limit_(NoLimit), + category_limits_({{Log::MessageType::Note, NoLimit}, + {Log::MessageType::Info, NoLimit}, + {Log::MessageType::Warning, NoLimit}, + {Log::MessageType::Error, NoLimit}, + {Log::MessageType::Problem, NoLimit}, + {Log::MessageType::Bug, NoLimit}}) { } @@ -46,62 +54,108 @@ namespace Opm /// Negative limits (including NoLimit) are interpreted as /// NoLimit, but the default constructor is the preferred way /// to obtain that behaviour. - explicit MessageLimiter(const int message_limit) - : message_limit_(message_limit < 0 ? NoLimit : message_limit) + explicit MessageLimiter(const int tag_limit) + : tag_limit_(tag_limit < 0 ? NoLimit : tag_limit), + category_limits_({{Log::MessageType::Note, NoLimit}, + {Log::MessageType::Info, NoLimit}, + {Log::MessageType::Warning, NoLimit}, + {Log::MessageType::Error, NoLimit}, + {Log::MessageType::Problem, NoLimit}, + {Log::MessageType::Bug, NoLimit}}) + { + } + + MessageLimiter(const int tag_limit, const std::map category_limits) + : tag_limit_(tag_limit < 0 ? NoLimit : tag_limit), + category_limits_(category_limits) { } /// The message limit (same for all tags). int messageLimit() const { - return message_limit_; + return tag_limit_; } - /// Used for handleMessageTag() return type (see that + /// Used for handleMessageLimits() return type (see that /// function). enum class Response { - PrintMessage, JustOverLimit, OverLimit + PrintMessage, JustOverTagLimit, JustOverCategoryLimit, OverTagLimit, OverCategoryLimit }; /// If a tag is empty, there is no message limit or for that - /// tag (count <= limit), respond PrintMessage. + /// (count <= limit), respond PrintMessage. /// If (count == limit + 1), respond JustOverLimit. /// If (count > limit + 1), respond OverLimit. - Response handleMessageTag(const std::string& tag) + Response handleMessageLimits(const std::string& tag, const int64_t messageMask) { - if (tag.empty() || message_limit_ == NoLimit) { - return Response::PrintMessage; + Response res = Response::PrintMessage; + // Deal with tag limits. + if (tag.empty() || tag_limit_ == NoLimit) { + category_counts_[messageMask]++; + res = Response::PrintMessage; } else { // See if tag already encountered. auto it = tag_counts_.find(tag); if (it != tag_counts_.end()) { // Already encountered this tag. Increment its count. const int count = ++it->second; - return countBasedResponse(count); + res = countBasedResponse(count, messageMask); } else { // First encounter of this tag. Insert 1. tag_counts_.insert({tag, 1}); - return countBasedResponse(1); + res = countBasedResponse(1, messageMask); } } + // If tag count reached the limit, ignore all the same tagged messages. + if (res == Response::JustOverTagLimit || res == Response::OverTagLimit) { + return res; + } else { + if (category_limits_[messageMask] == NoLimit) { + category_counts_[messageMask]++; + res = Response::PrintMessage; + } else { + res = countBasedResponse(messageMask); + } + } + return res; } private: - Response countBasedResponse(const int count) + Response countBasedResponse(const int count, const int64_t messageMask) { - if (count <= message_limit_) { + if (count <= tag_limit_) { + category_counts_[messageMask]++; return Response::PrintMessage; - } else if (count == message_limit_ + 1) { - return Response::JustOverLimit; + } else if (count == tag_limit_ + 1) { + category_counts_[messageMask]++; + return Response::JustOverTagLimit; } else { - return Response::OverLimit; + return Response::OverTagLimit; } } - int message_limit_; + Response countBasedResponse(const int64_t messageMask) + { + if (category_counts_[messageMask] < category_limits_[messageMask]) { + category_counts_[messageMask]++; + return Response::PrintMessage; + } else if (category_counts_[messageMask] == category_limits_[messageMask] + 1) { + category_counts_[messageMask]++; + return Response::JustOverCategoryLimit; + } else { + return Response::OverCategoryLimit; + } + } + + int tag_limit_; std::unordered_map tag_counts_; + std::map category_counts_; + // info, note, warning, problem, error, bug. + std::map category_limits_; + bool reachTagLimit_; }; diff --git a/tests/test_messagelimiter.cpp b/tests/test_messagelimiter.cpp index b076f951f..89c3a19a1 100644 --- a/tests/test_messagelimiter.cpp +++ b/tests/test_messagelimiter.cpp @@ -25,7 +25,7 @@ #include #include - +#include using namespace Opm; @@ -44,36 +44,37 @@ BOOST_AUTO_TEST_CASE(ConstructionAndLimits) BOOST_AUTO_TEST_CASE(Response) { + using namespace Opm; { // No limits. MessageLimiter m; - BOOST_CHECK(m.handleMessageTag("tag1") == MessageLimiter::Response::PrintMessage); - BOOST_CHECK(m.handleMessageTag("tag2") == MessageLimiter::Response::PrintMessage); - BOOST_CHECK(m.handleMessageTag("tag1") == MessageLimiter::Response::PrintMessage); - BOOST_CHECK(m.handleMessageTag("tag2") == MessageLimiter::Response::PrintMessage); - BOOST_CHECK(m.handleMessageTag("tag1") == MessageLimiter::Response::PrintMessage); - BOOST_CHECK(m.handleMessageTag("tag2") == MessageLimiter::Response::PrintMessage); + BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage); + BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage); + BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage); + BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage); + BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage); + BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage); } { // Limit == 0. MessageLimiter m(0); - BOOST_CHECK(m.handleMessageTag("tag1") == MessageLimiter::Response::JustOverLimit); - BOOST_CHECK(m.handleMessageTag("tag2") == MessageLimiter::Response::JustOverLimit); - BOOST_CHECK(m.handleMessageTag("tag1") == MessageLimiter::Response::OverLimit); - BOOST_CHECK(m.handleMessageTag("tag2") == MessageLimiter::Response::OverLimit); - BOOST_CHECK(m.handleMessageTag("tag1") == MessageLimiter::Response::OverLimit); - BOOST_CHECK(m.handleMessageTag("tag2") == MessageLimiter::Response::OverLimit); + BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::JustOverTagLimit); + BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::JustOverTagLimit); + BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit); + BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit); + BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit); + BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit); } { // Limit == 1. MessageLimiter m(1); - BOOST_CHECK(m.handleMessageTag("tag1") == MessageLimiter::Response::PrintMessage); - BOOST_CHECK(m.handleMessageTag("tag2") == MessageLimiter::Response::PrintMessage); - BOOST_CHECK(m.handleMessageTag("tag1") == MessageLimiter::Response::JustOverLimit); - BOOST_CHECK(m.handleMessageTag("tag2") == MessageLimiter::Response::JustOverLimit); - BOOST_CHECK(m.handleMessageTag("tag1") == MessageLimiter::Response::OverLimit); - BOOST_CHECK(m.handleMessageTag("tag2") == MessageLimiter::Response::OverLimit); + BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage); + BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage); + BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::JustOverTagLimit); + BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::JustOverTagLimit); + BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit); + BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit); } }