我正在Boost.Log之上实现包装器。在异步日志记录中,记录器不会立即写入日志消息,而是使消息排队。调用core.get()->flush()
方法时,消息将被写入文件。
但是很明显,在每条消息之后调用flush()效率不高。这样,异步日志记录就没有任何好处。在程序结束时一次调用它也不是一个好主意。 (也许程序在服务器上运行了很长时间)
我想编写一个代码来定期调用flush()(例如,每10毫秒一次)。
关于这个example和this问题,我使用Boost.asio编写了一个异步计时器,但它没有将消息写入文件。实际上,记录器不会创建任何.log文件。也许是因为没有发生日志记录时必须调用flush()方法。
typedef sinks::asynchronous_sink<
sinks::text_file_backend,
sinks::unbounded_ordering_queue<
logging::attribute_value_ordering< unsigned int, std::less< unsigned int > >
>
> Async_file_sink;
void do_flush(const boost::system::error_code& /*e*/,
boost::asio::deadline_timer* t)
{
logging::core::get()->flush();
t->expires_at(t->expires_at() + boost::posix_time::milliseconds(10));
t->async_wait(boost::bind(do_flush,
boost::asio::placeholders::error, t));
}
struct PerodicTimer{
PerodicTimer(boost::asio::deadline_timer &timer) : t(timer) {
t.async_wait(boost::bind(do_flush,
boost::asio::placeholders::error, &t));
}
boost::asio::deadline_timer& t;
};
void init_flushing()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::milliseconds(10));
PerodicTimer m(t);
std::thread th([&]{
// std::cout << "inside thread" << std::endl;
io.run();
});
th.detach();
}
static void init_logging()
{
logging::add_common_attributes();
boost::shared_ptr< Async_file_sink > sink(new Async_file_sink(
boost::make_shared< sinks::text_file_backend >(),
keywords::file_name = "sample_%N.log",
keywords::rotation_size = 1024 * 1024,
// We'll apply record ordering to ensure that records from different threads go sequentially in the file
keywords::order = logging::make_attr_ordering("LineID", std::less< unsigned int >())
));
// Set up where the rotated files will be stored
init_file_collecting(sink);
sink->set_formatter(&my_formatter);
sink->locked_backend()->scan_for_files();
logging::core::get()->add_sink(sink);
init_flushing(); // Starting Timer
}
int main()
{
init_logging();
ADD_LOG("SOME MESSAGE");
}
我认为问题在于,当flush()被调用()时,异步记录器正在记录消息。我无法在同一线程中运行异步计时器,因为io.run()正在阻止。
什么是最小解决方案?
答案 0 :(得分:1)
在init_flushing
中,您在生成线程后立即退出并在线程运行时销毁io_service io
和deadline_timer t
对象。这是未定义的行为,因此可以解释为什么代码未按预期运行。
在线程运行时,io
和t
都必须保持活动状态。但是,由于除了等待计时器之外,您没有使用io
进行其他操作,因此仅拥有一个调用std::this_thread::sleep_for
的循环并等待一个原子标志来终止循环会容易得多。
std::thread flushing_thread;
std::atomic<bool> terminate_flushing_thread{ false };
void init_flushing()
{
assert(!flushing_thread.joinable());
flushing_thread = std::thread([]()
{
while (!terminate_flushing_thread.load(std::memory_order_relaxed))
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
logging::core::get()->flush();
}
});
}
void stop_flushing()
{
if (flushing_thread.joinable())
{
terminate_flushing_thread.store(true, std::memory_order_relaxed);
flushing_thread.join();
}
}