Google开源库之Glog库详解

转自https://zhuanlan.zhihu.com/p/26025722

简介

Google Glog是Google的一个开源库,用于实现应用级别的logging。 它提供了一系列类似于C++流风格的logging API,以及一些预定义的宏。它有点类似于C里面的assert,但是比它具备更丰富的输出信息以及使用灵活性。

基本用法

下面主要介绍glog的编译安装和使用方法。

编译安装

在Google的Glog项目主页上下载相关的源码,并编译安装。

./configure --preifx=mypath
make
make install

输出方式

将下面的代码保存为http://glogtest.cc文件,然后编译运行:

#include <iostream>

#include <glog/logging.h>

int main(int argc, char** argv) {
	FLAGS_alsologtostderr = 1;
	google::InitGoogleLogging(argv[0]);

	LOG(INFO) << "I am INFO!";
	LOG(WARNING) << "I am WARNING!";
	LOG(ERROR) << "I am ERROR!";
	LOG(FATAL) << "I am FATAL!";

	return 0;
}

在终端命令行进行编译运行,执行结果如下

gwu@baina-game02:~$ g++ glogtest.cc -o test -lglog
gwu@baina-game02:~$ ./test
I0327 11:17:12.963464  4355 glogtest.cc:9] I am INFO!
W0327 11:17:12.963878  4355 glogtest.cc:10] I am WARNING!
E0327 11:17:12.964049  4355 glogtest.cc:11] I am ERROR!
F0327 11:17:12.964191  4355 glogtest.cc:12] I am FATAL!
*** Check failure stack trace: ***
    @     0x7f7ad1a40c9d  google::LogMessage::Fail()
    @     0x7f7ad1a42b3d  google::LogMessage::SendToLog()
    @     0x7f7ad1a408b8  google::LogMessage::Flush()
    @     0x7f7ad1a4339e  google::LogMessageFatal::~LogMessageFatal()
    @           0x400d21  main
    @     0x7f7ad10f4830  (unknown)
    @           0x400b29  _start
Aborted (core dumped)

在glog中,默认提供了四种级别的log,分别是INFO、WARNING、ERROR、FATAL。对应的等级分别是0,1,2,3。最终的结果不仅会在屏幕终端显示出来,同时会将log日志写入到/tmp/<program name>.<hostname>.<user name>.log.<severity level>.<date>.<time>.<pid>这个文件中。将上面样例程序运行两次,在/tmp文件中可以看到如下新增文件:

test.baina-game02.gwu.log.ERROR.20170327-112500.4555
test.baina-game02.gwu.log.ERROR.20170327-113245.4763
test.baina-game02.gwu.log.FATAL.20170327-112500.4555
test.baina-game02.gwu.log.FATAL.20170327-113245.4763
test.baina-game02.gwu.log.INFO.20170327-112500.4555
test.baina-game02.gwu.log.INFO.20170327-113245.4763
test.baina-game02.gwu.log.WARNING.20170327-112500.4555
test.baina-game02.gwu.log.WARNING.20170327-113245.4763
test.ERROR
test.FATAL
test.INFO
test.WARNING

其中前面8个文件,分别记录了程序每次运行之后的日志信息,包含运行的程序名字,主机名称,用户名称,错误类型,记录时间等等信息。

后面的4个文件,记录了程序最近一次运行时的错误信息。

打开http://test.INFO文件和test.ERROR文件,可以看到如下内容:

// test.INFO文件的内容
Log file created at: 2017/03/27 11:35:32
Running on machine: baina-game02
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
I0327 11:35:32.576002  4849 glogtest.cc:9] I am INFO!
W0327 11:35:32.576388  4849 glogtest.cc:10] I am WARNING!
E0327 11:35:32.576573  4849 glogtest.cc:11] I am ERROR!
F0327 11:35:32.576731  4849 glogtest.cc:12] I am FATAL!

