【日志工具】g3log_4_API接口描述

2023-05-16

API描述

使用g3log所需的大部分API都在本文件中进行了描述,有关更多API文档和示例,请继续阅读 API readme,你会找到一些例子如这里所示:

日志API: LOG调用

LOG调用可以采用流LOG(INFO) << "some text" 或类似printf的 LOGF(WARNING, "some number %d", 123)语法。

条件日志记录可以采用LOG_IF(INFO, <boolean-expression>) << " some text" LOGF_IF(WARNING, <boolean-expression>) << " some text". 的方式,且仅当表达式值为 true才会被记录到日志中。

例如: LOG_IF(INFO, 1 != 200) << " some text";LOG_IF(FATAL, SomeFunctionCall()) << " some text";

一段使用致命崩溃级别的日志调用, 例如LOG_IF(FATAL,...) , 日志会将FATAL级别的消息记录,同时也会杀死进程,它的本质和 CHECK(<boolea-expression>) << ...类似,不同的是 CHECK(<boolean-expression) 结果为false

契约式API: CHECK调用

契约式API和日志API类似,都有 CHECK(<boolean-expression>) << ... 流方式,或 (*) CHECKF(<boolean-expression>, ...)printf方式。

如果<boolean-expression> 值为false,检查失败的消息将以FIFO的顺序与之前已经生成的消息被一起记录,在消息被发送到接收器并且接收器已经处理了致命的契约消息之后,该进程将关闭。

(* * CHECK_F(<boolean-expression>, ...); 类似之前的CHECK类printf式API,它跟 CHECKF 完全相同,且保持向后兼容性 * )

日志级别

默认的日志记录级别是DEBUG, INFO, WARNINGFATAL (参考FATAL用法above),日志记录级别定义在loglevels.hpp.

在某些windows框架中,有一个跟DEBUG日志级别的冲突For some windows framework there is a clash with the logging level. CMake的Build options 有一个选项可以将默认的故障级别从DEBUG 改完 DBUG.

**CMake option: (default OFF) ** cmake -DCHANGE_G3LOG_DEBUG_TO_DBUG=ON ..

在运行时禁用/启用级别

日志记录级别可以在运行时被禁用。这种情况会发生在loglevels.hpp, loglevels.cpp 和 g3log.hpp.

有一个cmake选项来使能动态启用/禁用级别,当使能这个选项后,每一个日志记录都会检查这个开关的使能状态,从而导致有一个轻微的运行开销,对于大多数意图和目的,这个运行时开销是可以忽略的。

如果cmake选项被关闭了,那内部的开关检查基本不会有运行开销。如果关闭了动态日志记录cmake选项,则将启用所有日志记录级别。

CMake option: (default OFF) cmake -DUSE_DYNAMIC_LOGGING_LEVELS=ON ..

自定义日志级别

你可以创建和使用自定义日志记录级别,Custom logging levels can be created and used. 当自定义自定义日志记录级别时,您可以设置它的值以及它的文本。你可以重新利用诸如INFO, WARNING 等其他或你自己定义的值, 任何一个等于或大于FATAL的日志都将被记录到FATAL级别的日志中。

添加你自己的自定义级别时请记住

  1. 如果cmake 选项 G3_DYNAMIC_LOGGING 被使能,你必须使用 g3::only_change_at_initialization::addLogLevel(...) 来给g3log一个你的日志级别的记录,同时确定它是否启用。
  2. 如果cmake选项 G3_DYNAMIC_LOGGING 被关闭,那么利用addLogLevel(...) 给g3log一个你的日志级别的记录是不需要的,同时所有的日志记录级别都被被视为已启用。

例如:

// In CustomLoggingLevels.hpp
#include <g3log/loglevels.hpp>

// all values with a + 1 higher than their closest equivalet
// they could really have the same value as well.

const LEVELS FYI {DEBUG.value + 1, {"For Your Information"}}; 
const LEVELS CUSTOM {INFO.value + 1, {"CUSTOM"}}; 
const LEVELS SEVERE {WARNING.value +1, {"SEVERE"}};
const LEVELS DEADLY {FATAL.value + 1, {"DEADLY"}}; 

更多的例子可以参考 unit tests.

Sink的创建和使用

g3log默认的sink是g2log中使用的sink,它是一个具有有限API的简单文件接收器,有关默认文件接收器的详细信息,你可以在这里查阅 filesink.hpp, filesink.cpp, filesinkhelper.ipp

