c++ Boost日志:使用设置文件过滤命名的作用域

njthzxwz  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(109)

我在我的项目中使用Boost Log,我希望能够在设置文件中过滤我当前对控制台接收器感兴趣的作用域。
我添加了names scope属性,使用:

BOOST_LOG_ATTRIBUTE_KEYWORD(scope_attr, "Scope", boost::log::attributes::named_scope::value_type)

boost::log::core::get()->add_global_attribute("Scope", boost::log::attributes::named_scope());

字符串
在代码中,我使用了BOOST_PROJECT_NAMED_SCOPE宏,并通过boost::log::init_from_stream传递了以下设置:

[Core]
DisableLogging = false
Filter = "%Severity% >= DEBUG"
[Sinks.1]
Destination = Console
Format = "[%Severity%] [%TimeStamp%] [%Scope%] [%Tag%]: %Message%"
Filter = "%Scope% = \"TargetScope\" & %Severity% >= DEBUG"
[Sinks.2]
Destination = TextFile
FileName = textfile.log
AutoFlush = true
Format = "[%Severity%] [%TimeStamp%] [%Scope%] [%Tag%]: %Message%"


没有激活过滤器,“Scope”属性工作正常,并正确打印,在作用域之间添加“->”,并且只有目标作用域被打印为“...[TargetScope]..."的日志。但是如果我激活过滤器,什么也不会打印。
默认情况下支持过滤命名作用域?还是应该为过滤器解析系统编写一个扩展?

kh212irz

kh212irz1#

docs
必须注意的是,默认情况下,库只支持那些在库构建时已知的属性值类型。用户定义的类型在库中注册之前,将无法在解析的过滤器和格式化程序中正常工作。也可以重写已知类型的格式化规则,包括支持字符串模板中的其他格式参数。更多关于这方面的内容可以在扩展库部分找到。
从Boost日志中,通过命名范围过滤,你可以得到一个过滤器函数(我简化了):

bool my_filter(bl::value_ref<attr::named_scope_list> const& scopes, std::string const& target_scope) {
    if (!scopes.empty())
        for (auto& scope : scopes.get())
            if (scope.scope_name == target_scope)
                return true;

    return false;
}

字符串

解析过滤器

在这里,我们必须Extend library settings support
向过滤器解析器添加对用户定义类型的支持提供了一些步骤。
我选择了自定义(非简单)过滤器工厂,并将其与通用匹配函数相结合,如刚才显示的my_filter,名为allany

struct scope_filter_factory : bl::filter_factory<char> {
    bl::filter on_equality_relation(bl::attribute_name const& name, string_type const& arg) override {
        return px::bind(any<std::equal_to<>>,                               //
                        expr::attr<attr::named_scope_list>(name).or_none(), //
                        arg);
    }

    bl::filter on_inequality_relation(bl::attribute_name const& name, string_type const& arg) override {
        return px::bind(all<std::not_equal_to<>>,                           //
                        expr::attr<attr::named_scope_list>(name).or_none(), //
                        arg);
    }

  private:
    using list = attr::named_scope_list;
    template <typename Rel>
    static bool any(bl::value_ref<list> const& attr, std::string const& target_scope) {
        if (attr.empty())
            return false;

        return std::any_of(begin(attr.get()), end(attr.get()), [&, cmp = Rel{}](auto const& scope) {
            return cmp(scope.scope_name, target_scope);
        });
    }
    template <typename Rel>
    static bool all(bl::value_ref<list> const& attr, std::string const& target_scope) {
        if (attr.empty())
            return true;

        return std::all_of(begin(attr.get()), end(attr.get()), [&, cmp = Rel{}](auto const& scope) {
            return cmp(scope.scope_name, target_scope);
        });
    }
};


您使用register_filter_factory注册它,例如:

void init_logging() {
    bl::core::get()->add_global_attribute("Scope", attr::named_scope());
    bl::register_filter_factory("Scope", boost::make_shared<scope_filter_factory>());
    std::ifstream ifs("logging.cfg");
    bl::init_from_stream(ifs);
}


