如何从 boost log sink 组织线程安全读取?
How to organize thread safe reading from boost log sink?
我正在寻找从 boost::log::sinks::text_ostream_backend 安全获取文本数据的正确方法。
我目前仅在所有内容都记录在接收器后端后才获取数据。我想获取后端内部缓冲区的副本 (m_ss),同时仍然可以生成数据。
using Logger = boost::log::sources::severity_channel_logger_mt<boost::log::trivial::severity_level, std::string>;
class MyClass
{
mutable std::mutex m_mutex;
mutable Logger m_logger {boost::log::keywords::channel = "MyClass"};
std::stringstream m_ss;
bool m_completed {false};
public:
void initLogging(const std::string& id)
{
using namespace boost::log;
using Sink = sinks::synchronous_sink<sinks::text_ostream_backend>;
auto backend = boost::make_shared<sinks::text_ostream_backend>();
backend->add_stream(boost::shared_ptr<std::stringstream>(&m_ss, boost::null_deleter()));
auto sink = boost::make_shared<Sink>(backend);
sink->set_filter(expressions::has_attr<std::string>("ID") && expressions::attr<std::string>("ID") == id);
core::get()->add_sink(sink);
m_logger.add_attribute("ID", attributes::constant<std::string>(id));
}
void doSomething()
{
BOOST_LOG_SEV(logger, boost::log::trivial::severity_level::debug) << "TEST";
BOOST_LOG_SEV(logger, boost::log::trivial::severity_level::error) << "TEST";
// Stop write logs
std::lock_guard<std::mutex> lock(m_mutex);
m_completed = true;
}
void access()
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_completed) {
// Can read from stream
useStreamData(m_ss.str());
}
}
};
如果流仅由接收器后端访问,那么同步访问的最简单方法是使用 locked_backend
.
auto locked_backend = sink->locked_backend();
这里,locked_backend
对象是一个智能指针,它锁定接收器前端,因此阻止日志记录线程访问后端,从而阻止 m_ss
流。当 locked_backend
存在时,您可以安全地使用 m_ss
。
还有其他方法可以实现这一点。例如,你可以实现一个 custom sink backend or implement a stream buffer that would allow synchronized access to the accumulated data. There are a number of articles and blog posts about writing custom stream buffers, here is one example.
我正在寻找从 boost::log::sinks::text_ostream_backend 安全获取文本数据的正确方法。 我目前仅在所有内容都记录在接收器后端后才获取数据。我想获取后端内部缓冲区的副本 (m_ss),同时仍然可以生成数据。
using Logger = boost::log::sources::severity_channel_logger_mt<boost::log::trivial::severity_level, std::string>;
class MyClass
{
mutable std::mutex m_mutex;
mutable Logger m_logger {boost::log::keywords::channel = "MyClass"};
std::stringstream m_ss;
bool m_completed {false};
public:
void initLogging(const std::string& id)
{
using namespace boost::log;
using Sink = sinks::synchronous_sink<sinks::text_ostream_backend>;
auto backend = boost::make_shared<sinks::text_ostream_backend>();
backend->add_stream(boost::shared_ptr<std::stringstream>(&m_ss, boost::null_deleter()));
auto sink = boost::make_shared<Sink>(backend);
sink->set_filter(expressions::has_attr<std::string>("ID") && expressions::attr<std::string>("ID") == id);
core::get()->add_sink(sink);
m_logger.add_attribute("ID", attributes::constant<std::string>(id));
}
void doSomething()
{
BOOST_LOG_SEV(logger, boost::log::trivial::severity_level::debug) << "TEST";
BOOST_LOG_SEV(logger, boost::log::trivial::severity_level::error) << "TEST";
// Stop write logs
std::lock_guard<std::mutex> lock(m_mutex);
m_completed = true;
}
void access()
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_completed) {
// Can read from stream
useStreamData(m_ss.str());
}
}
};
如果流仅由接收器后端访问,那么同步访问的最简单方法是使用 locked_backend
.
auto locked_backend = sink->locked_backend();
这里,locked_backend
对象是一个智能指针,它锁定接收器前端,因此阻止日志记录线程访问后端,从而阻止 m_ss
流。当 locked_backend
存在时,您可以安全地使用 m_ss
。
还有其他方法可以实现这一点。例如,你可以实现一个 custom sink backend or implement a stream buffer that would allow synchronized access to the accumulated data. There are a number of articles and blog posts about writing custom stream buffers, here is one example.