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 使用相关推荐

  1. Go的日志模块glog调研笔记

    glog简介 glog是著名的google开源C++日志库glog(https://github.com/google/glog)的golang版本,glog是一个轻量级的日志库,上手简单不需要配置文 ...

  2. GoogleLog(GLog)源码分析

    GLog是Google开发的一套日志输出框架.由于其具有功能强大.方便使用等特性,它被众多开源项目使用.本文将通过分析其源码,解析Glog实现的过程. 该框架的源码在https://github.co ...

  3. 【C++】google glog详解

    0.简介 glog是google的日志管理系统,配合gflags库,通过命令行参数管理日志. 源码下载:https://github.com/google/glog ubuntu安装: sudo ap ...

  4. Google Glog使用

    Glog是Google的一个C++开源日志系统,轻巧灵活,入门简单,而且功能也比较完善. 安装 以下是官方的安装方法 git clone https://github.com/google/glog. ...

  5. 在windows下基于visual studio2017和CMake的安装Google glog

    这里简单记录安装google glog在windows下基于visual studio2017的安装过程. 下载 https://github.com/google/glog 使用cmake编译,编译 ...

  6. 2017年4月25日(日志库glog)

    原博客:http://www.cnblogs.com/kuliuheng/p/5046101.html 使用文档说明:http://www.yeolar.com/note/2014/12/20/glo ...

  7. GLog 初始化说明

    #include <iostream> #include <glog/logging.h>int main(int argc, char* argv[]) {google::I ...

  8. glog日志库使用笔记

    日志能方便地诊断程序原因.统计程序运行数据,是大型软件系统必不可少的组件之一.glog 是google的开源日志系统,相比较log4系列的日志系统,它更加轻巧灵活. 在Github上下载glog,解压 ...

  9. 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 ...

  10. failed to open log file_C++中glog源码剖析以及如何设计一个高效 log模块

    每个开发者编程中都会记录log信息,多数人都会使用log第三方库,log库使用起来很方便,但我们也需要了解log系统的原理,这里以glog为例进行分析. 开始 这里不会介绍glog中是如何控制INFO ...

最新文章

  1. Asp.NET中常用的一些优化性能的方法
  2. cnn识别mnist、Fashion-MNIST(pytorch)
  3. Dapper.NET——轻量ORM
  4. 10 PP配置-生产主数据-工作中心相关-定义工作中心公式
  5. redis2.2.8版本的安装详情
  6. linux shell read line,【Linux shell】while read line
  7. 热议|上海交大等6所“双一流”明确,博士生毕业,不再要求发表论文!
  8. IS-IS数据包--包头结构
  9. 删除python读取的txt每一行尾部的\n
  10. python网络编程学习笔记(5):socket的一些补充
  11. Linux 常用快捷键大全
  12. 8uftp连接服务器设置
  13. linux ls 配色方案,Terminal 配色方案
  14. raise notice oracle,openGauss 循序渐进:通过 raise notice 模拟 Oracle 的 DBMS_OUTPUT
  15. 三点共线,向量计算其中一点坐标
  16. SVN的正确使用方法以及疑难问题的处理(持续更新与补充)
  17. 如何解决“被调用的对象已与其客户端断开连接“
  18. 视频播放--自动播放
  19. 青龙面板-花花阅读6.25 最新修复版
  20. 自学整理之HTML5常用标签和知识——小白篇

热门文章

  1. 普洱熟茶如何从茶汤色泽中看出品质?
  2. python 如何利用Metpy计算水汽通量散度
  3. 【线段树】几次比赛里面用到的线段树+
  4. 计算机桌面运维论文,桌面运维Helpdesk常用英语词.docx
  5. 利用python爬取58同城简历数据_利用python爬取58同城简历数据-Go语言中文社区
  6. 11.18随堂测验:学习对象
  7. 转栅格后的nodata怎么调色_新手开卤菜店,第一锅新卤水如何制作?看看老师傅是怎么做的!...
  8. 大前端:分享21个经典的移动端 开源项目
  9. 端粒效应《The Telemere Effect》程序员的养生指南(三)身心与生活
  10. Android之一像素保活