// test.ERROR文件的内容
Log file created at: 2017/03/27 11:35:32
Running on machine: baina-game02
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0327 11:35:32.576573  4849 glogtest.cc:11] I am ERROR!
F0327 11:35:32.576731  4849 glogtest.cc:12] I am FATAL!

可以看到INFO文件包含了各个等级的信息,而ERROR文件只包含了ERROR以及FATAL的信息,因此,等级比较靠前的log类型,会包含其后面的所有log信息,而不会包含其前面的log信息。

log的主要输出方式就是上面两种,一种是向屏幕终端输出log信息,另一种将log信息写入了磁盘文件。

输出信息的结构

log类型 log日期 log时间  进程PID          文件和行数                输出信息
IWEF   月份信息 时间信息 进程号   输出信息的文件名称和在文件中的行数   调试信息

设置标志

在golg中有如下常用的标志位,用来控制log的内容和存储路径等属性。

 

标志位            |           含义
-----------------------------------------------------------------------------
logtostderr      | 将log信息输出了stderr设备,而不将log信息写入到log文件。
----------------------------------------------------------------------------
stderrthreshold  | 将log信息输出到stderr,并且将log信息写入到log文件。minloglevel 设置最小的log等级,比如讲该标志位设置为2,那么只会显示和记 录ERROR以及FATAL这两种类型的log信息。
-----------------------------------------------------------------------------
log_dir       |设置log文件的存储路径
-----------------------------------------------------------------------------
v             |类似于minloglevel,用来设置最大的显示等级,需要结合VLOG宏来一起使用
-----------------------------------------------------------------------------
vmodule       | 标志位v的扩充,可以分别设置不同文件的log信息类别。

标志位的简要用法

在标志位前面加上FLAGS_字符串,即可以设置相应的标识,例如:

#include <iostream>

#include <glog/logging.h>

int main(int argc, char** argv) {
	FLAGS_logtostderr = 1;
	
	google::InitGoogleLogging(argv[0]);

	FLAGS_v = 2;

	VLOG(0) << " i am 0";
	VLOG(1) << " i am 1";
	VLOG(2) << " i am 2";
	VLOG(3) << " i am 3";

	return 0;
}

上述代码自定义了4个等级,并将显示的最大等级设置为2(注:此处设置等级来显示的信息和-minloglevel标志的作用正好相反),执行后的结果为:

gwu@baina-game02:~$ ./test
I0327 12:19:27.905977  6017 glogtest.cc:12]  i am 0
I0327 12:19:27.906128  6017 glogtest.cc:13]  i am 1
I0327 12:19:27.906143  6017 glogtest.cc:14]  i am 2

可以看到只有等级小于等于2的log才会显示出来。

其他的log标识符的用法和上面的类似,都是在标志位前面添加FLAGS_限定符,从而来设置相应的标识。

条件日志

有时候需要在满足一定条件下,才进行log操作,因此glog提供了如下了宏来满足实际需求。

  • LOG_IF(INFO, Condition expression) :只有当条件表达式成立时,才会输出log信息。
  • LOG_EVERY_N(INFO, interval) :当这条log语句被执行了1次,(1+interval)次,(1 + 2 * interval)次……才会输出和记录log信息。
  • LOG_IF_EVERY_N(INFO, Condition, interval):只有当满足条件表达式时,才按照interval间隔来输出和记录log信息。
  • LOG_FIRST(INFO, nums):记录前面nums次执行的log信息。

 

CHECK宏

和assert不同,它不受NDEBUG编译选项的约束,即使是在编译模式下,它仍然能够被执行。

  • CHECK(Condition expression):当条件表达式不成立的时候,会输出一个类型为FATAL的log信息
  • CHECK_NE(a, b):判断两个值是否不相等
  • CHECK_EQ(a, b):判断两个值是否相等
  • CHECK_NOTNULL:判断是否为空指针

实例应用

