I am trying to create filter by configurable severity level. I have written following filter class:
class FilterBySeverity
{
public:
FilterBySeverity(boost::log::trivial::severity_level logLevel) :
m_logLevel(logLevel),
m_severityAttributeName("Severity")
{
}
bool operator()(const boost::log::attribute_value_set& attrs) const noexcept
{
auto it = attrs.find(m_severityAttributeName);
if (it == attrs.end()) return true;
return it->second.extract<int>() >= m_logLevel;
}
private:
const boost::log::trivial::severity_level m_logLevel;
const boost::log::attribute_name m_severityAttributeName;
};
and then I am initializing log as follows:
auto sink = boost::log::add_console_log(std::cout);
sink->set_filter(FilterBySeverity(logOptions.m_severity));
sink->locked_backend()->auto_flush(true);
Then I am making test output:
BOOST_LOG_TRIVIAL(info) << "Logging started.";
But I can't see my message. But when I comment out call to set_filter(), message appears. Value of the logOptions.m_severity is 0, i.e. all messages should be allowed. Tried to set breakpoint in the operator() and check what's going on - it seems to work correctly. What I am doing wrong?
The problem is the incorrect attribute value type you're trying to extract. You explicitly specify the type as
intwhile the logger used byBOOST_LOG_TRIVIALusesboost::log::trivial::severity_level. The result of theextractcall in this case is an emptyvalue_refinstance, which returnsfalseon any comparison operators.A better and more correct way to write the filter is to use attribute keywords, which take care of both the attribute names and their value types. Since you're using the trivial logging API, there is already a keyword defined by the library that corresponds to an attribute named "Severity" that has values of type
boost::log::trivial::severity_level:boost::log::trivial::severity.