如何手动刷新boost日志? [英] How can I manually flush a boost log?

查看:241
本文介绍了如何手动刷新boost日志?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

基本上,我只想对日志进行一次手动刷新,一次只调用 fork(),以确保没有消息仍然在内存中。换句话说,我正在寻找类似 fflush() .flush()<<



我试过使用<< flush 与日志,但我仍然得到重复的消息,所以我不是100%确定它是否刷新,并且重复是由一些其他问题,或者如果它以某种方式静默忽略<< flush ...



我在环顾四周,发现boost日志不是fork-safe。因此,我应该补充一点,我不是试图在父进程和子进程中使用相同的日志。我有两个forking场景 - 在一个,父终止立即和孩子contineus(所以应该是安全的),在另一个,孩子应该打开自己的单独的日志文件,所以应该是安全的...但我需要找出如何关闭日志文件接收器,然后打开一个新的(在不同的文件)。我想关闭水槽也可能是一种强制冲洗的方法...?

解决方案

通过boost代码有点(但不是太多),我发现这,似乎工作:



当你调用 add_file_log strLogFilename)它返回一个 shared_ptr< sink> 其中 sink 例如 shared_ptr< synchronous_sink< text_file_backend>> )。如果你改为创建你的接收器手动,那么当然你有一个指向它的指针...似乎水槽和后端都有一个 .flush()方法。我不知道如何直接获取一个后端的副本来调用它的flush,但是在sink上的flush似乎只是调用其后端的flush,所以工作。下面是我发现为我工作的一些示例代码:

  shared_ptr<同步_ text_file_backend> > pLogSink = add_file_log(strLogFilaname); 
BOOST_LOG_TRIVIAL(debug)<< Boost log!;

//其他工作在这里

BOOST_LOG_TRIVIAL(debug)<< 关于叉...;
if(pLogSink)
pLogSink-> flush();
pid_t pid = fork();

if(pid <0)
//句柄错误
else if(pid> 0)
exit(EXIT_SUCCESS); // parent terminated
assert(0 == pid); // child continued

BOOST_LOG_TRIVIAL(debug)<< 叉成功了!

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



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



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


I'm playing with Boost.Log in boost 1.54.0 to see if it is a viable option for my application. In general, I don't have a problem with the buffering, so I'm not looking to turn on auto_flush or anything... but I noticed that messages that are logged before I call fork() are duplicated, and I'm wondering if it's because they are buffered, the buffer gets duplicated when the process image is copied, and then both processes eventually write their buffer copies to the log file...

So basically, I'd like to just do a manual flush on the log, one time only, immediately before I call fork() in order to be sure no messages are still sitting in memory. In other words, I'm looking for something akin to fflush(), .flush(), << flush, etc. that I can use on a boost log.

I did try using << flush with the log, but I still get the duplicated messages, so I'm not 100% sure whether it's flushing and the duplicates are caused by some other problem, or if it somehow silently ignores the << flush...

Edit:

I was looking around and found that boost log is not fork-safe. So I should add that I am not trying to use the same log in parent and child processes. I have two forking scenarios - in one, the parent terminates immediately and child contineus (so that should be safe), and in the other, the child should open its own separate log file, so that should be safe also... but I'd need to figure out how to close a log file sink and then open a new one (on a different file). I suppose closing the sink may also be a way to force a flush...?

解决方案

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.

这篇关于如何手动刷新boost日志?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