Setting boost::log severity filter to call a funct

2019-09-11 06:50发布

I've created a Logger class that uses boost::log. The class keeps track of the current severity level set. When adding a severity filter to a sink, I'd like that the filter do the filtering based on the current severity, as opposed to the one when the sink was added.

class Logger
{
public:
    typedef /* ... */ severity_level;
    //(...)
    static severity_level currentSeverityLevel() {return severity_level_var;}
private:
    severity_level severity_level_var;
    //(...)
};

When adding a filter, as below, currentSeverityLevel() is called only when the filter is set.

console_sink->set_filter( severity >= Logger::currentSeverityLevel());

I would like such a filter, but that actually calls the function every time. As per the documentation, one can define a function to be used as filter (see below), but it requires the use of boost::phoenix. Surely there must be a simpler way? Something like a lambda expression? The set_filter function sets a filter type, which in turn sets a boost light_function, which is a "lightweight alternative of Boost.Function". It seems, then, that it would be straight forward to set something similar to a Lambda expression/Boost.Function

bool my_filter(logging::value_ref< severity_level, tag::severity > const& level,
               logging::value_ref< std::string, tag::tag_attr > const& tag)
{
    return level >= warning || tag == "IMPORTANT_MESSAGE";
}

void init()
{
    // ...
    namespace phoenix = boost::phoenix;
    sink->set_filter(phoenix::bind(&my_filter, severity.or_none(), tag_attr.or_none()));
    // ...
}

1条回答
老娘就宠你
2楼-- · 2019-09-11 07:20

In order to call Logger::currentSeverityLevel on every log record you have to turn it into a Boost.Phoenix expression so that it is evaluated lazily. The simplest way to do this is to use phoenix::bind.

console_sink->set_filter(
    severity >= phoenix::bind(&Logger::currentSeverityLevel)
);

You can achieve a cleaner syntax if you create a lazy wrapper for your function as described here.

BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(
    Logger::severity_level,
    lazyCurrentSeverityLevel,
    Logger::currentSeverityLevel
);

console_sink->set_filter(severity >= lazyCurrentSeverityLevel());

Also, you can save references to external objects in Boost.Phoenix expressions.

console_sink->set_filter(severity >= phoenix::ref(severity_level_var));

This filter will read the severity_level_var value on every call. However, this approach makes it more difficult to ensure thread safe operations on the severity_level_var variable. This is not done in your currentSeverityLevel implementation, so I assume thread safety is either not required or achieved by other means.

查看更多
登录 后发表回答