GLOG(Google Logging Library) 基本使用

安装

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.
  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: <glog/logging.h>是Google的开源C ++日志记录库,用于在C ++程序中实现灵活且高效的日志记录功能。它提供了一个易于使用的接口,可以将各种日志消息记录到控制台、文件或其他输出目标中。 <glog/logging.h>库主要由以下几个组件组成: 1. Logger(日志记录器):提供了不同级别的日志记录功能,例如INFO、WARNING、ERROR和FATAL。可以通过使用Logger对象的接口来记录不同级别的日志消息。 2. LogSink(日志汇):定义了将日志消息写入目标的接口。可以通过创建和注册不同类型的LogSink对象来将日志消息输出到不同的目标,例如控制台、文件或远程服务器。 3. LogMessage(日志消息):包含了要记录的日志消息的详细信息,例如发生日志记录的文件名、行号等。可以通过LogMessage提供的接口来记录日志消息。 4. Flag(标志):用于启用或禁用特定的日志记录功能。可以通过设置不同的Flag来控制日志记录的级别、输出目标等。 通过在C ++代码中包含<glog/logging.h>头文件,并使用其中的接口,开发人员可以方便地实现日志记录功能。此外,该库还提供了一些额外的功能,例如支持日志消息的格式化、日志消息的过滤和日志的分级统计等。 总而言之,<glog/logging.h>是一个强大且易于使用的C ++日志记录库,提供了丰富的功能和灵活的配置选项,可以帮助开发人员更好地追踪和调试程序中的问题。 ### 回答2: <glog/logging.h> 是一个开源的 C++ 日志库。它提供了一套灵活、功能丰富且易于使用的日志记录工具,用于帮助开发人员在程序中方便地记录和追踪各种信息。 使用<glog/logging.h>,开发人员可以通过简单的API调用来记录各种消息,包括调试信息、警告、错误和临时性信息。该库支持不同级别的日志,包括 INFO、WARNING、ERROR、FATAL,开发人员可以根据不同的需求来选择适当的日志级别。 此外,<glog/logging.h> 还提供了一些其他功能,如日志文件的自动分割、多线程支持、日志信息的颜色标记、日志信息到标准输出的同时写入到磁盘等。这些功能使得开发人员可以更好地分析和排查程序中的问题。 另外,<glog/logging.h> 是跨平台的,可以在多个操作系统上运行,如Linux、Windows和MacOS。它被广泛应用于各种规模的软件项目中,包括大型分布式系统、Web 服务器、数据库等。 总而言之,<glog/logging.h> 是一个功能强大且易于使用C++日志记录库,可以帮助开发人员在程序中方便地记录各种信息,并提供了许多有用的功能来方便开发人员分析和排查问题。无论是开发大型软件还是小型项目,都可以考虑使用这个库来提高开发效率和日志记录的质量。 ### 回答3: <glog/logging.h> 是一个开源的 C++ 日志库,由 Google 开发并维护。它提供了一种简单且高效的方式来在代码中记录日志信息。 使用 <glog/logging.h>,开发者可以通过调用相应的函数将各种级别的日志信息输出到控制台或文件中。这些日志级别包括 DEBUG、INFO、WARNING、ERROR 和 FATAL,可以根据需要选择不同的级别来记录日志,以方便在开发和调试过程中进行有效的日志跟踪和错误定位。 <glog/logging.h> 的优势在于其高性能和灵活的配置选项。它通过多线程和缓冲技术,能够在高并发的情况下保持较低的性能开销。此外,开发者还可以通过配置文件或命令行参数来调整日志记录的行为,包括输出格式、日志文件路径、日志级别等。这使得 <glog/logging.h> 能够灵活地适应各种不同的应用场景和需求。 另外,<glog/logging.h> 还提供了一些其他功能,如栈追踪信息的记录、日志的自动滚动和分割、对日志进行查找和过滤等。这些功能进一步增强了日志的可读性和可管理性,有助于快速定位和排查问题。 总之,<glog/logging.h> 是一个功能强大、易用且高性能的 C++ 日志库。它通过简化日志记录的过程和提供丰富的配置选项,极大地方便了开发人员进行日志管理和问题排查,是很多 C++ 项目中常用的工具之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值