gpt4 book ai didi

c++ - boost::log 在容器中保存消息,然后将所有消息发送到后端

转载 作者:行者123 更新时间:2023-11-28 06:07:51 24 4
gpt4 key购买 nike

我想用 memory_sink 之类的东西将实际格式化的消息保存在内存中,然后在 flush 上在后端发送消息。但是有一个问题,保存的record_view的属性被更改为最后创建的record_view的属性,我不知道为什么会这样。但可能有人会问我,我能否实现我想要的东西?

真正最小的例子:

#define BOOST_LOG_DLL 1
#include <boost/log/core.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/basic_sink_backend.hpp>
#include <boost/log/expressions/keyword.hpp>
#include <boost/log/trivial.hpp>
#undef BOOST_LOG_DLL

#include <boost/shared_ptr.hpp>
#include <queue>

namespace logging = boost::log;
namespace sinks = boost::log::sinks;

typedef sinks::combine_requirements<sinks::synchronized_feeding, sinks::flushing>::type sync_flushing;

struct message_t
{
message_t(const logging::record_view& r, const std::string& f) :
record(r), fstring(f)
{
}
logging::record_view record;
std::string fstring;
};

template<typename Sink>
class memory_sink : public sinks::basic_formatted_sink_backend<char, sync_flushing>
{
public:
memory_sink(const boost::shared_ptr<Sink>& sink) : sink_(sink)
{
}

void consume(const logging::record_view& rec, const string_type& fstring)
{
const message_t msg(rec, fstring);
messages_.push(msg);
}

void flush()
{
while (!messages_.empty())
{
const message_t& msg = messages_.front();
sink_->consume(msg.record, msg.fstring);
messages_.pop();
}
}
private:
typedef std::queue<message_t> buffer_t;
buffer_t messages_;
const boost::shared_ptr<Sink> sink_;
};

std::ostream& operator << (std::ostream& stream, logging::trivial::severity_level lvl)
{
return stream << boost::log::trivial::to_string(lvl);
}

class cout_sink : public sinks::basic_formatted_sink_backend< char, sinks::synchronized_feeding >
{
public:
std::string format(const logging::record_view& rec, const std::string& fstring) const
{
return fstring;
}
void consume(const logging::record_view& rec, const std::string& fstring)
{
std::cout << "[" << rec[boost::log::trivial::severity] << "] " << fstring << std::endl;
}
};

void init_cout()
{
typedef sinks::synchronous_sink<memory_sink<cout_sink> > sink_t;

boost::shared_ptr< logging::core > core = logging::core::get();
core->remove_all_sinks();

boost::shared_ptr< cout_sink > tsink = boost::make_shared<cout_sink>();
boost::shared_ptr<memory_sink<cout_sink> > backend = boost::make_shared<memory_sink<cout_sink> >(tsink);
boost::shared_ptr< sink_t > sink = boost::make_shared<sink_t>(tsink);

core->add_sink(sink);
}

void flush_logs()
{
logging::core::get()->flush();
}

int main()
{
logging::add_common_attributes();
init_cout();
BOOST_LOG_TRIVIAL(warning) << "warning message";
BOOST_LOG_TRIVIAL(error) << "error message";
flush_logs();
}

Live version

如您所见,两条记录中的严重性均为错误,但我期望的是警告错误。可能有更好的方法来做到这一点?

我知道格式化程序,这里严重性打印在 backend 中,仅作为示例,因为实际代码更大并且在消费接收 record_view 时下沉,而不是将它发送到后端,它也只接收 record_view

最佳答案

您观察到的行为是由库使用的优化技术引起的。创建日志记录时,Boost.Log 有时可以通过引用保存原始值的线程特定数据来避免将属性值复制到记录中。在处理记录时,特定于线程的数据应该保持不变。显然需要在线程之间传递记录的异步接收器有一种与日志记录核心通信的方式,因此禁用此优化并且日志记录在传递到接收器之前与原始线程分离。这是描述here ,请参阅有关 detach_from_thread 的注释。

问题是只有接收器前端决定是否必须禁用此优化,并且只有 asynchronous_sink 会这样做。没有办法为其他前端定制它。因此,要么您必须使用带有 asynchronous_sink 的后端,要么您也必须编写前端。

要实现接收器前端,您需要一个派生自 sink 的类基类并执行过滤、格式化(如果需要)并将记录传递给后端。您可以使用 synchronous_sink 实现作为示例。与 synchronous_sink 的重要区别是您必须将 true 传递给 sink 构造函数。这将告诉日志记录核心您的接收器需要分离的日志记录。

关于c++ - boost::log 在容器中保存消息,然后将所有消息发送到后端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32010535/

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