google-glog安装使用

摘抄修改自: http://www.cnblogs.com/tianyajuanke/archive/2013/02/22/2921850.html , 感谢原作者无私分享。

官方英文文档:http://google-glog.googlecode.com/svn/trunk/doc/glog.html


1.简介

google 出的一个C++轻量级日志库,支持以下功能:

◆ 参数设置,以命令行参数的方式设置标志参数来控制日志记录行为;
◆ 严重性分级,根据日志严重性分级记录日志;
◆ 可有条件地记录日志信息;
◆ 条件中止程序。丰富的条件判定宏,可预设程序终止条件;
◆ 异常信号处理。程序异常情况,可自定义异常处理过程;
◆ 支持debug功能;
◆ 自定义日志信息;
◆ 线程安全日志记录方式;
◆ 系统级日志记录;
◆ google perror风格日志信息;
◆ 精简日志字符串信息

2.安装

tar -zxvf glog-0.3.3.tar.gz
cd glog-0.3.3
./configure
make
make install
ldconfig


3.简单 Demo

vim glog.test.cpp

#include <glog/logging.h>
int main(int argc,char* argv[])
{
    LOG(INFO) << "Hello,GLOG!";
}

g++ glog.test.cpp -lglog

执行时日志输出到 stderr.

 

4.错误级别

GLOG 有四个错误级别,枚举如下:

enum SeverityLevel
{
  google::INFO = 0,
  google::WARNING = 1,
  google::ERROR = 2,
  google::FATAL = 3,
};

 

5.Flags 设置:

在上面的简单 Demo 中,只能将日志输出到 stderr ,如果想将日志重定向到文件,需要:

google::InitGoogleLogging(argv[0]);
/*
GLOG代码
*/
google::ShutdownGoogleLogging();

则默认运行会将日志输出到 /tmp 目录下(格式为 "<program name>.<hostname>.<user name>.log.<severity level>.<date>.<time>.<pid>")

运行参数可以在代码里通过加上 FLAGS_ 前缀来设置,如:

下面列出的都是默认值:

FLAGS_logtostderr = false;              //是否将所有日志输出到stderr,而非文件
FLAGS_alsologtostderr = false;          //日志记录到文件的同时输出到strerr
FLAGS_colorlogtostderr = false;         //将彩色日志输出到stderr
FLAGS_drop_log_memory = true;           //日志写到文件的时候删除其在内存中的buf
FLAGS_alsologtoemail = "";              //日志记录到文件的同时发送邮件到指定邮件地址
FLAGS_log_prefix = true;                //每行log加前缀
FLAGS_minloglevel = google::INFO;       //日志最低记录等级
FLAGS_logbuflevel = google::INFO;       //缓存日志的最低等级 , -1表示不缓存,0表示只缓存google::INFO
FLAGS_logbufsecs = 30; //日志最多缓存的秒数
FLAGS_logemaillevel = 999;              //日志发送邮件的最低等级 , 0表示发送全部 , 3表示只发送google::FATAL
FLAGS_logmailer = "/bin/mail" ;         //邮件发送的用户
FLAGS_log_dir = "";                     //设置日志文件输出目录
FLAGS_log_link = "";                    //给日志目录的文件添加额外的链接
FLAGS_max_log_size = 1800;              //最大日志大小(MB), 如果设置为0将默认为1
FLAGS_stop_logging_if_full_disk = false;//磁盘满停止记录日志
FLAGS_log_backtrace_at = "";            //当记录"文件名:行号"的日志的时候触发一个backtrace
FLAGS_v = 0;                            //记录所有 VLOG(m)中 m <= 这个值的自定义log , 这个标签会被 FLAGS_vmodule 覆盖
FLAGS_vmodule = "";                     //分模块(文件)设置VLOG(m)日志信息的输出等级。命令格式为以逗号分开的“<module name>=<log level>”表达式组成。其中<module name>是“glob pattern”,支持通配符,<module name>不包括文件的扩展名(.h,.cc等)。

详细运行参数见 logging.cc 中的 DEFINE_ 开头的定义。

6.条件输出:

LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";   //当条件满足时输出日志
LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";  //google::COUNTER 记录该语句被执行次数,从1开始,在第一次运行输出日志之后,每隔 10 次再输出一次日志信息
LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER << "th big cookie";  //上述两者的结合,不过要注意,是先每隔 10 次去判断条件是否满足,如果是则输出日志;而不是当满足某条件的情况下,每隔 10 次输出一次日志信息。
LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";  //当此语句执行的前 20 次都输出日志,然后不再输出

