opm-common/opm/common/OpmLog/MessageLimiter.hpp

176 lines
6.4 KiB
C++
Raw Normal View History

2016-05-18 05:11:26 -05:00
/*
Copyright 2016 SINTEF ICT, Applied Mathematics.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_MESSAGELIMITER_HEADER_INCLUDED
#define OPM_MESSAGELIMITER_HEADER_INCLUDED
2016-10-19 06:11:13 -05:00
#include <opm/common/OpmLog/LogUtil.hpp>
#include <cassert>
#include <map>
2016-05-18 05:11:26 -05:00
#include <string>
#include <unordered_map>
2016-10-18 06:26:06 -05:00
#include <vector>
2016-10-19 06:11:13 -05:00
2016-05-18 05:11:26 -05:00
namespace Opm
{
/// Handles limiting the number of messages with the same tag.
class MessageLimiter
{
public:
/// Used to indicate no message number limit.
enum { NoLimit = -1 };
/// Default constructor, no limit to the number of messages.
MessageLimiter()
2016-10-19 06:11:13 -05:00
: MessageLimiter(NoLimit)
2016-05-18 05:11:26 -05:00
{
}
/// Construct with given limit to number of messages with the
/// same tag.
///
/// Negative limits (including NoLimit) are interpreted as
/// NoLimit, but the default constructor is the preferred way
/// to obtain that behaviour.
2016-10-18 06:26:06 -05:00
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<int64_t, int> category_limits)
: tag_limit_(tag_limit < 0 ? NoLimit : tag_limit),
category_limits_(category_limits)
2016-05-18 05:11:26 -05:00
{
}
2016-10-19 06:11:13 -05:00
/// The tag message limit (same for all tags).
int tagMessageLimit() const
2016-05-18 05:11:26 -05:00
{
2016-10-18 06:26:06 -05:00
return tag_limit_;
2016-05-18 05:11:26 -05:00
}
2016-10-19 06:11:13 -05:00
/// 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_;
}
2016-10-18 06:26:06 -05:00
/// Used for handleMessageLimits() return type (see that
2016-05-18 05:11:26 -05:00
/// function).
enum class Response
{
2016-10-18 06:26:06 -05:00
PrintMessage, JustOverTagLimit, JustOverCategoryLimit, OverTagLimit, OverCategoryLimit
2016-05-18 05:11:26 -05:00
};
2016-10-19 06:11:13 -05:00
/// If (tag count == tag limit + 1) for the passed tag, respond JustOverTagLimit.
/// If (tag count > tag limit + 1), respond OverTagLimit.
/// If a tag is empty, there is no tag message limit or for that tag
/// (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.
2016-10-18 06:26:06 -05:00
Response handleMessageLimits(const std::string& tag, const int64_t messageMask)
2016-05-18 05:11:26 -05:00
{
2016-10-18 06:26:06 -05:00
Response res = Response::PrintMessage;
2016-10-19 06:11:13 -05:00
2016-10-18 06:26:06 -05:00
// Deal with tag limits.
2016-10-19 06:11:13 -05:00
if (!tag.empty() && tag_limit_ != NoLimit) {
2016-05-18 05:11:26 -05:00
// 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;
2016-10-19 06:11:13 -05:00
res = countBasedResponseTag(count);
2016-05-18 05:11:26 -05:00
} else {
// First encounter of this tag. Insert 1.
tag_counts_.insert({tag, 1});
2016-10-19 06:11:13 -05:00
res = countBasedResponseTag(1);
2016-05-18 05:11:26 -05:00
}
}
2016-10-19 06:11:13 -05:00
// If tag count reached the limit, the message is not counted
// towards the category limits.
if (res == Response::PrintMessage) {
// We are *not* above the tag limit, consider category limit.
const int count = ++category_counts_[messageMask];
if (category_limits_[messageMask] != NoLimit) {
res = countBasedResponseCategory(count, messageMask);
2016-10-18 06:26:06 -05:00
}
}
2016-10-19 06:11:13 -05:00
2016-10-18 06:26:06 -05:00
return res;
2016-05-18 05:11:26 -05:00
}
private:
2016-10-19 06:11:13 -05:00
Response countBasedResponseTag(const int count) const
2016-05-18 05:11:26 -05:00
{
2016-10-18 06:26:06 -05:00
if (count <= tag_limit_) {
2016-05-18 05:11:26 -05:00
return Response::PrintMessage;
2016-10-18 06:26:06 -05:00
} else if (count == tag_limit_ + 1) {
return Response::JustOverTagLimit;
2016-05-18 05:11:26 -05:00
} else {
2016-10-18 06:26:06 -05:00
return Response::OverTagLimit;
2016-05-18 05:11:26 -05:00
}
}
2016-10-19 06:11:13 -05:00
Response countBasedResponseCategory(const int count, const int64_t messageMask) const
2016-10-18 06:26:06 -05:00
{
2016-10-19 06:11:13 -05:00
const int limit = category_limits_.at(messageMask);
if (count <= limit) {
2016-10-18 06:26:06 -05:00
return Response::PrintMessage;
2016-10-19 06:11:13 -05:00
} else if (count == limit + 1) {
2016-10-18 06:26:06 -05:00
return Response::JustOverCategoryLimit;
} else {
return Response::OverCategoryLimit;
}
}
int tag_limit_;
2016-05-18 05:11:26 -05:00
std::unordered_map<std::string, int> tag_counts_;
2016-10-18 06:26:06 -05:00
std::map<int64_t, int> category_limits_;
2016-10-19 06:11:13 -05:00
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}};
2016-05-18 05:11:26 -05:00
};
} // namespace Opm
#endif // OPM_MESSAGELIMITER_HEADER_INCLUDED