更多的sinks可以在g3sinks 找到(log rotate, log rotate with filtering on levels)

日志记录接收器不必是特定类型的子类。日志接收器的唯一要求是,它可以接收日志消息。

使用默认sink

Sink的创建被定义在logworker.hpp ,使用在 logworker.cpp. 有关更深层的调用可以查阅 sinkhandle.hpp 和 sinkwrapper.hpp

  std::unique_ptr<FileSinkHandle> addDefaultLogger(
            const std::string& log_prefix
            , const std::string& log_directory
            , const std::string& default_id = "g3log");

在单元测试"test_filechange"中创建的默认的日志记录器如下所示:

  const std::string directory = "./";
  const std::string name = "(ReplaceLogFile)";
  auto worker = g3::LogWorker::createLogWorker();
  auto handle = worker->addDefaultLogger(name, directory);

得到的文件名应该是这样的:

   ./(ReplaceLogFile).g3log.20160217-001406.log

指定sink的日志接收函数

默认的日志格式可以被任意sink覆盖重写,如果sink接收函数调用 toString() ,默认日志格式将被启用The default log formatting look can be overriden by any sink. If the sink receiving function calls toString() then the default log formatting will be used. 如果sink接收 toString(&XFunc) 函数被调用,那么将会被XFunc替代使用(如果代码细节不清楚,请查阅 LogMessage.h/cpp ). (XFunc 是可以选择放置自定义函数的地方)。

这里有一个传递指针的函数:

std::string (*) (const LogMessage&)

也可以在 LogMessage.h 被定义:

using LogDetailsFunc = std::string (*) (const LogMessage&);

日志格式自定义

请查阅API_custom_formatting.md

日志刷新(记录)

默认的文件接收器将在每个日志进入时刷新(记录)它,对于不同的刷新(记录)策略,请查看g3sinks logrotate and LogRotateWithFilters.

在程序关闭时,所有加入队列的日志都将被刷新(记录)到接收器。
在发现致命崩溃事件(SIGSEGV等)时,所有加入队列的日志都将刷新(记录)到接收器。

以编程方式触发的突然进程退出,例如调用 exit(0) 将不会记录已加入队列的日志。这就类似于一个bug,它不会触发一个致命的信号,但是进程退出也不会使加入队列的日志条目被刷新(记录)。G3log可以捕获几个致命的崩溃,它可以很好地处理RAII退出,但魔术是如此遥不可及。

G3log和sink用法代码示例

加入了 logrotate sink (g3sinks) 的示例用法. 在这个例子中,我们展示了如何调用logrotate API ,logrotate的限制从默认值更改为10MB,通过调用sink处理程序来更改限制,该处理程序将函数调用传递给实际的logrotate sink对象。

// main.cpp
#include <g3log/g3log.hpp>
#include <g3log/logworker.h>
#include <g3sinks/LogRotate.h>
#include <memory>

int main(int argc, char**argv) {
   using namespace g3;
   std::unique_ptr<LogWorker> logworker{ LogWorker::createLogWorker() };
   auto sinkHandle = logworker->addSink(std::make_unique<LogRotate>(),
                                          &LogRotate::save);
   
   // initialize the logger before it can receive LOG calls
   initializeLogging(logworker.get());            
            
   // You can call in a thread safe manner public functions on the logrotate sink
   // The call is asynchronously executed on your custom sink.
   const int k10MBInBytes = 10 * 1024 * 1024;
   std::future<void> received = sinkHandle->call(&LogRotate::setMaxLogSize, k10MBInBytes);
   
   // Run the main part of the application. This can be anything of course, in this example
   // we'll call it "RunApplication". Once this call exits we are in shutdown mode
   RunApplication();

   // If the LogWorker is initialized then at scope exit the g3::shutDownLogging() will be 
   // called automatically. 
   //  
   // This is important since it protects from LOG calls from static or other entities that will go out of
   // scope at a later time. 
   //
   // It can also be called manually if for some reason your setup is different then the one highlighted in
   // this example
   g3::shutDownLogging();
}

动态消息大小调整

默认构建使用固定大小的缓冲区格式化消息。这个缓冲区的大小是2048字节。如果传入消息导致大于2048字节的格式化消息,则该消息将绑定到2048字节,并使用 [...truncated...] 附加到绑定消息的结尾,在某些情况下,我们希望在运行时动态地改变大小。例如,在调试服务器的有效负载时,为了检查整个有效负载,可能需要处理更大的消息大小。比起强迫开发人员重建服务器,在运行时用一个配置文件配置消息的大小的动态调整消息大小得功能是更好的。