演示代码如下:


#include <glog/logging.h>
int main(int argc,char* argv[])
{
    google::InitGoogleLogging(argv[0]);
    FLAGS_stderrthreshold=google::INFO;
    FLAGS_colorlogtostderr=true;
    for(int i = 1; i <= 100;i++)
    {
        LOG_IF(INFO,i==100)<<"LOG_IF(INFO,i==100)  google::COUNTER="<<google::COUNTER<<"  i="<<i;
        LOG_EVERY_N(INFO,10)<<"LOG_EVERY_N(INFO,10)  google::COUNTER="<<google::COUNTER<<"  i="<<i;
        LOG_IF_EVERY_N(WARNING,(i>50),10)<<"LOG_IF_EVERY_N(INFO,(i>50),10)  google::COUNTER="<<google::COUNTER<<"  i="<<i;
        LOG_FIRST_N(ERROR,5)<<"LOG_FIRST_N(INFO,5)  google::COUNTER="<<google::COUNTER<<"  i="<<i;
    }
    google::ShutdownGoogleLogging();
}

 输出结果如下:


I1210 13:23:20.059790  6322 test01.cpp:11] LOG_EVERY_N(INFO,10)  google::COUNTER=1  i=1
E1210 13:23:20.060670  6322 test01.cpp:13] LOG_FIRST_N(INFO,5)  google::COUNTER=1  i=1
E1210 13:23:20.061272  6322 test01.cpp:13] LOG_FIRST_N(INFO,5)  google::COUNTER=2  i=2
E1210 13:23:20.061337  6322 test01.cpp:13] LOG_FIRST_N(INFO,5)  google::COUNTER=3  i=3
E1210 13:23:20.061393  6322 test01.cpp:13] LOG_FIRST_N(INFO,5)  google::COUNTER=4  i=4
E1210 13:23:20.061450  6322 test01.cpp:13] LOG_FIRST_N(INFO,5)  google::COUNTER=5  i=5
I1210 13:23:20.061506  6322 test01.cpp:11] LOG_EVERY_N(INFO,10)  google::COUNTER=11  i=11
I1210 13:23:20.061529  6322 test01.cpp:11] LOG_EVERY_N(INFO,10)  google::COUNTER=21  i=21
I1210 13:23:20.061553  6322 test01.cpp:11] LOG_EVERY_N(INFO,10)  google::COUNTER=31  i=31
I1210 13:23:20.061575  6322 test01.cpp:11] LOG_EVERY_N(INFO,10)  google::COUNTER=41  i=41
I1210 13:23:20.061599  6322 test01.cpp:11] LOG_EVERY_N(INFO,10)  google::COUNTER=51  i=51
W1210 13:23:20.061621  6322 test01.cpp:12] LOG_IF_EVERY_N(INFO,(i>50),10)  google::COUNTER=51  i=51
I1210 13:23:20.061667  6322 test01.cpp:11] LOG_EVERY_N(INFO,10)  google::COUNTER=61  i=61
W1210 13:23:20.061691  6322 test01.cpp:12] LOG_IF_EVERY_N(INFO,(i>50),10)  google::COUNTER=61  i=61
I1210 13:23:20.061738  6322 test01.cpp:11] LOG_EVERY_N(INFO,10)  google::COUNTER=71  i=71
W1210 13:23:20.061761  6322 test01.cpp:12] LOG_IF_EVERY_N(INFO,(i>50),10)  google::COUNTER=71  i=71
I1210 13:23:20.061807  6322 test01.cpp:11] LOG_EVERY_N(INFO,10)  google::COUNTER=81  i=81
W1210 13:23:20.061831  6322 test01.cpp:12] LOG_IF_EVERY_N(INFO,(i>50),10)  google::COUNTER=81  i=81
I1210 13:23:20.061877  6322 test01.cpp:11] LOG_EVERY_N(INFO,10)  google::COUNTER=91  i=91
W1210 13:23:20.061902  6322 test01.cpp:12] LOG_IF_EVERY_N(INFO,(i>50),10)  google::COUNTER=91  i=91
I1210 13:23:20.062140  6322 test01.cpp:10] LOG_IF(INFO,i==100)  google::COUNTER=0  i=100

 