然后我们可以用一些函数进行测试,如

void bar(log_level level) {
    BOOST_LOG_NAMED_SCOPE(__FUNCTION__);
    BOOST_LOG_SEV(glg, level) << __FUNCTION__ << ":" << 222;
    BOOST_LOG_SEV(glg, level) << __FUNCTION__ << ":" << 333;
}

void foo(log_level level) {
    BOOST_LOG_NAMED_SCOPE(__FUNCTION__);
    BOOST_LOG_SEV(glg, level) << __FUNCTION__ << ":" << 333;
    bar(level);
    BOOST_LOG_SEV(glg, level) << __FUNCTION__ << ":" << 444;
}

int main() {
    init_logging();

    for (auto level : {log_level::trace, log_level::debug, log_level::info, //
                       log_level::warning, log_level::error, log_level::fatal})
        foo(level);
}


的数据

完整列表

Live On Coliru

#include <boost/log/attributes/named_scope.hpp>
#include <boost/log/attributes/scoped_attribute.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup.hpp>
#include <boost/phoenix.hpp>
#include <fstream>
namespace bl    = boost::log;
namespace attr  = bl::attributes;
namespace expr  = bl::expressions;
namespace px    = boost::phoenix;
using log_level = bl::trivial::severity_level;
bl::sources::severity_logger<log_level> glg;

BOOST_LOG_ATTRIBUTE_KEYWORD(severity,   "Severity", bl::trivial::severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(scope_attr, "Scope",    attr::named_scope::value_type)

// ============================================================================
// Custom filter factory
struct scope_filter_factory : bl::filter_factory<char> {
    bl::filter on_equality_relation(bl::attribute_name const& name, string_type const& arg) override {
        return px::bind(any<std::equal_to<>>,                               //
                        expr::attr<attr::named_scope_list>(name).or_none(), //
                        arg);
    }

    bl::filter on_inequality_relation(bl::attribute_name const& name, string_type const& arg) override {
        return px::bind(all<std::not_equal_to<>>,                           //
                        expr::attr<attr::named_scope_list>(name).or_none(), //
                        arg);
    }

  private:
    using list = attr::named_scope_list;
    template <typename Rel>
    static bool any(bl::value_ref<list> const& attr, std::string const& target_scope) {
        if (attr.empty())
            return false;

        return std::any_of(begin(attr.get()), end(attr.get()), [&, cmp = Rel{}](auto const& scope) {
            return cmp(scope.scope_name, target_scope);
        });
    }
    template <typename Rel>
    static bool all(bl::value_ref<list> const& attr, std::string const& target_scope) {
        if (attr.empty())
            return true;

        return std::all_of(begin(attr.get()), end(attr.get()), [&, cmp = Rel{}](auto const& scope) {
            return cmp(scope.scope_name, target_scope);
        });
    }
};

void init_logging() {
    bl::core::get()->add_global_attribute("Scope", attr::named_scope());
    bl::register_filter_factory("Scope", boost::make_shared<scope_filter_factory>());
    std::ifstream ifs("logging.cfg");
    bl::init_from_stream(ifs);
}

// ============================================================================

void bar(log_level level) {
    BOOST_LOG_NAMED_SCOPE(__FUNCTION__);
    BOOST_LOG_SEV(glg, level) << __FUNCTION__ << ":" << 222;
    BOOST_LOG_SEV(glg, level) << __FUNCTION__ << ":" << 333;
}

void foo(log_level level) {
    BOOST_LOG_NAMED_SCOPE(__FUNCTION__);
    BOOST_LOG_SEV(glg, level) << __FUNCTION__ << ":" << 333;
    bar(level);
    BOOST_LOG_SEV(glg, level) << __FUNCTION__ << ":" << 444;
}

int main() {
    init_logging();

    for (auto level : {log_level::trace, log_level::debug, log_level::info, //
                       log_level::warning, log_level::error, log_level::fatal})
        foo(level);
}

相关问题