安装
Github google logging library
进入glog文件夹
mkdir build
cd build
cmake ..
make -j8
sudo make install
基本demo编译测试
mkdir glog_demo
cd glog_demo
gedit glog_demo.cpp
glog_demo.cpp:
#include <glog/logging.h>
int main(int argc, char* argv[]) {
// 初始化 glog
google::InitGoogleLogging(argv[0]);
// 设置日志输出路径
google::SetLogDestination(google::INFO, "/path/to/your/logfile.INFO");
google::SetLogDestination(google::WARNING, "/path/to/your/logfile.WARNING");
google::SetLogDestination(google::ERROR, "/path/to/your/logfile.ERROR");
// 记录一些日志
LOG(INFO) << "This is an informational message";
LOG(WARNING) << "This is a warning message";
LOG(ERROR) << "This is an error message";
// 关闭 glog
google::ShutdownGoogleLogging();
return 0;
}
CMakeLists.txt
gedit CMakeLists.txt
cmake_minimum_required (VERSION 3.16)
project (glog_demo VERSION 1.0)
find_package (glog_demo 0.7.0 REQUIRED)
add_executable (glog_demo glog_demo.cpp)
target_link_libraries (glog_demo glog::glog)
Log Level
INFO
WARNING
ERROR
FATAL
如果出现FATAL则终止程序
基本log输出函数
LOG(INFO) << "This is an informational message";
LOG(WARNING) << "This is a warning message";
LOG(ERROR) << "This is an error message";
条件log输出函数
1.判断表达式是否为真,若真则输出:
LOG_IF
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
int value = 10;
LOG_IF(INFO, value > 5) << "Value is greater than 5: " << value;
LOG_IF(INFO, value < 5) << "This message will not be logged";
google::ShutdownGoogleLogging();
return 0;
}
2.每N次调用输出一次log
LOG_EVERY_N
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
for (int i = 0; i < 10; ++i) {
LOG_EVERY_N(INFO, 3) << "This message is logged every 3 iterations. Iteration: " << i;
}
google::ShutdownGoogleLogging();
return 0;
}
3.仅仅前N调用输出log,之后不输出
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
for (int i = 0; i < 10; ++i) {
LOG_FIRST_N(INFO, 3) << "This message is logged only for the first 3 iterations. Iteration: " << i;
}
google::ShutdownGoogleLogging();
return 0;
}
4.每N次调用输出一次log,同时判断表达式条件,为真时输出
LOG_IF_EVERY_N
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
int value = 10;
for (int i = 0; i < 10; ++i) {
LOG_IF_EVERY_N(INFO, value > 5, 3) << "This message is logged every 3 iterations when value > 5. Iteration: " << i;
}
google::ShutdownGoogleLogging();
return 0;
}
5.当条件为假时记录致命错误并终止程序
LOG_ASSERT
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
int value = 10;
LOG_ASSERT(value == 10) << "Value should be 10";
// LOG_ASSERT(value == 5) << "This will cause the program to terminate";
google::ShutdownGoogleLogging();
return 0;
}
调试模式 DEBUG
提供了一些函数,可以在调试模式下输出log,但是在非调试模式下无效。
DLOG
DLOG_IF
DLOG_EVERY_N
DLOG_IF_EVERY_N
函数使用方法和前面相同。
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
int value = 10;
DLOG(INFO) << "This is a debug message";
DLOG_IF(INFO, value > 5) << "This debug message is logged when value > 5";
for (int i = 0; i < 10; ++i) {
DLOG_EVERY_N(INFO, 3) << "This debug message is logged every 3 iterations. Iteration: " << i;
DLOG_IF_EVERY_N(INFO, value > 5, 3) << "This debug message is logged every 3 iterations when value > 5. Iteration: " << i;
}
google::ShutdownGoogleLogging();
return 0;
}
判断与断言 CHECK
提供了一系列函数对变量进行关系比较,在必要时终止程序。
CHECK — 检查条件是否为真
具体关系比较函数:
CHECK_EQ 判断是否相等
CHECK_NE 判断是否不相等
CHECK_LT 判断是否小于
CHECK_LE 判断是否小于等于
CHECK_GT 判断是否大于
CHECK_GE 判断是否大于等于
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
int x = 5;
int y = 10;
CHECK(x < y) << "x should be less than y";
CHECK_EQ(x + 5, y) << "x + 5 should be equal to y";
CHECK_NE(x, y) << "x should not be equal to y";
// CHECK(x > y) << "This will terminate the program because x is not greater than y";
google::ShutdownGoogleLogging();
return 0;
}
DEBUG模式下的CHECK
DCHECK_EQ
DCHECK_NE
DCHECK_LT
DCHECK_LE
DCHECK_GT
DCHECK_GE
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
int x = 5;
int y = 10;
DCHECK(x < y) << "x should be less than y (debug mode only)";
DCHECK_EQ(x + 5, y) << "x + 5 should be equal to y (debug mode only)";
DCHECK_NE(x, y) << "x should not be equal to y (debug mode only)";
google::ShutdownGoogleLogging();
return 0;
}
其他 Others
1.当条件为真时记录致命日志并终止程序
LOG_IF_FATAL
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
int value = 10;
LOG_IF(FATAL, value > 5) << "Fatal error because value > 5";
google::ShutdownGoogleLogging();
return 0;
}
2.只输出一次
LOG_ONCE
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
for (int i = 0; i < 10; ++i) {
LOG_ONCE(INFO) << "This message is logged only once.";
}
google::ShutdownGoogleLogging();
return 0;
}
3.每隔一段时间输出一次
LOG_EVERY_T
#include <glog/logging.h>
#include <chrono>
#include <thread>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
using namespace std::chrono_literals;
for (int i = 0; i < 100; ++i) {
LOG_EVERY_T(INFO, 5) << "This message is logged every 5 seconds.";
std::this_thread::sleep_for(1s);
}
google::ShutdownGoogleLogging();
return 0;
}
4.在某个log级别上输出
LOG_AT_LEVEL
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
int log_level = 1; // 0: INFO, 1: WARNING, 2: ERROR, 3: FATAL
LOG_AT_LEVEL(log_level) << "This message is logged at the specified log level.";
google::ShutdownGoogleLogging();
return 0;
}
5.指定级别并判断表达式条件
LOG_IF_AT_LEVEL
#include <glog/logging.h>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
int value = 10;
int log_level = 1; // 0: INFO, 1: WARNING, 2: ERROR, 3: FATAL
LOG_IF_AT_LEVEL(log_level, value > 5) << "This message is logged at the specified log level if condition is true.";
google::ShutdownGoogleLogging();
return 0;
}
6.将log存入一个string 而不是立即输出
LOG_STRING
#include <glog/logging.h>
#include <sstream>
#include <string>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
std::ostringstream log_stream;
LOG_STRING(INFO, &log_stream) << "This message is logged to a string stream.";
std::string log_output = log_stream.str();
std::cout << "Logged string: " << log_output << std::endl;
google::ShutdownGoogleLogging();
return 0;
}
自定义log输出函数(对接接口)
由于LOG等函数仅提供使用<<输出的方式,很多应用场景需要格式化输出。或者是需要自定义log输出函数的使用场景,则可以使用如下方式自定义输出:
#include <glog/logging.h>
#include <cstdarg>
#include <cstdio>
void log_info(const char* format, ...) {
va_list args;
va_start(args, format);
char buffer[1024];
vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
LOG(INFO) << buffer;
}
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
// 使用自定义函数进行日志记录
log_info("This is an informational message with number: %d", 42);
google::ShutdownGoogleLogging();
return 0;
}
例如这里通过log_info函数实现了和LOG(INFO)函数同样的功能并提供了格式化输出。
更为简单的,可以使用sprintf函数进行格式化:
#include <glog/logging.h>
#include <string>
#include <cstdio>
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
// 使用 sprintf 格式化字符串
char buffer[100];
sprintf(buffer, "This is an informational message with number: %d", 42);
LOG(INFO) << buffer;
// 使用 fmt::format (如果你使用了 fmt 库)
// #include <fmt/format.h>
// std::string msg = fmt::format("This is an informational message with number: {}", 42);
// LOG(INFO) << msg;
google::ShutdownGoogleLogging();
return 0;
}
输出log文件与格式
在前面的demo中,执行后生成3个log文件:
1.INFO output
filename: logfile.INFO20240722-092418.3462
Log file created at: 2024/07/22 09:24:18
Running on machine: wakkk-virtual-machine
Running duration (h:mm:ss): 0:00:00
Log line format: [IWEF]yyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg
I20240722 09:24:18.244402 137523320286784 glog_test.cpp:13] This is an informational message
W20240722 09:24:18.244973 137523320286784 glog_test.cpp:14] This is a warning message
E20240722 09:24:18.245163 137523320286784 glog_test.cpp:15] This is an error message
2.WARNING output
filename: logfile.WARNING20240722-092418.3462
Log file created at: 2024/07/22 09:24:18
Running on machine: wakkk-virtual-machine
Running duration (h:mm:ss): 0:00:00
Log line format: [IWEF]yyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg
W20240722 09:24:18.244973 137523320286784 glog_test.cpp:14] This is a warning message
E20240722 09:24:18.245163 137523320286784 glog_test.cpp:15] This is an error message
3.ERROR output
filename: logfile.ERROR20240722-092418.3462
Log file created at: 2024/07/22 09:24:18
Running on machine: wakkk-virtual-machine
Running duration (h:mm:ss): 0:00:00
Log line format: [IWEF]yyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg
E20240722 09:24:18.245163 137523320286784 glog_test.cpp:15] This is an error message
可见,INFO中会输出INFO WARNING ERROR信息,WARNING中会输出WARNING和ERROR,而ERROR中只有ERROR。
同时,对于ERROR,也会输出至程序所在的终端中(stderr输出)。
LOG输出格式
example:
W20240722 09:24:18.244973 137523320286784 glog_test.cpp:14] This is a warning message
格式描述:
Lyyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg...
附: logging.h 注释
// Make a bunch of macros for logging. The way to log things is to stream
// things to LOG(<a particular severity level>). E.g.,
//
// LOG(INFO) << "Found " << num_cookies << " cookies";
//
// You can capture log messages in a string, rather than reporting them
// immediately:
//
// vector<string> errors;
// LOG_STRING(ERROR, &errors) << "Couldn't parse cookie #" << cookie_num;
//
// This pushes back the new error onto 'errors'; if given a nullptr pointer,
// it reports the error via LOG(ERROR).
//
// You can also do conditional logging:
//
// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
//
// You can also do occasional logging (log every n'th occurrence of an
// event):
//
// LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
//
// The above will cause log messages to be output on the 1st, 11th, 21st, ...
// times it is executed. Note that the special google::COUNTER value is used
// to identify which repetition is happening.
//
// You can also do occasional conditional logging (log every n'th
// occurrence of an event, when condition is satisfied):
//
// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER
// << "th big cookie";
//
// You can log messages the first N times your code executes a line. E.g.
//
// LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";
//
// Outputs log messages for the first 20 times it is executed.
//
// Analogous SYSLOG, SYSLOG_IF, and SYSLOG_EVERY_N macros are available.
// These log to syslog as well as to the normal logs. If you use these at
// all, you need to be aware that syslog can drastically reduce performance,
// especially if it is configured for remote logging! Don't use these
// unless you fully understand this and have a concrete need to use them.
// Even then, try to minimize your use of them.
//
// There are also "debug mode" logging macros like the ones above:
//
// DLOG(INFO) << "Found cookies";
//
// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
//
// DLOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
//
// All "debug mode" logging is compiled away to nothing for non-debug mode
// compiles.
//
// We also have
//
// LOG_ASSERT(assertion);
// DLOG_ASSERT(assertion);
//
// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
//
// There are "verbose level" logging macros. They look like
//
// VLOG(1) << "I'm printed when you run the program with --v=1 or more";
// VLOG(2) << "I'm printed when you run the program with --v=2 or more";
//
// These always log at the INFO log level (when they log at all).
// The verbose logging can also be turned on module-by-module. For instance,
// --vmodule=mapreduce=2,file=1,gfs*=3 --v=0
// will cause:
// a. VLOG(2) and lower messages to be printed from mapreduce.{h,cc}
// b. VLOG(1) and lower messages to be printed from file.{h,cc}
// c. VLOG(3) and lower messages to be printed from files prefixed with "gfs"
// d. VLOG(0) and lower messages to be printed from elsewhere
//
// The wildcarding functionality shown by (c) supports both '*' (match
// 0 or more characters) and '?' (match any single character) wildcards.
//
// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
//
// if (VLOG_IS_ON(2)) {
// // do some logging preparation and logging
// // that can't be accomplished with just VLOG(2) << ...;
// }
//
// There are also VLOG_IF, VLOG_EVERY_N and VLOG_IF_EVERY_N "verbose level"
// condition macros for sample cases, when some extra computation and
// preparation for logs is not needed.
// 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";
// VLOG_EVERY_N(1, 10)
// << "I'm printed every 10th occurrence, and when you run the program "
// "with --v=1 or more. Present occurrence is " << google::COUNTER;
// VLOG_IF_EVERY_N(1, (size > 1024), 10)
// << "I'm printed on every 10th occurrence of case when size is more "
// " than 1024, when you run the program with --v=1 or more. ";
// "Present occurrence is " << google::COUNTER;
//
// The supported severity levels for macros that allow you to specify one
// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
// Note that messages of a given severity are logged not only in the
// logfile for that severity, but also in all logfiles of lower severity.
// E.g., a message of severity FATAL will be logged to the logfiles of
// severity FATAL, ERROR, WARNING, and INFO.
//
// There is also the special severity of DFATAL, which logs FATAL in
// debug mode, ERROR in normal mode.
//
// Very important: logging a message at the FATAL severity level causes
// the program to terminate (after the message is logged).
//
// Unless otherwise specified, logs will be written to the filename
// "<program name>.<hostname>.<user name>.log.<severity level>.", followed
// by the date, time, and pid (you can't prevent the date, time, and pid
// from being in the filename).
//
// The logging code takes two flags:
// --v=# set the verbose level
// --logtostderr log all the messages to stderr instead of to logfiles
// LOG LINE PREFIX FORMAT
//
// Log lines have this form:
//
// Lyyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg...
//
// where the fields are defined as follows:
//
// L A single character, representing the log level
// (eg 'I' for INFO)
// yyyy The year
// mm The month (zero padded; ie May is '05')
// dd The day (zero padded)
// hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds
// threadid The space-padded thread ID as returned by GetTID()
// (this matches the PID on Linux)
// file The file name
// line The line number
// msg The user-supplied message
//
// Example:
//
// I1103 11:57:31.739339 24395 google.cc:2341] Command line: ./some_prog
// I1103 11:57:31.739403 24395 google.cc:2342] Process id 24395
//
// NOTE: although the microseconds are useful for comparing events on
// a single machine, clocks on different machines may not be well
// synchronized. Hence, use caution when comparing the low bits of
// timestamps from different machines.
// Log messages below the GOOGLE_STRIP_LOG level will be compiled away for
// security reasons. See LOG(severity) below.
// A few definitions of macros that don't generate much code. Since
// LOG(INFO) and its ilk are used all over our code, it's
// better to have compact code for these operations.
标签:INFO,Google,Logging,LOG,int,Library,google,argv,include
From: https://blog.csdn.net/m0_54943420/article/details/140601340