7.日志类型


LOG    //内置日志
VLOG    //自定义日志
DLOG    //DEBUG模式可输出的日志
DVLOG    //DEBUG模式可输出的自定义日志
SYSLOG    //系统日志,同时通过 syslog() 函数写入到 /var/log/message 文件
PLOG    //perror风格日志,设置errno状态并输出到日志中
RAW_LOG        //线程安全的日志,需要#include <glog/raw_logging.h>

前六种的日志使用方法完全相同(包括条件日志输出),而 RAW_LOG 使用方法比较特殊,且不支持条件日志输出,另外不接受  colorlogtostderr 的颜色设置。自定义日志也不接受 colorlogtostderr 的颜色设置,另外其日志严重级别也为自定义数字,且与默认日志严重级别相反,数字越小严重级别越高。如:


 1 #include <glog/logging.h>
 2 #include <glog/raw_logging.h>
 3 
 4 class GLogHelper
 5 {
 6 public:
 7     GLogHelper(char* program)
 8     {
 9         google::InitGoogleLogging(program);
10         FLAGS_stderrthreshold=google::INFO;
11         FLAGS_colorlogtostderr=true;
12         FLAGS_v = 3;
13     }
14     ~GLogHelper()
15     {
16         google::ShutdownGoogleLogging();
17     }
18 };
19 
20 int main(int argc,char* argv[])
21 {
22     GLogHelper gh(argv[0]);
23     LOG(ERROR)<<"LOG";
24     VLOG(3)<<"VLOG";
25     DLOG(ERROR)<<"DLOG";
26     DVLOG(3)<<"DVLOG";
27     SYSLOG(ERROR)<<"SYSLOG";
28     PLOG(ERROR)<<"PLOG";
29     RAW_LOG(ERROR,"RAW_LOG");
30 }

输出结果如下:


E1211 03:04:22.718116 13083 test01.cpp:23] LOG
I1211 03:04:22.719225 13083 test01.cpp:24] VLOG
E1211 03:04:22.719297 13083 test01.cpp:25] DLOG
I1211 03:04:22.719365 13083 test01.cpp:26] DVLOG
E1211 03:04:22.719391 13083 test01.cpp:27] SYSLOG
E1211 03:04:22.719650 13083 test01.cpp:28] PLOG: Success [0]
E1211 03:04:22.719650 13083 test01.cpp:29] RAW: RAW_LOG

 

8.CHECK 宏

当通过该宏指定的条件不成立的时候,程序会中止,并且记录对应的日志信息。功能类似于ASSERT,区别是 CHECK 宏不受 NDEBUG 约束,在 release 版中同样有效。

1.判定大小关系

         CHECK_EQ, CHECK_NE, CHECK_LE, CHECK_LT, CHECK_GE, CHECK_GT,使用这些宏需要注意类型一致,如果出现类型不一致的,可使用static_cast转换。

2.判定指针是否为空

         CHECK_NOTNULL(some_ptr),可用于对象初始化的时候。

3.判定字符串是否相等

     CHECK_STREQ, CHECK_STRNE, CHECK_STRCASEEQ, CHECK_STRCASENE 。可进行大小写敏感或不敏感字符串来分别判定。
4. 判定浮点是否相等或相近
     CHECK_DOUBLE_EQ ,CHECK_NEAR。这两个宏都需要指定一个可容忍的偏差上限。
当这些宏判定条件不成立时,glog会生成一个FATAL级别的日志信息,该信息包含比较的两个值和stream方式传入的字符串,然后中止程序。 此外,类似的,还有 PCHECK 和 RAW_CHECK 版本,使用方法类似,只是 RAW_CHECK 使用方法特殊,形如 RAW_CHECK(i<3,"RAW_CHECK");

 

9.core dumped 

通过 google::InstallFailureSignalHandler(); 即可注册,将 core dumped 信息输出到 stderr,如:


#include <glog/logging.h>
#include <string>
#include <fstream>

//将信息输出到单独的文件和 LOG(ERROR)
void SignalHandle(const char* data, int size)
{
    std::ofstream fs("glog_dump.log",std::ios::app);
    std::string str = std::string(data,size);
    fs<<str;
    fs.close();
    LOG(ERROR)<<str;
}

