gpt4 book ai didi

filtering - 使用自定义属性和严重级别为提升日志接收器设置自定义过滤器

转载 作者:行者123 更新时间:2023-12-04 12:44:54 25 4
gpt4 key购买 nike

我有一个日志设置,其中有两种类型的日志消息:

  • 1 完全基于严重程度
  • 1 完全基于自定义标签属性

这些属性定义如下:

BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", trivial::severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(tag_attr, "Tag", std::string)

我想创建一个过滤器功能,允许根据 2 个标准中的任何一个将消息添加到我的日志中(请注意,基于自定义标签属性的日志消息总是打印严重级别信息,基于琐碎的记录器的严重级别)。

所以我想要一个过滤器,它允许基于消息是否具有自定义标记的消息,如果没有,则基于消息的严重性。

我尝试使用一个相对简单的过滤器来执行以下操作:

sink_->set_filter(
trivial::severity >= severityLevel
|| (expr::has_attr(tag_attr) && tag_attr == "JSON" && logJson_)
);

但由于 severityLevel 可能是 Debug、Info、Warning、Error 或 Fatal,如果级别配置为 Debug 或 Info,自定义标记属性将被过滤器忽略。

我试过使用 c++11 lambda,如下所示:

sink_->set_filter([this, severityLevel](const auto& attr_set) {
if (<condition for custom tag first>) {
return true;
} else if (<condition for severity level second>) {
return true;
} else {
return false;
}
});

但是我不知道如何实际检查我的条件。我尝试了以下方法:

if (attr_set["Tag"].extract<std::string>() == "JSON" && logJson_) {
return true;
} else if (attr_set["Severity"].extract<trivial::severity_level>() >= severityLevel) {
return true;
} else {
return false;
}

但是编译器会抛出几个错误:

Core/Source/Log/Logger.cpp: In lambda function:
Core/Source/Log/Logger.cpp:127:48: error: expected primary-expression before '>' token
if (attr_set["Tag"].extract<std::string>() == "JSON" && logJson_) {
^
Core/Source/Log/Logger.cpp:127:50: error: expected primary-expression before ')' token
if (attr_set["Tag"].extract<std::string>() == "JSON" && logJson_) {
^
Core/Source/Log/Logger.cpp:129:72: error: expected primary-expression before '>' token
} else if (attr_set["Severity"].extract<trivial::severity_level>() >= severityLevel) {
^
Core/Source/Log/Logger.cpp:129:74: error: expected primary-expression before ')' token
} else if (attr_set["Severity"].extract<trivial::severity_level>() >= severityLevel) {
^
Core/Source/Log/Logger.cpp: In lambda function:
Core/Source/Log/Logger.cpp:134:5: error: control reaches end of non-void function [-Werror=return-type]
});
^
cc1plus: all warnings being treated as errors
scons: *** [obj/release/Core/Source/Log/Logger.os] Error 1
====5 errors, 0 warnings====

我一直在搜索关于自己提取属性的 boost 日志文档,但找不到我需要的信息。

编辑:

为了后代,我将添加我是如何解决我的问题的(感谢 Andrey 给出的答案):

sink_->set_filter([this, severityLevel](const auto& attr_set) {
if (attr_set[tag_attr] == "JSON") {
return logJson_;
} else if (attr_set[severity] >= severityLevel) {
return true;
} else {
return false;
}
});

最佳答案

过滤器可以用多种方式编写,我将演示几种替代方法。

首先,使用表达式模板你可以这样写:

sink_->set_filter(
(expr::has_attr(tag_attr) && tag_attr == "JSON" && logJson_) ||
trivial::severity >= severityLevel
);

按照C++的正常短路规则,首先会测试标签属性,如果条件成功,则不会测试严重性。如果标签不存在或不是 JSON 或 logJson_不正确,则测试严重性级别。

请注意,上面的过滤器将在构建时保存其参数的副本(包括 logJson_severityLevel ),因此如果您更改 logJson_稍后过滤器将继续使用旧值。这与您后来尝试使用 C++14 lambda 的一个重要区别,后者访问 logJson_。通过捕获的 this指针。如果你真的想保存对你的成员的引用 logJson_在过滤器中,您可以使用 phoenix::ref :

sink_->set_filter(
(expr::has_attr(tag_attr) && tag_attr == "JSON" && boost::phoenix::ref(logJson_)) ||
trivial::severity >= severityLevel
);

但是,你应该记住过滤器可以在多个线程中并发调用,所以访问logJson_不 protected 。如果要更新 logJson_,则必须实现自己的线程同步在运行时。

除非多线程问题,否则您对 lambda 的第二次尝试几乎是正确的。编译器提示是因为 lambda 函数是一个模板,而 attr_set["Tag"] 的结果表达式取决于模板参数之一(即 attr_set 的类型)。在这种情况下,程序员必须限定以下 extract<std::string>() expression 是模板实例化而不是比较序列。这是通过添加 template 来完成的。关键词:

if (attr_set["Tag"].template extract<std::string>() == "JSON" && logJson_) {
return true;
} else if (attr_set["Severity"].template extract<trivial::severity_level>() >= severityLevel) {
return true;
} else {
return false;
}

请注意,您可以使用独立函数来达到相同的效果,这不需要模板限定:

if (boost::log::extract<std::string>("Tag", attr_set) == "JSON" && logJson_) {
return true;
} else if (boost::log::extract<trivial::severity_level>("Severity", attr_set) >= severityLevel) {
return true;
} else {
return false;
}

最后,提取属性值的首选方法是利用您之前声明的属性关键字。这不仅可以避免模板限定怪癖,还可以消除大量代码重复。

BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", trivial::severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(tag_attr, "Tag", std::string)

if (attr_set[tag_attr] == "JSON" && logJson_) {
return true;
} else if (attr_set[severity] >= severityLevel) {
return true;
} else {
return false;
}

在这种情况下,属性值名称和类型是从关键字声明中推断出来的。 this 末尾记录了属性关键字的这种使用部分。

关于filtering - 使用自定义属性和严重级别为提升日志接收器设置自定义过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52206677/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com