1 日志清理
其实GLOG很长时间以来都没有日志清理功能。小白对此也很震惊,还特意去查了GLOG的提交记录。代码的提交记录显示,GLOG与日志清理有关的最初代码是2019年11月1日,而这个开源项目的起始时间可以追溯到2008年。也就是说,在长达11年的时间里,这个项目都没有清理日志的功能,甚至开发团队都没有进行相关代码的开发。
所以小白也在网上查询到一些文章,专门提到针对GLOG日志库使用时,由各路好手自己开发的日志清理工具。
如果小白开始使用这个库的时候还在它缺乏如此重要功能的时间段,那大概是会放弃它的吧。不过小白在体验过当前版本(即0.6.0)中的日志清理后,仍然还是有想要吐槽的冲动。
2 GLOG对日志清理功能的描述
在GLOG的ReadMe里,对日志清理功能的描述如下:
Automatically Remove Old Logs
To enable the log cleaner:
google::EnableLogCleaner(3); // keep your logs for 3 days
And then glog will check if there are overdue logs whenever a flush is performed. In this example, any log file from your project whose last modified time is greater than 3 days will be unlink()ed.
This feature can be disabled at any time (if it has been enabled)
google::DisableLogCleaner();
这里看上去非常简单,就是启用一下google::EnableLogCleaner()
函数,然后GLOG会在第一次刷新日志的时候把超期的日志清理掉,如果想禁用清理功能,就随时调用一下google::DisableLogCleaner()
函数。
唔……轻松愉快?!
事实并非如此。经过小白的测试,有以下几点问题值得吐槽,至少为什么明明有坑却不讲清楚:
google::FlushLogFiles()
前先写入内容才能清理掉日志;google::FlushLogFiles()
只能清理掉对应级别内的日志(而并不是如文档及代码注释所说可以清理掉该级别及以上的日志),比如google::FlushLogFiles(google::GLOG_INFO)
就只能清理GLOG_INFO
级别的日志。
其中第一点其实很不好:因为清理本身是一个动作,而写入是另一个动作,目前GLOG的做法是把清理这个动作绑定在写入之后进行,差评。
对于第二点,影响倒小一些:通常情况下Warning Error Fatal级别的日志比较少也比较小。但是清理功能的设计需求明明是按时间来筛选,怎么还需要按级别分别设置?
大家可能没意识到,把第一和第二点连起来看,意味着如果要删掉超期的Warning Error Fatal级别的日志,就需要到下一次写入同等级日志并刷新的时候!对于有强迫症的人来说这很难受,不太明白为什么是这样的设计思路,希望开发团队后期能做出点调整。
3 小白的示例
为了说明小白发现的两个问题,还是以上篇文章中控制小数点精度的代码为例:
#define GLOG_NO_ABBREVIATED_SEVERITIES
#include "glog/logging.h"
#include <iostream>
#include <iomanip>
#define WRITE_LOG(s) (LOG(INFO)<<s)
int main(int argc, char* argv[])
{
FLAGS_log_dir = "../Log/";
if (!google::IsGoogleLoggingInitialized())
{
google::InitGoogleLogging("Alg_Log");
}
google::EnableLogCleaner(1);
double pi = 3.141592653;
// Method1: C语言风格的小数点控制
char testInfo[128];
sprintf_s(testInfo, "pi = %.3lf", pi);
WRITE_LOG(testInfo); // 尝试注释掉写入动作1
google::FlushLogFiles(google::GLOG_INFO);
// Method2: C++语言风格的输出流小数点控制
LOG(INFO) << std::fixed << std::setprecision(9) << "pi = " << pi; // 尝试注释掉写入动作2
google::FlushLogFiles(google::GLOG_INFO);
if (google::IsGoogleLoggingInitialized())
{
google::ShutdownGoogleLogging();
}
return 0;
}
如果你和我一样,把写入的两句代码注释掉,你就会发现日志不会被清理掉。
如果你完整执行以上代码,你就会发现:
看到了吧,在没有刷新WARNING ERROR FATAL之前,就是不会清理掉这些等级的日志。
诚以为在这个方面GLOG还需要改进。不过从开发团队给GLOG赋予的版本号来看也确实远不是完全体。希望开发团队能及时发现这些不太合理的地方。