class GLogHelper
{
public:
    GLogHelper(char* program)
    {
        google::InitGoogleLogging(program);
        FLAGS_colorlogtostderr=true;
        google::InstallFailureSignalHandler();
        //默认捕捉 SIGSEGV 信号信息输出会输出到 stderr,可以通过下面的方法自定义输出方式:
        google::InstallFailureWriter(&SignalHandle);
    }
    ~GLogHelper()
    {
        google::ShutdownGoogleLogging();
    }
};

void fun()
{
    int* pi = new int;
    delete pi;
    pi = 0;
    int j = *pi;
}

int main(int argc,char* argv[])
{
    GLogHelper gh(argv[0]);
    fun();
}

输出的错误报告如下,可定位错误于 fun() 函数内:

E1211 06:07:04.787719 15444 test01.cpp:11] *** Aborted at 1386742024 (unix time) try "date -d @1386742024" if you are using GNU date ***
E1211 06:07:04.789120 15444 test01.cpp:11] PC: @ 0x401227 fun()
E1211 06:07:04.789481 15444 test01.cpp:11] *** SIGSEGV (@0x0) received by PID 15444 (TID 0x7f03ce478720) from PID 0; stack trace: ***
E1211 06:07:04.791168 15444 test01.cpp:11] @ 0x7f03cd505960 (unknown)
E1211 06:07:04.791453 15444 test01.cpp:11] @ 0x401227 fun()
E1211 06:07:04.791712 15444 test01.cpp:11] @ 0x40125b main
E1211 06:07:04.792908 15444 test01.cpp:11] @ 0x7f03cd4f1cdd __libc_start_main
E1211 06:07:04.793227 15444 test01.cpp:11] @ 0x400fc9 (unknown)
段错误 (core dumped)

如果不使用  google::InstallFailureSignalHandler();  则只会输出 “段错误” 三个字,难于排查。

默认情况下,异常信息是输出到 stderr,通过InstallFailureWriter()可以改变输出目标。

10.日志文件说明

如果可执行文件名为 "test",则将日志输出到文件后,还会生成 test.ERROR,test.WARNING,test.INFO 三个链接文件,分别链接到对应级别的日志文件。如果日志输出超过 FLAGS_max_log_size 设置的大小,则会分为多个文件存储,链接文件就会指向其中最新的对应级别的日志文件。所以当日志文件较多时,查看链接文件来查看最新日志挺方便的。

11.支持debug功能
glog提供特定的宏只在debug模式下生效。以下分别对应LOG、LOG_IF、LOG_EVERY_N操作的专用宏。

   DLOG(INFO) << "Found cookies";

   DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";

   DLOG_EVERY_N(INFO, 10) << "Got the " << COUNTER << "th cookie";

12.自定义日志信息
        glog提供VLOG宏,让用户自定义分级信息,该分级与LOG宏对应的严重性分级是独立管理,在命令行参数设置中独立设置“v”或“vmodule”参数来控制,具体见“参数设置”部分标志说明。VLOG宏便于用户调试、查找完问题以后,屏蔽日志信息,减轻负担。具体使用如下:
  VLOG_IF(1, (size > 1024))<< "I'm printed when size is more than 1024 and when you run the ""program with --v=1 or more";
       上面的语句,只有在size>1024成立时且命令行参数v的值不小于1,才记录日志信息。
  VLOG_EVERY_N(1, 10) << "I'm printed every 10th occurrence, and when you run the program " "with --v=1 or more. Present occurence is " << COUNTER;
       上面的语句,只有在命令行参数v的值不小于1时,才会每执行10次记录一次日志信息。
  VLOG_IF_EVERY_N(1, (size > 1024), 10) << "I'm printed on every 10th occurence of case when size is more " " than 1024, when you run the program with --v=1 or more. "; "Present occurence is " << COUNTER;
  上面的语句,只有在命令行参数v的值不小于1时,若size>1024条件连续成立10次,记录一次日志信息。

13.线程安全日志记录

      glog提供了线程安全的日志记录方式。在<glog/raw_logging.h>文件中提供了相关的宏,如,RAW_CHECK,RAW_LOG等。这些宏的功能与CHECK,LOG等一致,除此以外支持线程安全,不需要为其分配任何内存和提供额外的锁(lock)机制。

14.系统级日志记录

      除了提供了普通的日志记录宏,还提供SYSLOG, SYSLOG_IF,和 SYSLOG_EVERY_N宏,这些宏将日志信息通过syslog()函数记录到系统日志。

