【问题标题】:logging with glog is not working properly使用 glog 记录无法正常工作
【发布时间】:2016-02-23 08:09:47
【问题描述】:

当我使用时,我正在使用 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";

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

【问题讨论】:

  • INFO 流可能需要刷新。你试过LOG(INFO).flush()之类的吗?
  • @muXXmit2X 是的,我试过了,但问题是一样的,它会在我停止程序执行后将所有内容写入日志文件。我在 proxygen 库中使用它
  • 当您登录到 stderr 而不是日志文件时,是否也会发生这种情况?
  • @muXXmit2X 不,它只使用日志文件将所有内容完美地记录到控制台,这个问题就在那里
  • @muXXmit2X 我在某个地方找到了使用 google::LogMessage::Flush() 但是当我使用它时出现此错误:cannot call member function ‘void google::LogMessage::Flush()’ without object google::LogMessage::Flush();

标签: c++ glog


【解决方案1】:

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

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


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

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

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

【讨论】:

  • 我不想将两个严重级别记录到一个文件中。我想在一个文件中多次使用一个严重级别,例如:LOG(INFO) &lt;&lt;"111111111111111"; LOG(INFO) &lt;&lt;"222222222222222"; LOG(INFO) &lt;&lt;"333333333333333"; LOG(INFO) &lt;&lt;"444444444444444";
  • 我编辑了答案以满足您的需求。我希望它有所帮助。
  • 非常感谢,太棒了!
【解决方案2】:

这是因为glog 默认缓冲INFO 日志。缓冲由标志FLAG_logbuflevel控制,其默认值为0,即所有严重性

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

other answer 提出了一个有趣的想法,即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

因此,默认情况下,即使在 LogMessage 的 dtor 中有 Flush 调用,也不会将数据实际刷新到磁盘

【讨论】:

    【解决方案3】:

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

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

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

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

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

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

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

    【讨论】:

    • 这是正确的。析构函数中Flush 的存在并不能保证数据的实际刷新,因为它以标志FLAG_logbuflevel 为条件。看我的回答
    猜你喜欢
    • 2014-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-02
    相关资源
    最近更新 更多