4

当我使用时,我使用 glog 进行日志记录:

LOG(INFO) << "something";

它按预期工作,但是当我使用如下所示的多个日志时,它不会记录,直到程序停止。当程序停止时,它将按预期记录所有内容。

LOG(INFO) <<"111111111111111";
LOG(INFO) <<"222222222222222";
LOG(INFO) <<"333333333333333";
LOG(INFO) <<"444444444444444";

但是这里令人困惑的是,当我多次使用 LOG(WARNING) 时,它工作得很好,即,即使程序正在运行,它也会记录所有内容,这与前一种情况不同,即在程序停止时记录所有内容。

LOG(WARNING) <<"111111111111111";
LOG(WARNING) <<"222222222222222";
LOG(WARNING) <<"333333333333333";
LOG(WARNING) <<"444444444444444";

**非常感谢对此行为的任何帮助**

4

3 回答 3

7

问题相当简单。glog 默认为每个严重性使用一个日志文件,以防止两个流打开同一个文件。如果您通过不同的流打开同一个文件,c++其中一个(第一个打开文件的)将优先写入文件。当第一个流关闭时,另一个只能开始写入该文件。

您要么必须为每种严重性声明不同的日志文件,要么将所有日志消息放在一个文件中,您可以简单地编写自己的小日志库。


似乎尤其是 INFO 流需要使用google::FlushLogFiles(google::INFO). 为此,在您要记录的每个信息之后,我会为自己定义一个宏来调用刷新函数,如下所示:

#define log(severity, msg) LOG(severity) << msg; google::FlushLogFiles(google::severity); 

这确保了流将被刷新,并且您的所有消息都将出现在日志文件中

于 2016-02-23T08:51:54.713 回答
7

这是因为默认情况下会glog缓冲INFO日志。缓冲由FLAG_logbuflevel默认值为 0 的标志控制,也就是说所有严重性 <= 该值都将被缓冲。

接受的答案有效,因为google::FlushLogFiles(min_severity)强制刷新所有日志> = min_severity,但在生产代码库中定义我们的自定义宏可能不可行。因此,防止INFO日志缓冲的最简单解决方案是设置FLAG_logbuflevel-1

另一个答案提出了一个有趣的想法,LogMessage::~LogMessage()它需要调用Flush(),因此不需要接受答案中建议的显式刷新。这是不正确的,因为 dtor 中的调用Flush()是有条件的。这是调用堆栈-

LogMessage::~LogMessage()
|__LogMessage::Flush()
   |__(LogMessage::*send_method_)() == LogMessage::SendToLog()
       |__LogDestination::LogToAllLogfiles()
          |__LogDestination::MaybeLogToLogfile()
             |__Logger::Write(should_flush = log_severity > FLAGS_logbuflevel )

正如您在调用堆栈的最后一帧中看到的那样,Write日志目标(文件)的实际值采用一个布尔值,该布尔值should_flush取决于FLAGS_logbuflevel我之前谈到的标志。

因此,默认情况下,即使Flush在 dtor 中调用了LogMessage

于 2020-04-14T17:03:30.290 回答
0

尽管上述答案已被接受并且可能有助于解决问题,但我不确定这是正确的方法,甚至是对问题的正确解释。

如果你查看 glog 的代码,你会发现:

#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()

所以在原始问题中, LOG(INFO) 将被定义为

#define COMPACT_GOOGLE_LOG_INFO google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO).stream()

这将创建一个临时流对象,并将日志记录内容写入该流对象。之后,LogMessage LogMessage::~LogMessage()将调用 的析构函数。在该析构函数内部,Flush()实际上将调用以将日志记录内容刷新到 I/O 设备。

也就是说,对于每LOG(INFO)一条语句,都会创建和销毁一个临时的流对象,并Flush()在销毁之前被调用。所以恕我直言,不需要额外的电话,google::LogMessage::Flush()甚至google::FlushLogFiles(google::INFO)不需要。

于 2019-05-09T06:42:50.283 回答