15.peror风格日志记录

     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]

16.精简日志字符串信息

      日志信息的字符串会占用比较大的内存空间,另外还带来隐私泄露的问题。glog提供了GOOGLE_STRIP_LOG宏在编译时候去除日志的字符串信息。

17.windows平台使用注意

因为glog的严重性级别中使用了ERROR宏,与<windows.h>文件中冲突,可通过以下方式避免:
     a,在包含<windows.h>文件之前,定义宏WIN32_LEAN_AND_MEAN 或者NOGDI。
     b,在包含<windows.h>文件之后,undef掉ERROR定义。
     c, 导致冲突的ERROR标识符定义在文件“glog\log_severity.h”中,类型为const int,不过在里面还定义一个ERROR的字符串,所以在替换时要区别这两个标识符。此外Glog中的一些宏也需要小改,COMPACT_GOOGLE_LOG_ERROR需要改成COMPACT_GOOGLE_LOG_GERROR。

18.实用封装

GLogHelper.h 如下:

#include <glog/logging.h>
#include <glog/raw_logging.h>

//将信息输出到单独的文件和 LOG(ERROR)
void SignalHandle(const char* data, int size);

class GLogHelper
{
public:
    //GLOG配置:
    GLogHelper(char* program);
    //GLOG内存清理:
    ~GLogHelper();
};

GlogHelper.cpp 如下:


#include <stdlib.h>
#include "GLogHelper.h"

//配置输出日志的目录:
#define LOGDIR "log"
#define MKDIR "mkdir -p "LOGDIR

//将信息输出到单独的文件和 LOG(ERROR)
void SignalHandle(const char* data, int size)
{
    std::string str = std::string(data,size);
    /*
    std::ofstream fs("glog_dump.log",std::ios::app);
    fs<<str;
    fs.close();
    */
    LOG(ERROR)<<str;
    //也可以直接在这里发送邮件或短信通知,不过这个方法是被回调多次的(每次回调只输出一行错误信息,所以如上面的记录到文件,也需要>以追加模式方可),所以这里发邮件或短信不是很适合,不过倒是可以调用一个 SHELL 或 PYTHON 脚本,而此脚本会先 sleep 3秒左右,然后将错
误信息通过邮件或短信发送出去,这样就不需要监控脚本定时高频率执行,浪费效率了。
}

//GLOG配置:
GLogHelper::GLogHelper(char* program)
{
    system(MKDIR);
    google::InitGoogleLogging(program);

    google::SetStderrLogging(google::INFO); //设置级别高于 google::INFO 的日志同时输出到屏幕
    FLAGS_colorlogtostderr=true;    //设置输出到屏幕的日志显示相应颜色
    //google::SetLogDestination(google::ERROR,"log/error_");    //设置 google::ERROR 级别的日志存储路径和文件名前缀
    google::SetLogDestination(google::INFO,LOGDIR"/INFO_"); //设置 google::INFO 级别的日志存储路径和文件名前缀
    google::SetLogDestination(google::WARNING,LOGDIR"/WARNING_");   //设置 google::WARNING 级别的日志存储路径和文件名前缀
    google::SetLogDestination(google::ERROR,LOGDIR"/ERROR_");   //设置 google::ERROR 级别的日志存储路径和文件名前缀
    FLAGS_logbufsecs =0;        //缓冲日志输出,默认为30秒,此处改为立即输出
    FLAGS_max_log_size =100;  //最大日志大小为 100MB
    FLAGS_stop_logging_if_full_disk = true;     //当磁盘被写满时,停止日志输出
    google::SetLogFilenameExtension("91_");     //设置文件名扩展,如平台?或其它需要区分的信息
    google::InstallFailureSignalHandler();      //捕捉 core dumped
    google::InstallFailureWriter(&SignalHandle);    //默认捕捉 SIGSEGV 信号信息输出会输出到 stderr,可以通过下面的方法自定义输出>方式:
}
//GLOG内存清理:
GLogHelper::~GLogHelper()
{
    google::ShutdownGoogleLogging();
}

测试文件 test.cpp 如下:


#include "GLogHelper.h"

int main(int argc,char* argv[])
{
    //要使用 GLOG ,只需要在 main 函数开始处添加这句即可
    GLogHelper gh(argv[0]);

    LOG(INFO)<<"INFO";
    LOG(ERROR)<<"ERROR";
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值