glog是一个轻量、稳定、开源的日志系统,详细见上一篇文章所述.这里主要介绍glog的使用.
D:\src\test\glog\src\windows\port.h(116): error C2375: 'snprintf': redefinition; different linkage
...
snprintf重复定义问题,其中一种解决办法:
--- a/src/windows/port.h
+++ b/src/windows/port.h
@@ -111,6 +111,7 @@ enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
* because they don't always NUL-terminate. :-( We also can't use the
* name vsnprintf, since windows defines that (but not snprintf (!)).
*/
+#define HAVE_SNPRINTF
#ifndef HAVE_SNPRINTF
编译成功,生成动态库(libglog.dll,libglog.lib),和静态库(libglog_static.lib).接下来以动态库的方式说明glog的使用.
代码添加:
//为了防止windows.h头文件中的ERROR与glog的ERROR重定义问题.这个宏必须在包含logging.h之前定义!
#define GLOG_NO_ABBREVIATED_SEVERITIES
#include
添加代码:
//import lib
#pragma comment(lib,"libglog.lib")
输出你的第一条LOG信息:
//programe name:"HelenXR_glog_program"
google::InitGoogleLogging("HelenXR_glog_program");
LOG(INFO) << "google log first info level message!";
//...... DoSomething
//Shutdown google's logging library.
google::ShutdownGoogleLogging();
此时如果你是的工程时控制台程序,你会发现”google log first info level message!”这句信息并没有输出到控制台中,它们去哪了?别急,这时候你要保持冷静!冷静!冷静!
如果没有设置日志存放的文件夹(下面我们会介绍如何保存到指定文件夹),它们会被存放到指定的路径(windows平台上会默认存放到$(LOCALAPPDATA)的Temp文件夹下,如:C:\Users\dell\AppData\Local\Temp,这个路径中的”dell”是计算机当前的用户名),你可以找到以特定格式命名的文件,格式为:
/tmp/<program name>.<hostname>.<user name>.log.<severity level>.<date>.<time>.<pid>
例如,我这里运行的是”HelenXR_glog_program.PC-2016-0510-9.dell.log.INFO.20170426-113842.14508”(这个文件名看起来很完整,实际使用还是不方便,花点时间可以修改,这里是我之前做的一个尝试,如果你有兴趣可以做的更好),打开这个文件我们可以看到如下信息:
Log file created at: 2017/04/26 11:38:42
Running on machine: PC-2016-0510-9
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
I0426 11:38:42.172986 14132 glog.cpp:20] google log first info level message!
上面介绍了日志输出的格式和我们输出的日志信息”google log first info level message!”.
glog拥有的4个日志等级:INFO,WARNING,ERROR,FATAL分别对应0,1,2,3.数值越大严重性越高,严重性高的日志不但会保存到自己的日志文件中,还会同时保存到所有比它严重性更低的日志文件中.例如:ERROR信息会被同时打印到INFO,WARNING,ERROR日志文件中,测试代码:
LOG(INFO) << "google log first info level message!";
LOG(WARNING) << "google log first warning level message!";
LOG(ERROR) << "google log first error level message!";
测试结果:
//HelenXR_glog_program.PC-2016-0510-9.dell.log.INFO.20170426-115025.8608
...(省略开头无关信息)
I0426 11:50:25.476213 9092 glog.cpp:20] google log first info level message!
W0426 11:50:25.477213 9092 glog.cpp:21] google log first warning level message!
E0426 11:50:25.477213 9092 glog.cpp:22] google log first error level message!
//HelenXR_glog_program.PC-2016-0510-9.dell.log.WARNING.20170426-115025.8608
...(省略开头无关信息)
W0426 11:50:25.477213 9092 glog.cpp:21] google log first warning level message!
E0426 11:50:25.477213 9092 glog.cpp:22] google log first error level message!
//HelenXR_glog_program.PC-2016-0510-9.dell.log.ERROR.20170426-115025.8608
...(省略开头无关信息)
E0426 11:50:25.477213 9092 glog.cpp:22] google log first error level message!
同时你注意下控制台的日志信息:
日志信息默认是写入对应的文件中的,这里console里打印出了ERROR等级的日志信息, 这是因为默认情况(stderrthreshold默认为2)下,ERROR和FATAL等级的信息会同时被输出到stderr上,当然你可以通过修改stderrthreshold值来改变.
你还可以通过在程序中修改全局变量FLAGS_*来配置.这些FLAG_*标识,你可以在”glog\logging.h”文件中查阅.
这里说一下比较常用的一个标志:FLAGS_log_dir,这个标志用来指定日志保存的路径,需要在”InitGoogleLogging”执行之前修改,代码修改:
//注意指定的路径,必须手动存在,你可以在运行前先创建好,否则生成不了日志文件,路径'\'要转义.
FLAGS_log_dir = "D:\\helenxr_glog_log_dir";
//programe name:"HelenXR_glog_program"
google::InitGoogleLogging("HelenXR_glog_program");
LOG(INFO) << "google log first info level message!";
LOG(WARNING) << "google log first warning level message!";
LOG(ERROR) << "google log first error level message!";
结果:
到这里Glog的基本日志输出功能已经完成.(文件名和文件路径看起来是不是很不爽?glog有源码可以修改,你可以修改到你满意的情况:-)),接下来的是glog的一些高级功能,这些功能前一篇文章有说明了,下面主要是代码演示.
条件型LOG包括:LOG_IF,LOG_EVERY_N,LOG_IF_EVERY_N,LOG_FIRST_N等.
代码如下:
//注意FLAGS_log_dir指定的路径,必须手动先创建好,否则生成不了日志文件,另外路径'\'要记得转义.
FLAGS_log_dir = "D:\\helenxr_glog_log_dir";
//programe name:"HelenXR_glog_program"
google::InitGoogleLogging("HelenXR_glog_program");
//LOG(INFO) << "google log first info level message!";
//LOG(WARNING) << "google log first warning level message!";
//LOG(ERROR) << "google log first error level message!";
//Conditional logging test
int test_number = 5;
//LOG_IF:条件满足时执行打印.
LOG_IF(INFO, test_number > 5) << "LOG_IF:test_number > 5";//no log this message
LOG_IF(INFO, test_number == 5) << "LOG_IF:test_number == 5";//log this message
//LOG_EVERY_N:此代码每执行过N此后,打印一次,注:第一次也会打印.
int loop_count = 0;
while (loop_count++ < 50 - 1) {
LOG_EVERY_N(INFO,10) << "LOG_EVERY_N:[" << loop_count << "]:"<<"loop in " << google::COUNTER << "th times.";
}
//LOG_IF_EVERY_N:条件满足情况下每N次,打印一次.注:第一次满足条件也会打印.
loop_count = 0;
while (loop_count++ < 50 - 1) {
LOG_IF_EVERY_N(INFO, (loop_count % 2 == 0),10) << "LOG_IF_EVERY_N:[" << loop_count << "]:" << "loop in " << google::COUNTER << "th times.";
}
//LOG_FIRST_N:此代码执行的前N此都打印,超过N次后不打印.
loop_count = 0;
while (loop_count++ < 50 - 1) {
LOG_FIRST_N(INFO,10) << "LOG_FIRST_N:[" << loop_count << "]:" << "loop in " << google::COUNTER << "th times.";
}
google::ShutdownGoogleLogging();
输出日志信息:
Log file created at: 2017/04/26 17:59:13
Running on machine: PC-2016-0510-9
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
I0426 17:59:13.759878 3016 glog.cpp:30] LOG_IF:test_number == 5
I0426 17:59:13.759878 3016 glog.cpp:34] LOG_EVERY_N:[1]:loop in 1th times.
I0426 17:59:13.759878 3016 glog.cpp:34] LOG_EVERY_N:[11]:loop in 11th times.
I0426 17:59:13.759878 3016 glog.cpp:34] LOG_EVERY_N:[21]:loop in 21th times.
I0426 17:59:13.759878 3016 glog.cpp:34] LOG_EVERY_N:[31]:loop in 31th times.
I0426 17:59:13.759878 3016 glog.cpp:34] LOG_EVERY_N:[41]:loop in 41th times.
I0426 17:59:13.759878 3016 glog.cpp:39] LOG_IF_EVERY_N:[2]:loop in 2th times.
I0426 17:59:13.759878 3016 glog.cpp:39] LOG_IF_EVERY_N:[22]:loop in 22th times.
I0426 17:59:13.759878 3016 glog.cpp:39] LOG_IF_EVERY_N:[42]:loop in 42th times.
I0426 17:59:13.759878 3016 glog.cpp:44] LOG_FIRST_N:[1]:loop in 1th times.
I0426 17:59:13.759878 3016 glog.cpp:44] LOG_FIRST_N:[2]:loop in 2th times.
I0426 17:59:13.759878 3016 glog.cpp:44] LOG_FIRST_N:[3]:loop in 3th times.
I0426 17:59:13.759878 3016 glog.cpp:44] LOG_FIRST_N:[4]:loop in 4th times.
I0426 17:59:13.759878 3016 glog.cpp:44] LOG_FIRST_N:[5]:loop in 5th times.
I0426 17:59:13.759878 3016 glog.cpp:44] LOG_FIRST_N:[6]:loop in 6th times.
I0426 17:59:13.759878 3016 glog.cpp:44] LOG_FIRST_N:[7]:loop in 7th times.
I0426 17:59:13.759878 3016 glog.cpp:44] LOG_FIRST_N:[8]:loop in 8th times.
I0426 17:59:13.759878 3016 glog.cpp:44] LOG_FIRST_N:[9]:loop in 9th times.
I0426 17:59:13.759878 3016 glog.cpp:44] LOG_FIRST_N:[10]:loop in 10th times.
glog提供了一些调试模式时输出,正常模式下不输出的宏,如DLOG,DLOG_IF,DLOG_EVERY_N等.这些宏只有在debug模式下才会输出日志,正常模式下不会输出日志,也不会拖慢应用程序的速度.
//Debug Mode support test
//如果你工程为Debug模式,下面信息会输出,如果是release模式,下面信息不会输出.
DLOG(INFO) << "DLOG:Debug Mode Message!";
glog提供VLOG宏来提供自定义打印等级的功能.
//verbose logging test
//你可以通过命令行"--v=n",来控制VLOG的输出,VLOG(x),x<=n的情况,VLOG会输出,否则不输出.v默认为0,所以默认情况下VLOG(-1),VLOG(0)能够输出.
VLOG(-1) << "VLOG(-1) message.";
VLOG(0) << "VLOG(0) message.";
VLOG(1) << "VLOG(1) message.";
VLOG(2) << "VLOG(2) message.";
VLOG(3) << "VLOG(3) message.";
输出的日志信息:
......(省略无关部分)
I0426 18:35:52.879662 15440 glog.cpp:57] VLOG(-1) message.
I0426 18:35:52.879662 15440 glog.cpp:58] VLOG(0) message.
还有VLOG_XXX等宏,来实现不同的功能,详见”glog\logging.h”.
CHECK宏的目标是让异常情况尽早被检测到,它的特点就是当所检测条件不满足时,应用程序会中止(类似C语言的assert),同时会以最高等级FATAL写入日志中.
//CHECK macros test
test_number = 1;
CHECK(test_number == 2) << " but test_number != 2";
上面的代码,会触发你的应用程序中止,并记录到日志中,FATAL日志信息如下:
Log file created at: 2017/04/26 18:20:24
Running on machine: PC-2016-0510-9
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
F0426 18:20:24.066536 11560 glog.cpp:53] Check failed: test_number == 2 but test_number != 2
还有很多CHECK_XXX宏可以使用,详细见”glog\logging.h”文件.