如何手动冲洗升压日志?

Dav*_*hun 4 c++ boost flush boost-logging boost-log

我正在使用Boost.Log中的boost 1.54.0来查看它是否适用于我的应用程序.一般来说,我没有缓冲问题,所以我不打算打开auto_flush或其他任何东西......但是我注意到在我调用之前记录的消息fork()是重复的,我想知道它是否是因为它们是缓冲的,所以在复制过程映像时缓冲区会被复制,然后两个进程最终将它们的缓冲区副本写入日志文件......

所以基本上,我只想在我打电话之前在日志上做一次手动刷新,fork()以确保没有消息仍然在内存中.换句话说,我正在寻找一个类似于fflush(),.flush(),<< flush等我可以在升压日志使用.

我确实尝试使用<< flush日志,但我仍然得到重复的消息,所以我不是100%确定它是否正在刷新并且重复是由其他一些问题引起的,或者它是否以某种方式默默地忽略了<< flush...

编辑:

我环顾四周,发现升压日志不是叉安全的.所以我应该补充一点,我不是想在父进程和子进程中使用相同的日志.我有两个分叉场景 - 在一个,父母立即终止和孩子contineus(这应该是安全的),而在另一个,孩子应该打开自己的单独的日志文件,所以这应该是安全的...但我需要弄清楚如何关闭日志文件接收器,然后打开一个新文件(在不同的文件上).我想关闭水槽也可能是一种强制冲洗的方法......?

Dav*_*hun 5

好的......我不得不深入研究一下(但不是太多)增强代码,我找到了这个,这似乎有效:

当你调用add_file_log(strLogFilename)它返回一个shared_ptr<sink>地方sink是你的接收器(例如,类型shared_ptr< synchronous_sink< text_file_backend > >).如果您"手动"创建接收器,那么当然您也有一个指向它的指针......看起来接收器和后端都有一个.flush()方法.我不确定你是如何直接获得后端的副本来调用它的同花顺,但是接收器上的刷新似乎只是在其后端调用flush,这样就行了.这是我发现为我工作的一些示例代码:

shared_ptr< synchronous_sink< text_file_backend > > pLogSink = add_file_log(strLogFilaname);
BOOST_LOG_TRIVIAL(debug) << "Boost log!";

// other work goes here

BOOST_LOG_TRIVIAL(debug) << "About to fork...";
if (pLogSink)
  pLogSink->flush();
pid_t pid = fork();

if (pid < 0)
  // handle error
else if (pid > 0)
  exit(EXIT_SUCCESS); // parent terminates
assert(0 == pid); // child continues

BOOST_LOG_TRIVIAL(debug) << "Fork succeeded!";
Run Code Online (Sandbox Code Playgroud)

使用此方法,我现在只看到每条日志消息一次.当然,请记住关于将Boost.Log与fork()混合的警告... http://boost-log.sourceforge.net/libs/log/doc/html/log/rationale/fork_support.html

在我的例子中,它是安全的,因为父进程在分叉后立即退出而根本没有触及日志(在fork之后).因此,日志没有任何争用.

尽管有这些限制,我可以看到在少数情况下使用它:1)守护进程(这是我在这里尝试做的,实际上),2)fork-exec模式(使用Boost.Log 可以正常工作,根据上面的URL),或者3)子进程立即关闭文件接收器并为日志打开一个新的接收器,指向不同的文件(来自父进程正在使用的文件) - 我认为这第三种情况应该是安全的.


Paw*_*zur 5

甚至更简单的代码(使用琐碎的日志记录):

#include <boost/filesystem.hpp>
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/utility/setup/file.hpp>

namespace logging = boost::log;

void InitLogging() {
  boost::filesystem::path full_path(boost::filesystem::current_path());

  auto sink = logging::add_file_log("sample.log");
  BOOST_LOG_TRIVIAL(info) << "Log initialized.";
  BOOST_LOG_TRIVIAL(info) << "Working dir: " << full_path;
  sink->flush();
}

int main() {
  InitLogging();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

根据我的测试,冲洗是一种阻止方法。我仅在初始化期间使用它,因此如果发生错误,我知道执行在哪里。