作为CMake选项支持此功能:

CMake option: (default OFF) cmake -DUSE_G3_DYNAMIC_MAX_MESSAGE_SIZE=ON ..

下面是更改消息大小的示例。

    g3::only_change_at_initialization::setMaxMessageSize(10000);

致命处理

G3log的默认行为是在强制进程退出之前捕获多个致命事件。 在捕获致命之间后将生成一个堆栈,并且知道堆栈前的所有日志都将被刷新(记录)到sink中。

Linux/*nix

linux的默认致命处理是处理致命信号,在编写诸如 SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM的 信号时, Linux致命处理是在 crashhandler.hpp 和 crashhandler_unix.cpp。

通常与自愿进程退出的相关联信号 SIGINT (ctrl + c) G3log不做处理。

致命信号可以被 disabled 或changed/added .

Linux 堆栈的一个示例,如致命示例的输出所示g3log-FATAL-sigsegv*. ```***** FATAL SIGNAL RECEIVED ******* "Received fatal signal: SIGSEGV(11) PID: 6571

***** SIGNAL SIGSEGV(11)

******* STACKDUMP *******
        stack dump [1]  ./g3log-FATAL-sigsegv() [0x42a500]
        stack dump [2]  /lib/x86_64-linux-gnu/libpthread.so.0+0x10340 [0x7f83636d5340]

        stack dump [3]  ./g3log-FATAL-sigsegv : example_fatal::tryToKillWithAccessingIllegalPointer(std::unique_ptr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::default_delete<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >)+0x119 [0x4107b9]
        stack dump [4]  ./g3log-FATAL-sigsegvmain+0xdec [0x40e51c]
        stack dump [5]  /lib/x86_64-linux-gnu/libc.so.6__libc_start_main+0xf5 [0x7f8363321ec5]
        stack dump [6]  ./g3log-FATAL-sigsegv() [0x40ffa2]

Exiting after fatal event  (FATAL_SIGNAL). Fatal type:  SIGSEGV
Log content flushed sucessfully to sink

"
g3log g3FileSink shutdown at: 16:33:18

```

自定义致命处理-覆盖默认值

默认情况下,致命信号定义在 https://github.com/KjellKod/g3log/tree/master/src/g3log.cpp as

SIGABRT
SIGFPE
SIGILL
SIGSEGV
SIGTERM

如果您想定义自己的一组致命信号,请覆盖默认信号,那么可以这样做,如src/g3log/crashhandler.hpp

// Example when SIGTERM is skipped due to ZMQ usage
g3::overrideSetupSignals({ {SIGABRT, "SIGABRT"}, 
                           {SIGFPE, "SIGFPE"},
                           {SIGILL, "SIGILL"},
                           {SIGSEGV, "SIGSEGV"}});

前致命钩hook

可以定义一个自定义回调函数,该函数将在致命信号处理重新发出fatal 信号。请查阅 src/g3log/g3log.hpp 获取更多细节

// Example of how to enforce important shutdown cleanup even in the event of a fatal crash: 
g3::setFatalPreLoggingHook([]{ cleanup(); });

禁用致命处理

可以使用CMake选项禁用致命信号处理: ENABLE_FATAL_SIGNALHANDLING. 请查阅 Options.cmake 获取更多细节

PID1致命信号建议

如果你在一个PID1进程上使用g3log,那么你绝对应该提供自己的信号处理(参考:第269期),因为g3log在恢复了该信号的前一个信号处理程序之后重新发射该致命信号。PID1处理完毕关闭一个正常的致命信号的进程,所以在这样的信号后退出PID1进程的选择必须由编码器作出,而不是由g3log作出。

Windows

Windows致命处理也像Linux一样处理致命信号。除了致命的信号之外,它还处理未定义的异常,向量异常。Windows致命处理是在crashhandler.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/crashhandler.hpp), crashhandler_windows.cpp, stacktrace_windows.hpp, stacktrace_windows.cpp

Windows堆栈转储的一个示例,如致命示例的输出所示 g3log-FATAL-sigsegv.

黎明就在眼前

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【日志工具】g3log_4_API接口描述 的相关文章

随机推荐