Improve MessageLimiter class.

This commit is contained in:
Atgeirr Flø Rasmussen 2016-10-19 13:11:13 +02:00
parent 68311cf5b3
commit 35514c0aa0
2 changed files with 135 additions and 46 deletions

View File

@ -20,11 +20,14 @@
#ifndef OPM_MESSAGELIMITER_HEADER_INCLUDED #ifndef OPM_MESSAGELIMITER_HEADER_INCLUDED
#define OPM_MESSAGELIMITER_HEADER_INCLUDED #define OPM_MESSAGELIMITER_HEADER_INCLUDED
#include <opm/common/OpmLog/LogUtil.hpp>
#include <cassert>
#include <map>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <map>
#include <vector> #include <vector>
#include <opm/common/OpmLog/LogUtil.hpp>
namespace Opm namespace Opm
{ {
@ -38,13 +41,7 @@ namespace Opm
/// Default constructor, no limit to the number of messages. /// Default constructor, no limit to the number of messages.
MessageLimiter() MessageLimiter()
: tag_limit_(NoLimit), : MessageLimiter(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}})
{ {
} }
@ -71,12 +68,24 @@ namespace Opm
{ {
} }
/// The message limit (same for all tags). /// The tag message limit (same for all tags).
int messageLimit() const int tagMessageLimit() const
{ {
return tag_limit_; return tag_limit_;
} }
/// The category message limits.
const std::map<int64_t, int>& categoryMessageLimits() const
{
return category_limits_;
}
/// The category message counts.
const std::map<int64_t, int>& categoryMessageCounts() const
{
return category_counts_;
}
/// Used for handleMessageLimits() return type (see that /// Used for handleMessageLimits() return type (see that
/// function). /// function).
enum class Response enum class Response
@ -84,52 +93,51 @@ namespace Opm
PrintMessage, JustOverTagLimit, JustOverCategoryLimit, OverTagLimit, OverCategoryLimit PrintMessage, JustOverTagLimit, JustOverCategoryLimit, OverTagLimit, OverCategoryLimit
}; };
/// If a tag is empty, there is no message limit or for that /// If (tag count == tag limit + 1) for the passed tag, respond JustOverTagLimit.
/// (count <= limit), respond PrintMessage. /// If (tag count > tag limit + 1), respond OverTagLimit.
/// If (count == limit + 1), respond JustOverLimit. /// If a tag is empty, there is no tag message limit or for that tag
/// If (count > limit + 1), respond OverLimit. /// (tag count <= tag limit), consider the category limits:
/// If (category count == category limit + 1) for the passed messageMask, respond JustOverCategoryLimit.
/// If (category count > category limit + 1), respond OverCategoryLimit.
/// If (category count <= category limit), or there is no limit for that category, respond PrintMessage.
Response handleMessageLimits(const std::string& tag, const int64_t messageMask) Response handleMessageLimits(const std::string& tag, const int64_t messageMask)
{ {
Response res = Response::PrintMessage; Response res = Response::PrintMessage;
// Deal with tag limits. // Deal with tag limits.
if (tag.empty() || tag_limit_ == NoLimit) { if (!tag.empty() && tag_limit_ != NoLimit) {
category_counts_[messageMask]++;
res = Response::PrintMessage;
} else {
// See if tag already encountered. // See if tag already encountered.
auto it = tag_counts_.find(tag); auto it = tag_counts_.find(tag);
if (it != tag_counts_.end()) { if (it != tag_counts_.end()) {
// Already encountered this tag. Increment its count. // Already encountered this tag. Increment its count.
const int count = ++it->second; const int count = ++it->second;
res = countBasedResponse(count, messageMask); res = countBasedResponseTag(count);
} else { } else {
// First encounter of this tag. Insert 1. // First encounter of this tag. Insert 1.
tag_counts_.insert({tag, 1}); tag_counts_.insert({tag, 1});
res = countBasedResponse(1, messageMask); res = countBasedResponseTag(1);
} }
} }
// If tag count reached the limit, ignore all the same tagged messages.
if (res == Response::JustOverTagLimit || res == Response::OverTagLimit) { // If tag count reached the limit, the message is not counted
return res; // towards the category limits.
} else { if (res == Response::PrintMessage) {
if (category_limits_[messageMask] == NoLimit) { // We are *not* above the tag limit, consider category limit.
category_counts_[messageMask]++; const int count = ++category_counts_[messageMask];
res = Response::PrintMessage; if (category_limits_[messageMask] != NoLimit) {
} else { res = countBasedResponseCategory(count, messageMask);
res = countBasedResponse(messageMask);
} }
} }
return res; return res;
} }
private: private:
Response countBasedResponse(const int count, const int64_t messageMask) Response countBasedResponseTag(const int count) const
{ {
if (count <= tag_limit_) { if (count <= tag_limit_) {
category_counts_[messageMask]++;
return Response::PrintMessage; return Response::PrintMessage;
} else if (count == tag_limit_ + 1) { } else if (count == tag_limit_ + 1) {
category_counts_[messageMask]++;
return Response::JustOverTagLimit; return Response::JustOverTagLimit;
} else { } else {
return Response::OverTagLimit; return Response::OverTagLimit;
@ -137,13 +145,12 @@ namespace Opm
} }
Response countBasedResponse(const int64_t messageMask) Response countBasedResponseCategory(const int count, const int64_t messageMask) const
{ {
if (category_counts_[messageMask] < category_limits_[messageMask]) { const int limit = category_limits_.at(messageMask);
category_counts_[messageMask]++; if (count <= limit) {
return Response::PrintMessage; return Response::PrintMessage;
} else if (category_counts_[messageMask] == category_limits_[messageMask] + 1) { } else if (count == limit + 1) {
category_counts_[messageMask]++;
return Response::JustOverCategoryLimit; return Response::JustOverCategoryLimit;
} else { } else {
return Response::OverCategoryLimit; return Response::OverCategoryLimit;
@ -152,10 +159,13 @@ namespace Opm
int tag_limit_; int tag_limit_;
std::unordered_map<std::string, int> tag_counts_; std::unordered_map<std::string, int> tag_counts_;
std::map<int64_t, int> category_counts_;
// info, note, warning, problem, error, bug.
std::map<int64_t, int> category_limits_; std::map<int64_t, int> category_limits_;
bool reachTagLimit_; std::map<int64_t, int> category_counts_ = {{Log::MessageType::Note, 0},
{Log::MessageType::Info, 0},
{Log::MessageType::Warning, 0},
{Log::MessageType::Error, 0},
{Log::MessageType::Problem, 0},
{Log::MessageType::Bug, 0}};
}; };

View File

@ -33,16 +33,16 @@ using namespace Opm;
BOOST_AUTO_TEST_CASE(ConstructionAndLimits) BOOST_AUTO_TEST_CASE(ConstructionAndLimits)
{ {
MessageLimiter m1; MessageLimiter m1;
BOOST_CHECK_EQUAL(m1.messageLimit(), MessageLimiter::NoLimit); BOOST_CHECK_EQUAL(m1.tagMessageLimit(), MessageLimiter::NoLimit);
MessageLimiter m2(0); MessageLimiter m2(0);
BOOST_CHECK_EQUAL(m2.messageLimit(), 0); BOOST_CHECK_EQUAL(m2.tagMessageLimit(), 0);
MessageLimiter m3(1); MessageLimiter m3(1);
BOOST_CHECK_EQUAL(m3.messageLimit(), 1); BOOST_CHECK_EQUAL(m3.tagMessageLimit(), 1);
MessageLimiter m4(-4); MessageLimiter m4(-4);
BOOST_CHECK_EQUAL(m4.messageLimit(), MessageLimiter::NoLimit); BOOST_CHECK_EQUAL(m4.tagMessageLimit(), MessageLimiter::NoLimit);
} }
BOOST_AUTO_TEST_CASE(Response) BOOST_AUTO_TEST_CASE(TagResponse)
{ {
using namespace Opm; using namespace Opm;
{ {
@ -54,6 +54,7 @@ BOOST_AUTO_TEST_CASE(Response)
BOOST_CHECK(m.handleMessageLimits("tag2", 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("tag1", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage);
BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage); BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage);
BOOST_CHECK(m.categoryMessageCounts().at(Log::MessageType::Info) == 6);
} }
{ {
@ -65,6 +66,7 @@ BOOST_AUTO_TEST_CASE(Response)
BOOST_CHECK(m.handleMessageLimits("tag2", 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("tag1", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit);
BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit); BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit);
BOOST_CHECK(m.categoryMessageCounts().at(Log::MessageType::Info) == 0);
} }
{ {
@ -76,5 +78,82 @@ BOOST_AUTO_TEST_CASE(Response)
BOOST_CHECK(m.handleMessageLimits("tag2", 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("tag1", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit);
BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit); BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::OverTagLimit);
BOOST_CHECK(m.categoryMessageCounts().at(Log::MessageType::Info) == 2);
} }
} }
BOOST_AUTO_TEST_CASE(CategoryResponse)
{
using namespace Opm;
{
// No limits.
MessageLimiter m;
BOOST_CHECK(m.handleMessageLimits("", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage);
BOOST_CHECK(m.handleMessageLimits("", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage);
BOOST_CHECK(m.handleMessageLimits("", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage);
BOOST_CHECK(m.categoryMessageCounts().at(Log::MessageType::Info) == 3);
}
{
// Limit == 0.
MessageLimiter m(MessageLimiter::NoLimit,
{{ Log::MessageType::Info, 0 }});
BOOST_CHECK(m.handleMessageLimits("", Log::MessageType::Info) == MessageLimiter::Response::JustOverCategoryLimit);
BOOST_CHECK(m.handleMessageLimits("", Log::MessageType::Info) == MessageLimiter::Response::OverCategoryLimit);
BOOST_CHECK(m.handleMessageLimits("", Log::MessageType::Info) == MessageLimiter::Response::OverCategoryLimit);
BOOST_CHECK(m.categoryMessageCounts().at(Log::MessageType::Info) == 3);
}
{
// Limit == 1.
MessageLimiter m(MessageLimiter::NoLimit,
{{ Log::MessageType::Info, 1 }});
BOOST_CHECK(m.handleMessageLimits("", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage);
BOOST_CHECK(m.handleMessageLimits("", Log::MessageType::Info) == MessageLimiter::Response::JustOverCategoryLimit);
BOOST_CHECK(m.handleMessageLimits("", Log::MessageType::Info) == MessageLimiter::Response::OverCategoryLimit);
BOOST_CHECK(m.categoryMessageCounts().at(Log::MessageType::Info) == 3);
}
}
BOOST_AUTO_TEST_CASE(MixedResponse)
{
using namespace Opm;
{
// Tag Limit == 1. Category limit = 0.
MessageLimiter m(1, {{ Log::MessageType::Info, 0 }});
BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::JustOverCategoryLimit);
BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::OverCategoryLimit);
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.categoryMessageCounts().at(Log::MessageType::Info) == 2);
}
{
// Tag Limit == 0. Category limit = 1.
MessageLimiter m(0, {{ Log::MessageType::Info, 1 }});
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);
BOOST_CHECK(m.categoryMessageCounts().at(Log::MessageType::Info) == 0);
}
{
// Tag Limit == 1. Category limit = 1.
MessageLimiter m(1, {{ Log::MessageType::Info, 1 }});
BOOST_CHECK(m.handleMessageLimits("tag1", Log::MessageType::Info) == MessageLimiter::Response::PrintMessage);
BOOST_CHECK(m.handleMessageLimits("tag2", Log::MessageType::Info) == MessageLimiter::Response::JustOverCategoryLimit);
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.categoryMessageCounts().at(Log::MessageType::Info) == 2);
}
}