一、glog是什么:
Google glog是一个基于程序级记录日志信息的c++库,编程使用方式与c++的stream操作类似,例:
LOG(INFO) << "Found " << num << " cookies";
“LOG”宏为日志输出关键字,“INFO”为严重性程度。
主要支持功能:
1, 参数设置,以命令行参数的方式设置标志参数来控制日志记录行为;
2, 严重性分级,根据日志严重性分级记录日志;
3, 可有条件地记录日志信息;
4, 条件中止程序。丰富的条件判定宏,可预设程序终止条件;
5, 异常信号处理。程序异常情况,可自定义异常处理过程;
6, 支持debug功能。可只用于debug模式;
7, 自定义日志信息;
8, 线程安全日志记录方式;
9, 系统级日志记录;
10, google perror风格日志信息;
11, 精简日志字符串信息。
二、下载安装
1.下载:https://github.com/google/glog/releases
2.解压安装
tar zxvf glog-0.3.3.tar && cd glog-0.3.3 && ./configure && make && make install
三、glog的主要内容
1.日志等级
1)系统预定义等级:INFO(=0)<WARNING(=1)<ERROR(=2)<FATAL(=3)以上是简写形式,可通过宏关闭简写形式,其原始定义是有GLOG_前缀.
在windows中可能存在ERROR宏冲突的问题,通过宏监测会在编译器提示.
2)最严重级别是FATAL级别,对应DEBUG模式是DFATAL级别
2.1)在输出FATAL日志消息后,会终止程序运行.
2.2)DEBUG模式中,DFATAL级别对应ERROR--便于调试,而非 DEBUG模式则对应FATAL.
3)每个级别都对应有相应的日志文件,日志文件的位置及名称定义如下:
3.1)文件默认存放在临时文件中,windows下为 "C:\Users\user_name\AppData\Local\Temp",Linux是"/tmp"
3.2)文件名称: programname.hostname.user_name.log.severity_level.dat e.time.pid
3.3)Linux系还会为每个文件创建一个文件链接
4)日志输出采用如下规则:
4.1)每个级别的日志除了输出到对应日志文件中,还输出到每个低级别日志文件中
4.2)如一个ERROR日志,会输出到INFO,WARNING,ERROR三个日志文件中
4.3)默认,ERROR和FATAL消息除了输出到日志文件中之外,还会输出到标准错误中
2.DEBUG模式支持
1)DEBUG模式日志输出形式,增加前缀D表示DEBUG模式日志,如DLOG(log_severity),DLOG_IF(log_severity,condition)
2)采用DEBUG宏控制,非DEBUG模式中DEBUG日志不会编译进程序就避免了程序冗余
3.丰富的助手宏
功能类似assert断言,但不受DEBUG模式控制即非DEBUG模式也生效.如果验证失败,会写FATAL日志并终止程序运行.
1)比较验证
CHECK_EQ(arg1,arg2)
CHECK_NE(arg1,arg2)
CHECK_LE(arg1,arg2)
CHECK_LT(arg1,arg2)
CHECK_GE(arg1,arg2)
CHECK_GT(arg1,arg2)
2)CHECK_NOTNULL(arg)
3)字符串比较
CHECK_STREQ
CHECK_STRNE
CHECK_STRCASEEQ
CHECK_STRCASENE
4.特定的信息处理
1)针对可能导致程序崩溃的信号会输出dump信息
2)处理的信号包括:SIGSEGV,SIGILL,SIGABRT,SIGBUS,SIGTERM
3)相关函数:
google::InstallFailureSignalHandler() ,信号处理函数。
google::InstallFailureWriter(void (writer)(const char data,int size)) 默认dump信息输出到STDERR,可通过该函数定制dump输出目标。
5.日志类型
LOG //内置日志
VLOG //自定义日志
DLOG //DEBUG模式可输出的日志
DVLOG //DEBUG模式可输出的自定义日志
SYSLOG //系统日志,同时通过 syslog() 函数写入到/var/log/message 文件
PLOG //perror风格日志,设置errno状态并输出到日志中
RAW_LOG //线程安全的日志,需要#include <glog/raw_logging.h>
6.几个常用参数
FLAGS_logtostderr = true; // 设置日志消息是否转到标准输出而不是日志文件
FLAGS_alsologtostderr = true; // 设置日志消息除了日志文件之外是否去标准输出
FLAGS_colorlogtostderr = true; // 设置记录到标准输出的颜色消息(如果终端支持)
FLAGS_log_prefix = true; // 设置日志前缀是否应该添加到每行输出
FLAGS_logbufsecs = ; // 设置可以缓冲日志的最大秒数,0指实时输出
FLAGS_max_log_size = ; // 设置最大日志文件大小(以MB为单位)
FLAGS_stop_logging_if_full_disk = true; // 设置是否在磁盘已满时避免日志记录到磁盘
7.几个常用函数
google::SetLogDestination(google::INFO, "log/INFO_"); // 设置特定严重级别的日志的输出目录和前缀。第一个参数为日志级别,第二个参数表示输出目录及日志文件名前缀
google::SetLogFilenameExtension("logExtension"); // 在日志文件名中级别后添加一个扩展名。适用于所有严重级
google::SetStderrLogging(google::INFO); // 大于指定级别的日志都输出到标准输出
google::InstallFailureSignalHandler(); // 将 coredumped 信息输出到 stderr
四、自定义日志打印格式
要自定义glog输出格式并不难,可以直接修改logging.cc文件中的LogMessage::Init函数,修改的位置:
glog大部分常用功能在该文件中实现,可通过修改该文件来实现自己想要的功能
if (FLAGS_log_prefix && (line != kNoLogPrefix)) {
stream() << LogSeverityNames[severity][0]
<< setw(2) << 1+data_->tm_time_.tm_mon
<< setw(2) << data_->tm_time_.tm_mday
<< ' '
<< setw(2) << data_->tm_time_.tm_hour << ':'
<< setw(2) << data_->tm_time_.tm_min << ':'
<< setw(2) << data_->tm_time_.tm_sec << "."
<< setw(6) << usecs
<< ' '
<< setfill(' ') << setw(5)
<< static_cast<unsigned int>(GetTID()) << setfill('0')
<< ' '
<< data_->basename_ << ':' << data_->line_ << "] ";
}
五、增加严重度的种类
将系统中用来统计profile的日志单独打印到一个日志文件中,以便于定位问题与分析性能问题,所以我增加了一个LOG(PROFILE)的日志格式
修改以下源码部分(修改后记得重新编译):
src/logging.cc:337: "INFO", "WARNING", "ERROR", "FATAL", "PROFILE"
src/glog/logging.h:418:#define COMPACT_GOOGLE_LOG_PROFILE google::LogMessage( \
src/glog/logging.h:419: __FILE__, __LINE__, google::GLOG_PROFILE)
src/glog/logging.h:420:#define LOG_TO_STRING_PROFILE(message) google::LogMessage( \
src/glog/logging.h:421: __FILE__, __LINE__, google::GLOG_PROFILE, message)
src/glog/logging.h:423:#define COMPACT_GOOGLE_LOG_PROFILE google::NullStream()
src/glog/logging.h:424:#define LOG_TO_STRING_PROFILE(message) google::NullStream()
src/glog/logging.h:466:#define GOOGLE_LOG_PROFILE(counter) \
src/glog/logging.h:467: google::LogMessage(__FILE__, __LINE__, google::GLOG_PROFILE, counter, \
src/glog/logging.h:469:#define SYSLOG_PROFILE(counter) \
src/glog/logging.h:470: google::LogMessage(__FILE__, __LINE__, google::GLOG_PROFILE, counter, \
src/glog/logging.h.in:418:#define COMPACT_GOOGLE_LOG_PROFILE @ac_google_namespace@::LogMessage( \
src/glog/logging.h.in:419: __FILE__, __LINE__, @ac_google_namespace@::GLOG_PROFILE)
src/glog/logging.h.in:420:#define LOG_TO_STRING_PROFILE(message) @ac_google_namespace@::LogMessage( \
src/glog/logging.h.in:421: __FILE__, __LINE__, @ac_google_namespace@::GLOG_PROFILE, message)
src/glog/logging.h.in:423:#define COMPACT_GOOGLE_LOG_PROFILE @ac_google_namespace@::NullStream()
src/glog/logging.h.in:424:#define LOG_TO_STRING_PROFILE(message) @ac_google_namespace@::NullStream()
src/glog/logging.h.in:466:#define GOOGLE_LOG_PROFILE(counter) \
src/glog/logging.h.in:467: @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_PROFILE, counter, \
src/glog/logging.h.in:469:#define SYSLOG_PROFILE(counter) \
src/glog/logging.h.in:470: @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_PROFILE, counter, \
src/glog/log_severity.h:47:const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3, GLOG_PROFILE = 4,
src/glog/log_severity.h:54: ERROR = GLOG_ERROR, FATAL = GLOG_FATAL, PROFILE = GLOG_PROFILE;
测试:
#include <iostream>
#include <glog/logging.h>
#include <cstdlib>
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
// create logpath
std::string str_des;
str_des.append("mkdir -p ");
str_des.append("log");
system(str_des.c_str());
// INFO
std::string str_info;
str_info.append("./log");
str_info.append("/INFO_");
google::SetLogDestination(google::INFO, str_info.c_str());
// WARNING
std::string str_warn;
str_warn.append("./log");
str_warn.append("/WARNING_");
google::SetLogDestination(google::WARNING, str_warn.c_str());
LOG(WARNING) << "The is a warning!";
// my own type
std::string str_pro;
str_pro.append("./log");
str_pro.append("/PROFILE_");
google::SetLogDestination(google::WARNING, str_pro.c_str());
LOG(WARNING) << "The is my own type!";
// stop glog
google::ShutdownGoogleLogging();
编译执行:
g++ -g test.cpp -lglog -lgflags && ./a.out
之后在该目录下会生成一个log目录
a.out log test.cpp
cd log
a.out.INFO a.out.WARNING a.out.PROFILE INFO_20171208-151843.18256 PROFILE_20171208-151843.18256 WARNING_20171208-151843.18256
打开PROFILE_20171208-151843.18256
1 Log file created at: 2017/12/08 15:18:43
2 Running on machine: test
3 Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
4 W1208 15:18:43.879918 18256 test.cpp:28] The is my own type!
如果系统长时间运行,可以设置日志文件的大小,当文件超过该限制后就会重新生成一个新的log文件,glog有提供该功能
glog在Mac上可能存在打印线程号错误的情况, 此时修改glog源代码中的utilities.cc文件中的GetTID()接口,将最后一行
return (pid_t)(uintptr_t)pthread_self();改为
return ::pthread_mach_thread_np(pthread_self());