文章

封装 spdlog

spdlog 是一个快速、可扩展的 c++ 日志库,它提供了简单易用的接口和灵活的配置选项。spdlog 支持多种日志级别、多线程安全,可以将日志输出到终端、文件或者其他自定义的目标。它具有高性能和低开销的特点,适用于各种规模的应用程序和系统。

获取源码

如果要将源码添加进你的工程里,请从 github 获取

1
https://github.com/gabime/spdlog
  • 如果使用的是 conan 包管理,可以从这里获取
1
https://conan.io/center/recipes/spdlog

封装 spdlog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// 单例模板
#include <iostream>
#include <string>

template<class T>
class Singleton
{
protected:
    Singleton(const Singleton &) = delete;
    Singleton &operator=(const Singleton &) = delete;
    Singleton() = default;
    ~Singleton() = default;

public:
    template<typename... Args>
    static T &instance(Args &&...args)
    {
        static T obj(std::forward<Args>(args)...);
        return obj;
    }
};



// spdlog wraper
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h"

#include <memory>

#define LOG_TOPIC "app"                               // 日志tag
#define LOG_FILE_NAME "./log/" LOG_TOPIC ".log"       // 日志文件名
#define LOG_FILE_SIZE 1024 * 1024 * 3                 // 3MB
#define LOG_ROTATION 3                                // 日志文件满3个时开始滚动日志
#define PATTERN  "[%Y-%m-%d %H:%M:%S.%f] [%^%L%$] %v" // 日志格式
#define LOG_FLUSH_ON spdlog::level::info              // 当打印这个级别日志时flush

#define LOGE(...) Singleton<Logger>::Instance().log_error(__VA_ARGS__)
#define LOGW(...) Singleton<Logger>::Instance().log_warn(__VA_ARGS__)
#define LOGI(...) Singleton<Logger>::Instance().log_info(__VA_ARGS__)
#define LOGD(...) Singleton<Logger>::Instance().log_debug(__VA_ARGS__)
#define LOGC(...) Singleton<Logger>::Instance().log_critical(__VA_ARGS__)

class Logger
{
private:
    std::unique_ptr<spdlog::logger> logger_;

public:
    Logger()
    {
        auto function = [&]() {
            auto stdout_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
            auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(LOG_FILE_NAME, LOG_FILE_SIZE, LOG_ROTATION);
            std::vector<spdlog::sink_ptr> sinks{stdout_sink, rotating_sink};
            logger_ = std::make_unique<spdlog::logger>(LOG_TOPIC, sinks.begin(), sinks.end());
            logger_->set_pattern(PATTERN);
            if (is_debug_mode())
            {
                logger_->set_level(spdlog::level::debug);
            }
            else
            {
                logger_->set_level(spdlog::level::info);
            }
            logger_->flush_on(LOG_FLUSH_ON);
        };
        try
        {
            function();
        } catch (...)
        {
            std::cout << "init failed" << std::endl;
        }
    }

    template<typename... Args>
    inline void log_error(const char *fmt, Args... args)
    {
        logger_->error(fmt, args...);
    }

    template<typename... Args>
    inline void log_warn(const char *fmt, Args... args)
    {
        logger_->warn(fmt, args...);
    }

    template<typename... Args>
    inline void log_info(const char *fmt, Args... args)
    {
        logger_->info(fmt, args...);
    }

    template<typename... Args>
    inline void log_debug(const char *fmt, Args... args)
    {
        logger_->debug(fmt, args...);
    }

    template<typename... Args>
    inline void log_critical(const char *fmt, Args... args)
    {
        logger_->critical(fmt, args...);
    }

private:
    bool is_debug_mode()
    {
        char *var = getenv("debug");
        if (nullptr == var)
        {
            return false;
        }
        if (0 == strcmp(var, "on"))
        {
            return true;
        }
        return false;
    }
};
本文由作者按照 CC BY 4.0 进行授权

© ziqing. 保留部分权利。

纸上得来终觉浅,绝知此事要躬行!