How can I manually flush a boost log?

谁都会走 提交于 2019-12-04 10:24:15

Okies... I had to dig through the boost code a bit (but not too much), and I found this, which seems to work:

When you call add_file_log(strLogFilename) it returns a shared_ptr<sink> where sink is your type of sink (e.g., shared_ptr< synchronous_sink< text_file_backend > >). If you instead create your sink "manually" then of course you have a pointer to it as well... It seems the sinks and backend both have a .flush() method. I'm not sure offhand how you directly get a copy of the backend to call its flush, but the flush on the sink seems to simply call the flush on its backend(s), so that works. Here's some example code of what I found to work for me:

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!";

Using this method, I now see each log message only once. Of course, bear in mind this warning about mixing Boost.Log with fork()... http://boost-log.sourceforge.net/libs/log/doc/html/log/rationale/fork_support.html

In my example, it's safe only because the parent process immediately exits after forking without touching the log at all (after the fork). Thus there isn't any contention for the log.

Despite the limitations, I can see using this in a few cases: 1) daemonizing a process (which is what I'm trying to do here, actually), 2) fork-exec pattern (which does work fine with Boost.Log, according to the above URL), or 3) child process immediately closes the file sink and opens a new sink for the log that points to a different file (from the one the parent process is using) - I think this third case should be safe.

Even simpler code (with trivial logging):

#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;
}

According to my tests flush is a blocking method. I use it only during initialization so if something wrong happen there I know where the execution was.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!