[转] GLOG 使用
0 下载及编译
从网络上搜索即可得到下载链接。然后编译(本人编译的是静态链接库libglog_static),编译过程中可能会报出如下错误。
(0)”min ” 不是std成员;
#include <algorithm>;
(1)函数snprintf已经被定义
可注释,或者将所有snprintf替换为其它名称如“glog_snprintf”(原因在于VS2015中已经集成C11,而C11中已经将该函数列入了标准的库函数);
(2)warning va_copy 宏重定义
修改文件port.h line117为
#undef va_copy
#defineva_copy(dst, src) (dst) = (src)
(3)一些编译中的错误可以尝试在port.h或者config.h这种系统配置文件中寻找解决办法;
1 集成测试
编译成功后会在glog-0.3.3/Debug下生成libglog_static.lib文件,供后续集成。同时还需要将glog-0.3.3\src\windows\glog下的所有文件拷贝到待测试工程中,如下图所示。
然后修改工程配置属性。如下所述。
(0)VC++目录,修改“包含目录”和“库目录”,分别添加GLOG头文件所在目录和生成的静态库拷贝所在目录;如下图所示。
(1)在“C/C++ 预处理器”->“预处理定义”中添加_CONSOLE宏和_STL_DEBUG宏和GOOGLE_GLOG_DLL_DECL=宏;如下图所示
(2)“链接器”->“常规”中“附加库目录”添加静态库所在目录,如下图所示。
(3)“链接器”->“输入”中“附加依赖项”添加libglog_static.lib;如下图所示。
(4)最后正常编写测试使用程序即可。
3 说明(转)
(0)严重性分级
Glog可根据指定的严重性等级,通过LOG宏来选择性记录日志。默认的等级是按INFO,WARNING,ERROR,ERROR和FATAL四级。另外,FATAL等级的日志会在纪录以后终止程序的运行。
stderrthreshold参数,即用来控制输出至stderr的阈值设置,严重性级别在该值以上的除了写入日志以外,还会输出至stderr。默认值2,对应ERROR。各严重性等级分别为INFO-0,WARNING-1,ERROR-2和FATAL-3。如果是代码中,则是通过修改FLAG_stderrthreshold完成,而如果是命令行参数则需要添加前缀GLOG完成。
miloglevel参数,严重级级别在此阈值之上的才会被记录。
(1)VLOG
LOG是由google定义的日志等级信息,而vlog则是提供一个用户接口,由用户自定义日志等级。如下所示。
#define VLOG(verboselevel)LOG_IF(INFO, VLOG_IS_ON(verboselevel))
#define VLOG_IS_ON(verboselevel)(FLAGS_v>= (verboselevel))
由上可知,需要设置FLAGS_v控制阈值输出,而且它也是作为INFO级别输出。
v (int, default= 0 )对于使用“VLOG(m)”,m为int型,表达式进行输出日志信息,只有m值小于FLGAS_v的值时,才能输出。
(2)log_dir
FLAGS_log_dir,日志信息记录路径,默认为空。
如果没有指定信息输出到stderr则信息保存在“/tmp/<program name>.<hostname>.<username>.log.<severity level>.<date>.<time>.<pid>”文件中。
(3)有条件地记录日志信息
LOG_IF(INFO,num > 10) << “num larger than 10”。表示num大于10,才会输出日志。
LOG_EVERY_N(INFO,10)<<”aaa”。表示在该语句执行的第1次,11次,21次执行的时候,才会记录日志信息。
LOG_IF_EVERY_N(INFO,condition, times),当condition满足且被执行times之后才会执行。即上述两者的结合。
LOG_FIRST_N(INFO,20),语句执行20次以后记录的日志信息。
(4)有条件地终止程序
CHECK,CHECK_EQ,当条件不满足时,会直接终止退出。
(5)debug日志
GLOG考虑到了在调试过程中产生的日志,所以提供宏只在debug模式生效。宏有:DLOG,DLOG_IF,DLOG_EVERY_N,用法和意义与GLOG普通日志相同。
(6)去除日志信息
日志信息的字符串会占用比较大的内存空间,另外还带来隐私泄露的问题。glog提供了GOOGLE_STRIP_LOG宏在编译时候去除日志的字符串信息。
(7)日志风格
Glog提供了与LOG*和CHECK宏作用等价的PLOG()、PLOG_IF() 和PCHECK()宏,不同的是,后者在记录日志信息的时候,会将errno的状态及其描述附加到日志描述中。
如:PCHECK(write(1, NULL, 2) >= 0)<< "Write NULL failed";
当条件不成立时,会输出日志信息:
F0825 185142 test.cc:22] Check failed:write(1, NULL, 2) >= 0 Write NULL failed: Bad address [14]
4 GLOG调用追踪
glog一般使用VLOG(num)或者LOG(severity)两种形式的宏进行输出。就以LOG(severity)为例进行说明,VLOG(num)系列应该类似了。比如要输出一条日志信息,如
LOG(ERROR) << "helloworld"
LOG宏的定义是:
#define LOG(severity)COMPACT_GOOGLE_LOG_ ## severity.stream()
可以看到它将根据具体的名字展开为另一个宏,因为上面选择的输出级别是ERROR,所以展开的名称为COMPACT_GOOGLE_LOG_ERROR。
继续跟进这个宏的定义:
#define COMPACT_GOOGLE_LOG_ERROR google::LogMessage(\
__FILE__, __LINE__, google::GLOG_ERROR)
可以看到这个宏的作用其实就是创建了一个名为LogMessage的类,构造函数的输入参数包括了:文件名,行号,日志级别。继续跟进LogMessage的构造函数:
LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
: allocated_(NULL){
Init(file, line, severity,&LogMessage::SendToLog);
}
这一次,多了一个参数,名为SendToLog的类成员函数指针。这里需要说明的是,其实这个函数指针参数的目的是进行日志输出的操作,但是是可以配置的,因为LogMessage还有另外重载的构造函数其中有这个参数的,只是这里说明的是最简单的情况,所以就考虑了这个函数指针默认为SendToLog的情况,从名字可以猜测到,该函数的作用是向磁盘进行日志输出操作,另外glog中还可以向标准输出进行输出,如果有必要,应该还可以通过网络对某个地址端口进行输出–这些情况我都没有进一步跟进了,只想说明该函数指针的作用是向不同的介质输出日志,而使用函数指针作为参数就是为了让这个行为可以配置。
继续往下走,看看LogMessage::Init函数做的事情。这里不贴代码了,有兴趣的可以自己跟进看看。简单来说做的事情是:初始化日志输入的流缓冲区,初始化该日志的时间,格式,找到日志打印的文件名等。
好了,至此,一个完整的LogMessage就创建完毕。可以看到,在glog中,任何的一条日志信息,最终都会对应到一个新创建的LogMessage对象。
上面的日志输出流程,其实还没有完,因为还要进行流输入操作呢,就是输入“helloworld”字符串。没错,退回头看看LOG宏的定义。
#define LOG(severity)COMPACT_GOOGLE_LOG_ ## severity.stream()
如果说,前面的COMPACT_GOOGLE_LOG_ ## severity创建了一个LogMessage类对象,那么其实这个宏最终的结果是返回这个LogMessage类对象的成员stream(),在提到LogMessage::Init函数的时候就提到过,该函数初始化了流输入缓冲区。来看LogMessage类中该流输入类的定义:
#ifdef _MSC_VER
# pragma warning(disable: 4275)
#endif
class GOOGLE_GLOG_DLL_DECL LogStream :public std::ostream {
#ifdef _MSC_VER
# pragma warning(default:4275)
#endif
public:
LogStream(char *buf, int len, int ctr)
: std::ostream(NULL),
streambuf_(buf, len),
ctr_(ctr),
self_(this){
rdbuf(&streambuf_);
}
int ctr()const { return ctr_;}
void set_ctr(int ctr){ ctr_ = ctr;}
LogStream* self()const { return self_;}
// Legacy std::streambuf methods.
size_t pcount()const { return streambuf_.pcount();}
char* pbase()const { return streambuf_.pbase();}
char* str()const { return pbase();}
private:
base_logging::LogStreamBuf streambuf_;
int ctr_; //Counter hack (for the LOG_EVERY_X() macro)
LogStream *self_; //Consistency check hack
};
其实很简单,从std::ostrstream中继承过来,构造函数中有一个缓冲区就好了。在LogMessage::Init类中,定义该缓冲区的大小为:
data_->buf_= new char[kMaxLogMessageLen +1]
其中
const size_t LogMessage::kMaxLogMessageLen =30000;
这里可以看到glog限制的一条日志长度大小为30000 byte。
好了,到此为止,流输入也有了,尽管往里面写数据就好。那么什么时候进行输出呢?glog采用的是在这个创建的临时LogMessage对象(说它是”临时对象”是因为它是匿名的,因此不会保存,创建了就会被释放)被释放的时候,在析构函数中做输出操作:
LogMessage::~LogMessage(){
Flush();
delete allocated_;
}
Flush函数不详细分析了,主要做的事情就是将日志和之前得到的日期等进行格式化,最后调用注册的输出日志用的函数指针进行输出操作。到此为止,一条glog日志就输出完成了。
再回头看看,实际上这里应该还有一些东西是需要全局使用的,比如有多条日志同时向一个文件进行输出的时候,需要对文件进行加锁,还比如要更新一些统计的数据,如每个级别的日志都有多少条了。这些在glog中都是全局变量:
static Mutex log_mutex;
// Number of messages sent at eachseverity. Under log_mutex.
int64LogMessage::num_messages_[NUM_SEVERITIES] = {0, 0, 0, 0};
当然,这里的num_messages_数组准确的说是LogMessage的静态成员变量,但是大体理解为全局变量也不为错,因为这个数据全局都只有一份了。
5 常用API
0)void google::InitGoogleLogging(const char* argv0)
初始化glog库,参数是第一个命令行参数即程序名。
1)void google::ShutdownGoogleLogging()
关闭glog库。
3)void google::FlushLogFiles(LoSeveritymin_severity)
[Thread - safe]指定级别以上的所有日志消息都立即写入到日志文件中。
4)void google::FlushLogFilesUnsafe(LogSeverity min_severity)
非线程安全的输出指定级别以上的日志消息,用于灾难性程序问题时输出必要的日志消息。
5)void google::SetLogDestination(LogSeverity severity, const char* basefilename)
[Thread - safe]设置指定级别的日志输出的日志文件,如果basefilename为""则表示该级别日志不输出。
6)void google::SetLogSymlink(LogSeverity severity, const char* symlinkbasename)
[Thread - safe]设置置顶级别的日志文件的软连接,symlikbasename为空表示不设置软连接。如果不调用该函数,系统默认连接名称是程序名。
7)void google::AddLogSink(LogSink *destination)
void google::RemoveLogSink(LogSink *destination)
[Thread - safe]添加和删除日志输出渠道。
8)void google::SetLogFilenameExtension(const char* filename_extension)
[Thread - safe]为所有日志文件添加文件扩展名,特别用于SetLogDestination()设置的日志文件。通常做法是将监听的端口号作为日志文件扩展名。
9)void google::SetStderrLogging(LogSeverity min_severity)
[Thread - safe]确定除了输出到日志文件同时还输出到STDERR的日志最小级别。
10)void google::LogToStderr()
[Thread - safe]设置只只将日志输出到STDERR而不输出到日志文件。
11)void google::SetEmailLogging(LogSeverity min_severity, const char* address)
[Thread - safe]设置发送邮件的日志最小级别。
12)bool google::SendEmail(const char *dest, const char *subject, const char *body)
[Thread - safe]发送邮件。
13)const std::vector& google::GetLoggingDirectories()
获取日志输出目录集合。
14)void google::InstallFailureSignalHandler()
信号处理函数,处理的主要信号有SIGSEGV / SIGILL / SIGFPE / SIGBRT / SIGBUS/SIGTERM。
15)void google::InstallFailureWriter(void(*writer)(const char *data, int size))
设置系统崩溃时的输出函数,data数据不一定是以'\0'结尾。
16)void google::InstallFailureFunction(void(*fail_func)())
设置LOG(FATAL)在输出日志消息后调用的函。
[转] GLOG 使用相关推荐
- Go的日志模块glog调研笔记
glog简介 glog是著名的google开源C++日志库glog(https://github.com/google/glog)的golang版本,glog是一个轻量级的日志库,上手简单不需要配置文 ...
- GoogleLog(GLog)源码分析
GLog是Google开发的一套日志输出框架.由于其具有功能强大.方便使用等特性,它被众多开源项目使用.本文将通过分析其源码,解析Glog实现的过程. 该框架的源码在https://github.co ...
- 【C++】google glog详解
0.简介 glog是google的日志管理系统,配合gflags库,通过命令行参数管理日志. 源码下载:https://github.com/google/glog ubuntu安装: sudo ap ...
- Google Glog使用
Glog是Google的一个C++开源日志系统,轻巧灵活,入门简单,而且功能也比较完善. 安装 以下是官方的安装方法 git clone https://github.com/google/glog. ...
- 在windows下基于visual studio2017和CMake的安装Google glog
这里简单记录安装google glog在windows下基于visual studio2017的安装过程. 下载 https://github.com/google/glog 使用cmake编译,编译 ...
- 2017年4月25日(日志库glog)
原博客:http://www.cnblogs.com/kuliuheng/p/5046101.html 使用文档说明:http://www.yeolar.com/note/2014/12/20/glo ...
- GLog 初始化说明
#include <iostream> #include <glog/logging.h>int main(int argc, char* argv[]) {google::I ...
- glog日志库使用笔记
日志能方便地诊断程序原因.统计程序运行数据,是大型软件系统必不可少的组件之一.glog 是google的开源日志系统,相比较log4系列的日志系统,它更加轻巧灵活. 在Github上下载glog,解压 ...
- NuGet Error:Unable to find version ‘0.3.3.0‘ of package ‘glog.overlay-x64_v120_Release_dynamic‘.
问题: 使用VS2013生成caffe解决方案时,报错NuGet Error:Unable to find version '0.3.3.0' of package 'glog.overlay-x64 ...
- failed to open log file_C++中glog源码剖析以及如何设计一个高效 log模块
每个开发者编程中都会记录log信息,多数人都会使用log第三方库,log库使用起来很方便,但我们也需要了解log系统的原理,这里以glog为例进行分析. 开始 这里不会介绍glog中是如何控制INFO ...
最新文章
- Asp.NET中常用的一些优化性能的方法
- cnn识别mnist、Fashion-MNIST(pytorch)
- Dapper.NET——轻量ORM
- 10 PP配置-生产主数据-工作中心相关-定义工作中心公式
- redis2.2.8版本的安装详情
- linux shell read line,【Linux shell】while read line
- 热议|上海交大等6所“双一流”明确,博士生毕业,不再要求发表论文!
- IS-IS数据包--包头结构
- 删除python读取的txt每一行尾部的\n
- python网络编程学习笔记(5):socket的一些补充
- Linux 常用快捷键大全
- 8uftp连接服务器设置
- linux ls 配色方案,Terminal 配色方案
- raise notice oracle,openGauss 循序渐进:通过 raise notice 模拟 Oracle 的 DBMS_OUTPUT
- 三点共线,向量计算其中一点坐标
- SVN的正确使用方法以及疑难问题的处理(持续更新与补充)
- 如何解决“被调用的对象已与其客户端断开连接“
- 视频播放--自动播放
- 青龙面板-花花阅读6.25 最新修复版
- 自学整理之HTML5常用标签和知识——小白篇
热门文章
- 普洱熟茶如何从茶汤色泽中看出品质?
- python 如何利用Metpy计算水汽通量散度
- 【线段树】几次比赛里面用到的线段树+
- 计算机桌面运维论文,桌面运维Helpdesk常用英语词.docx
- 利用python爬取58同城简历数据_利用python爬取58同城简历数据-Go语言中文社区
- 11.18随堂测验:学习对象
- 转栅格后的nodata怎么调色_新手开卤菜店,第一锅新卤水如何制作?看看老师傅是怎么做的!...
- 大前端:分享21个经典的移动端 开源项目
- 端粒效应《The Telemere Effect》程序员的养生指南(三)身心与生活
- Android之一像素保活