在阅读研究caffe源码的时候,会在里面看到大量的LOG宏和CHECK宏。并且很多时候,由于系统环境设置不正确,或者相应的配置文件参数错误,导致编译caffe失败,或者在运行caffe的时候失败,这个时候就可以根据在终端输出的log信息来定位到具体的文件,找到相应的错误,从而能够解决问题,例如有时候我们编译运行的时候,会出现如下错误:

F0327 14:56:35.274469  7500 common.cpp:158] Check failed: error == cudaSuccess (10 vs. 0)  invalid device ordinal
*** Check failure stack trace: ***
    @     0x7fcb0aaecc9d  google::LogMessage::Fail()
    @     0x7fcb0aaeeb3d  google::LogMessage::SendToLog()
    @     0x7fcb0aaec8b8  google::LogMessage::Flush()
    @     0x7fcb0aaef39e  google::LogMessageFatal::~LogMessageFatal()
    @     0x7fcb0b0ec62e  caffe::Caffe::SetDevice()
    @           0x40a1c8  device_query()
    @           0x406ef7  main
    @     0x7fcb09a7e830  (unknown)
    @           0x407949  _start
Aborted (core dumped)

从上面错误提示来看,出错的地方在common.cpp文件的158行,之后我们就可以定位到相关的文件:

156  // The call to cudaSetDevice must come before any calls to Get, which
157  // may perform initialization using the GPU.
158  CUDA_CHECK(cudaSetDevice(device_id));

结合文件中上下文的注释和代码,可以看到是GPU设备出现了问题,GPU编号从0,1,2...一直往后面编号,每个号码对应一块实际的GPU设备。而在测试的机器上面只有一块GPU,但是在配置文件里面./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt --gpu=1将GPU设置成了1,导致没法找到相应的设备,因此将1修改为0之后,就可以顺利解决这个问题。

当然,不止这一种错误情况,基本上在编译和运行caffe的时候,出现的所有错误情况,都可以通过终端中输出的LOG信息,定位到相应的文件和代码行数,然后结合上下文代码,可以很方便快速的找到程序出错的地方。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux上使用glog静态的步骤如下所示: 1. 首先,将glog的静态文件libglog.a和头文件src/glog复制到您的工程目录中。这些文件可以从引用中提供的资源中获取。 2. 接下来,创建一个名为main.cpp的文件,并将以下代码添加到该文件中: ``` /******************************************************** main.cpp ********************************************************/ #include <stdio.h> #include "glog/logging.h" int main() { // 初始化参数 FLAGS_logtostderr = false; // TRUE:标准输出,FALSE:文件输出 FLAGS_alsologtostderr = true; // 除了日志文件之外是否需要标准输出 FLAGS_colorlogtostderr = false; // 标准输出带颜色 FLAGS_logbufsecs = 0; // 设置可以缓冲日志的最大秒数,0指实时输出 FLAGS_max_log_size = 10; // 日志文件大小(单位:MB) FLAGS_stop_logging_if_full_disk = true; // 磁盘满时是否记录到磁盘 google::InitGoogleLogging("mqttserver"); google::SetLogDestination(google::GLOG_INFO, "./test"); LOG(INFO) << "this is log"; LOG(WARNING) << "this is warning"; LOG(ERROR) << "this is error"; google::ShutdownGoogleLogging(); } ``` 3. 编译和链接您的代码。您可以使用以下命令编译您的代码: ``` g++ main.cpp -o main -lglog ``` 这将生成一个名为main的可执行文件。 4. 运行您的程序。您可以使用以下命令运行您的程序: ``` ./main ``` 这将执行您的代码,并在"./test"目录下生成日志文件。 请注意,如果在编译过程中遇到任何错误,请根据引用中提供的信息检查头文件的路径是否正确,并确保已正确安装gflags和glog,如引用所述。 希望这可以帮助您在Linux上使用glog静态。如果您还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值