glog:日志输出
支持debug功能
glog提供特定的宏只在debug模式下生效。以下分别对应LOG、LOG_IF、DLOG_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";
判定大小关系: CHECK_EQ, CHECK_NE, CHECK_LE, CHECK_LT, CHECK_GE, CHECK_GT,使用这些宏需要注意类型一致,如果出现类型不一致的,可使用static_cast转换。
判定指针是否为空:CHECK_NOTNULL(some_ptr),可用于对象初始化的时候。
判定字符串是否相等:CHECK_STREQ, CHECK_STRNE, CHECK_STRCASEEQ, CHECK_STRCASENE。可进行大小写敏感或不敏感字符串来分别判定。
判定浮点是否相等或相近:CHECK_DOUBLE_EQ,CHECK_NEAR。这两个宏都需要指定一个可容忍的偏差上限。
gflags:命令行参数解析
将需要的命令行参数使用gflags的宏:DEFINE_xxxxx(变量名,默认值,help-string) 定义在文件当中,注意全局域哦。gflags支持以下类型:
DEFINE_bool
: booleanDEFINE_int32
: 32-bit integerDEFINE_int64
: 64-bit integerDEFINE_uint64
: unsigned 64-bit integerDEFINE_double
: doubleDEFINE_string
: C++ string
google::ParseCommandLineFlags(&argc, &argv, true);
第三个参数的作用:
如果设为true,则该函数处理完成后,argv中只保留argv[0],argc会被设置为1。
如果为false,则argv和argc会被保留,但是注意函数会调整argv中的顺序。
这样,在后续代码中可以使用FLAGS_变量名访问对应的命令行参数了
最后,编译成可执行文件之后,用户可以使用:executable --参数1=值1 --参数2=值2 ... 来为这些命令行参数赋值。
这里值得注意的是bool类型命令行参数,除了可以使用--xxx=true/false之外,还可以使用--xxx和--noxxx后面不加等号的方式指定true和false
在其他文件中使用定义的flags变量:有些时候需要在main之外的文件使用定义的flags变量,这时候可以使用宏定义DECLARE_xxx(变量名)声明一下(就和c++中全局变量的使用是一样的,extern一下一样)
DECLARE_bool
: booleanDECLARE_int32
: 32-bit integerDECLARE_int64
: 64-bit integerDECLARE_uint64
: unsigned 64-bit integerDECLARE_double
: doubleDECLARE_string
: C++ string在gflags的doc中,推荐在对应的.h文件中进行DECLARE_xxx声明,需要使用的文件直接include就行了。
- 定制你自己的help信息与version信息:(gflags里面已经定义了-h和--version,你可以通过以下方式定制它们的内容)
- version信息:使用google::SetVersionString设定,使用google::VersionString访问
- help信息:使用google::SetUsageMessage设定,使用google::ProgramUsage访问
- 注意:google::SetUsageMessage和google::SetVersionString必须在google::ParseCommandLineFlags之前执行
main.cc:
#include <glog/logging.h>
#include <gflags/gflags.h>
DEFINE_string(file_path, "", "input file path"); // 不一定放在main函数中
DEFINE_bool(verbose, false, "whether to print log"); // 调试开关
DEFINE_double(rate, 2.0, ""); // 代替宏定义
int main(int argc, char *argv[]) {
google::InitGoogleLogging(argv[0]); // 初始化glog
FLAGS_logtostderr = 1;
FLAGS_colorlogtostderr = 1;
gflags::SetUsageMessage("\nusage: ./test --file_path <file_path>");
google::ParseCommandLineFlags(&argc, &argv, true); // 初始化gflags
std::string file_path = FLAGS_file_path;
if (file_path.empty()) {
gflags::ShowUsageWithFlagsRestrict(argv[0], "main");
LOG(FATAL) << "file_path is empty !";
}
CHECK(!FLAGS_file_path.empty()) << "file path is empty";
for(int index = 0; index <= 10; ++index) {
LOG(INFO) << "index: " << index;
LOG_IF(INFO, index > 5) << " --> index > 5"; // 当index > 5时输出log
LOG_EVERY_N(WARNING, 5) << " --> index % 5 == 0"; // 每隔5次输出一次log
LOG_IF_EVERY_N(ERROR, index < 5, 2) << " --> index < 5, i % 2 == 0"; // 当index < 5时每隔2次输出一次log;
LOG_FIRST_N(INFO, 8) << " --> index < 8"; // 输出前8次log
}
DLOG(INFO) << "Debug Mode Message!"; // debug模式输出log,release模式不输出
google::ShutdownGoogleLogging();
return 0;
}
CMakeList.txt:
cmake_minimum_required(VERSION 2.8)
project(test)
set(CMAKE_BUILD_TYPE "Debug") # Debug/Release
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
find_package(gflags REQUIRED)
include_directories(${gflags_INCLUDE_DIR})
find_package(Glog REQUIRED)
include_directories(${GLOG_INCLUDE_DIRS})
add_executable(test main.cc)
target_link_libraries(test glog::glog gflags)
$ ./bin/test
test:
usage: ./test --file_path <file_path>
Flags from /home/ubuntu/test/main.cc:
-file_path (input file path) type: string default: ""
-rate () type: double default: 2
-verbose (whether to print log) type: bool default: false
F0601 20:30:42.405541 32641 main.cc:19] file_path is empty !
*** Check failure stack trace: ***
@ 0x414be6 google::LogMessage::Fail()
@ 0x414b2a google::LogMessage::SendToLog()
@ 0x414466 google::LogMessage::Flush()
@ 0x417f87 google::LogMessageFatal::~LogMessageFatal()
@ 0x410daa main
@ 0x7fa34acdf830 __libc_start_main
@ 0x410ba9 _start
@ (nil) (unknown)
Aborted (core dumped)
$ ./bin/test --file_path /home/
默认情况下,日志会写入本地/tmp/文件夹中,文件名格式:
<program name>.<host name>.<user name>.log.<Severity level>.<date>-<time>.<pid>
如:在/tmp下生成
main.INFO -> main.ubuntu.alan.log.INFO.20191022-150504.49837
main.ubuntu.alan.log.INFO.20191022-150504.49837
默认情况下,GLog还会将ERROR和FATAL错误记录到stderr消息中(会在终端打印出来);
在终端打印出的消息的格式:
<Serverity level><number> <time>.<number> <pid> <file>:<line number> <messages>
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
如:
I1022 15:05:04.920763 49837 main.cc:20] initial main
glog参数设置:
FLAGS_log_dir = "./"; // 设置log输出文件夹,默认输出到本地/tmp文件夹下
FLAGS_logtostderr = 1; // 设置log输出到stderr,不保存到本地
FLAGS_alsologtostderr = 1; // 设置log输出到stderr和本地
FLAGS_stderrthreshold = 1; // WARNING以及更高级别的log将会记录到stderr中;(INFO: 0, WARNING: 1, ERROR: 2 FATAL: 3)
FLAGS_minloglevel = 0; // 默认是0,INFO以及更高级别的Log将会被记录;(INFO: 0, WARNING: 1, ERROR: 2 FATAL: 3)
FLAGS_colorlogtostderr = 1; // 设置记录到标准输出的颜色消息(如果终端支持)
FLAGS_log_prefix = true; // 设置日志前缀是否应该添加到每行输出
FLAGS_logbufsecs = 0;// 设置可以缓冲日志的最大秒数,0指实时输出
FLAGS_max_log_size =10;// 设置最大日志文件大小(以MB为单位)
FLAGS_stop_logging_if_full_disk = true; // 设置是否在磁盘已满时避免日志记录到磁盘
可在命令行运行程序时指定这些flag,如$ ./exe -logtostderr true
在其他文件中使用定义的flags变量:有些时候需要在main之外的文件使用定义的flags变量,这时候可以使用宏定义DECLARE_xxx(变量名)声明一下(就和c++中全局变量的使用是一样的,extern一下一样)
DECLARE_bool
: booleanDECLARE_int32
: 32-bit integerDECLARE_int64
: 64-bit integerDECLARE_uint64
: unsigned 64-bit integerDECLARE_double
: doubleDECLARE_string
: C++ string在gflags的doc中,推荐在对应的.h文件中进行DECLARE_xxx声明,需要使用的文件直接include就行了。
参考:https://blog.youkuaiyun.com/qq_34347375/article/details/86629421
glog重定向
#include <glog/logging.h>
#include "alan/logger.h"
Alan::Logger my_logger;
class MyLogSink : public google::LogSink {
void send(google::LogSeverity severity,
const char* full_filename,
const char* base_filename,
int line,
const struct ::tm* tm_time,
const char* message,
size_t message_len) override {
thread_local std::string msg;
msg.assign(message, message_len);
Alan::LogLevel my_level;
switch (severity) {
case google::GLOG_INFO: my_level = Alan::LogLevel::INFO; break;
case google::GLOG_WARNING: my_level = Alan::LogLevel::WARN; break;
case google::GLOG_ERROR: my_level = Alan::LogLevel::ERROR; break;
case google::GLOG_FATAL: my_level = Alan::LogLevel::FATAL; break;
default: my_level = Alan::LogLevel::INFO;
}
my_logger.Log(my_level, "%%:%%] %%", base_filename, line, msg);
}
};
static MyLogSink my_log_sink;
int main(int argc, char *argv[]) {
google::InitGoogleLogging(argv[0]);
google::AddLogSink(&my_log_sink);
// Avoid duplicate logging to stderr with my_logger.
FLAGS_stderrthreshold = google::NUM_SEVERITIES;
return 0;
}