使用 glog 记录无法正常工作
logging with glog is not working properly
我在使用时使用 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";
**非常感谢对此行为的任何帮助**
问题很简单。默认情况下,glog 为每个严重性使用一个日志文件,以防止两个流打开同一个文件。如果您通过不同的流在 c++
中打开同一个文件,其中一个流(第一个打开文件的流)将优先写入文件。当第一个流关闭时,另一个只能开始写入该文件。
您要么必须为每种严重性声明不同的日志文件,要么将所有日志消息放在一个文件中,您只需编写自己的小型日志库即可。
似乎特别需要使用 google::FlushLogFiles(google::INFO)
刷新 INFO 流。要在您要记录的每个信息之后执行此操作,我会为自己定义一个宏来调用刷新函数,如下所示:
#define log(severity, msg) LOG(severity) << msg; google::FlushLogFiles(google::severity);
这确保流将被刷新并且您的所有消息将出现在日志文件中
虽然上面的答案被接受并且可能有助于解决问题,但我不确定这是正确的方法,甚至是对问题的正确解释。
如果你查看 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)
。
这是因为 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
我之前讲过。
因此,默认情况下,即使 LogMessage
的 dtor 中有 Flush
调用,也不会实际将数据刷新到磁盘
我在使用时使用 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";
**非常感谢对此行为的任何帮助**
问题很简单。默认情况下,glog 为每个严重性使用一个日志文件,以防止两个流打开同一个文件。如果您通过不同的流在 c++
中打开同一个文件,其中一个流(第一个打开文件的流)将优先写入文件。当第一个流关闭时,另一个只能开始写入该文件。
您要么必须为每种严重性声明不同的日志文件,要么将所有日志消息放在一个文件中,您只需编写自己的小型日志库即可。
似乎特别需要使用 google::FlushLogFiles(google::INFO)
刷新 INFO 流。要在您要记录的每个信息之后执行此操作,我会为自己定义一个宏来调用刷新函数,如下所示:
#define log(severity, msg) LOG(severity) << msg; google::FlushLogFiles(google::severity);
这确保流将被刷新并且您的所有消息将出现在日志文件中
虽然上面的答案被接受并且可能有助于解决问题,但我不确定这是正确的方法,甚至是对问题的正确解释。
如果你查看 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)
。
这是因为 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
我之前讲过。
因此,默认情况下,即使 LogMessage
Flush
调用,也不会实际将数据刷新到磁盘