g3log源代码学习

g3log是一个高性能C++日志库,其代码十分精简和可读性强,本文将从3个方面详细介绍g3log源代码学习。

一、g3log源代码整体架构

g3log的整体架构十分清晰,其中有3个核心组件,分别是Logger、LogWorker和Sink。Logger负责产生日志记录,LogWorker是一个异步的队列,负责将Logger产生的日志记录进行处理和缓存,最终交由Sink进行输出。

class Logger
{
public:
    Logger(const std::string& loggerId, SinkHandle worker, LogLevel minimumLevel)
    {
        ...
    }
    virtual ~Logger();

    void log(const LogMessage& message)
    {
        ...
    }

    ...
};
class LogWorker
{
public:
    ...
    LogWorker(std::string id, std::unique_ptr sink, const int& maxMessageSize, const int& workerCount);
    virtual ~LogWorker();

    inline int getWorkerId() const noexcept { return worker_id_; }
    void stop();
    void send(std::unique_ptr);
    bool try_send(std::unique_ptr);
    void sendImmediate(std::unique_ptr);

    template  inline void send(T&& message, const LEVELS& level)
    {
        send(LogMessage(std::forward(message), getWorkerId(), level), true);
    }

    ...
};
class Sink
{
public:
    virtual ~Sink() = default;
    virtual void sink(const LogMessage& message) = 0;
};

Logger、LogWorker、Sink三个组件各司其职,代码规范且易于扩展。

二、日志级别的控制和处理

g3log中有INFO、DEBUG、WARNING、ERROR和FATAL 5个级别的日志等级,并且可以通过配置文件来设置日志等级。在代码中,对于每个日志级别都有对应的宏定义,并且都会在编译时进行一次条件判断,从而确保了日志输出的高效性。

#define INFO_IF(instance, condition)                    \
    if (condition) {                                    \
        if (auto log_message = (instance).debug()) {     \
            log_message->write().startPrint().stream()

#define DEBUG_IF(instance, condition)                   \
    if (condition) {                                    \
        if (auto log_message = (instance).debug()) {     \
            log_message->write().startPrint().stream()

#define WARNING_IF(instance, condition)                 \
    if (condition) {                                    \
        if (auto log_message = (instance).warning()) {   \
            log_message->write().startPrint().stream()

#define ERROR_IF(instance, condition)                   \
    if (condition) {                                    \
        if (auto log_message = (instance).error()) {     \
            log_message->write().startPrint().stream()

#define FATAL_IF(instance, condition)                   \
    if (condition) {                                    \
        if (auto log_message = (instance).fatal()) {     \
            log_message->write().startPrint().stream()

代码中对于每个宏定义都做了一次条件判断,只有当日志等级高于设置等级时,才会执行相应的日志操作,从而提高了日志输出性能。

三、日志输出效率的提高

g3log的异步输出机制可以提高日志系统的效率,其采用多个LogWorker来处理日志记录的缓存和输出,而且每个LogWorker维护一个RingBuffer,多个LogWorker之间可以互相切换和传输RingBuffer,从而实现了多线程并发处理。

class RingBuffer
{
public:
    RingBuffer() { clear(); }

    void push_back(const T data)
    {
        auto slot = ++_tail & _mask;
        _buffer[slot] = data;
    }

    T pop_front()
    {
        auto slot = ++_head & _mask;
        return _buffer[slot];
    }

    ...
};

在实现RingBuffer时采用了循环队列的设计,这样一来从队列头和尾部的插入和删除操作的处理速度就会非常快。

四、总结

通过对g3log源代码的学习,我们可以发现g3log的设计非常简单高效,代码规范而且易于扩展和维护。同时,其采用了异步输出机制和多线程并发处理等机制,也提高了日志系统的效率。

原创文章,作者:EZMXK,如若转载,请注明出处:https://www.506064.com/n/375558.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
EZMXK的头像EZMXK
上一篇 2025-04-29 12:49
下一篇 2025-04-29 12:49

相关推荐

发表回复

登录后才能评论