mini logger for c++
阅读原文时间:2023年07月09日阅读:1

水平太菜,最近捣鼓这个 log,折腾了好一会。由于之前都是用 std::cout,不能满足同时输出到屏与文件的目的,故经过一番搜索,在stackoverflow 找到了答案,现总结如下:

  1. 头文件 logger.hpp, 代码如下:

    #ifndef __LOGGER
    #define __LOGGER

    #include
    #include
    #include
    #include
    #include

    #include

    typedef enum
    {
    EMERG = LOG_EMERG, /* system is unusable / ALERT = LOG_ALERT, / action must be taken immediately / CRIT = LOG_CRIT, / critical conditions / ERROR = LOG_ERR, / error conditions / WARNING = LOG_WARNING, / warning conditions / NOTICE = LOG_NOTICE, / normal but significant condition / INFO = LOG_INFO, / informational / DEBUG = LOG_DEBUG / debug-level messages */
    } Severity;

    static std::string severity_str[] = {
    [EMERG] = "EMERG", /* system is unusable / [ALERT] = "ALERT", / action must be taken immediately / [CRIT] = "CRIT", / critical conditions / [ERROR] = "ERROR", / error conditions / [WARNING] = "WARNING", / warning conditions / [NOTICE] = "NOTICE,", / normal but significant condition / [INFO] = "INFO", / informational / [DEBUG] = "DEBUG", / debug-level messages */
    };

    class Logger
    {
    private:
    Logger() {}

    ~Logger() {}
    
    /* forbide copy */
    Logger &operator=(const Logger &) = delete;
    Logger(const Logger &) = delete;

    private:
    static Severity m_log_level; /* only show log that with level
    not higher than m_log_level / static bool m_sync_syslog; / sync log to syslog ? / static bool m_sync_stdout; / sync log to stdout / static bool m_sync_file; / sync log to file / static std::string m_logfile; / file to save log */
    static Severity m_severity;
    static std::string m_filename;
    static int m_line;
    static std::string m_funcname;
    std::stringstream ss;
    std::mutex m_lk;

    public:
    static Logger &Instance(Severity s = Severity::INFO,
    const char *f = "", int l = 0,
    const char *fc = "")
    {
    static Logger instance_;

        instance_.m_severity = s;
        instance_.m_filename = f;
        instance_.m_line = l;
        instance_.m_funcname = fc;
        return instance_;
    }
    
    static void Init(bool sync_flag, const char *logfile)
    {
        m_sync_file = sync_flag;
        m_logfile = logfile;
    }
    
    static void Init(bool sync_stdout, bool sync_file, bool sync_syslog)
    {
        m_sync_file = sync_file;
        m_sync_stdout = sync_stdout;
        m_sync_syslog = sync_syslog;
    }
    
    static void Init(const char *label = "LOGGER",
                     Severity s = Severity::INFO,
                     bool sync_syslog = false)
    {
        m_log_level = s;
        if (sync_syslog)
        {
            m_sync_syslog = true;
            openlog(label, LOG_CONS | LOG_NDELAY, LOG_USER | LOG_LOCAL1);
        }
    }
    
    Logger &operator<<(const char *t)
    {
        std::lock_guard<std::mutex> _lk(m_lk);
        ss << t;
        return *this;
    }
    
    template <typename T>
    Logger &operator<<(const T &t)
    {
        std::lock_guard<std::mutex> _lk(m_lk);
        ss << t;
        return *this;
    }
    
    Logger &operator<<(std::ostream &(*os)(std::ostream &))
    {
        dump_line();
        return *this;
    }
    
    void dump_line()
    {
        std::lock_guard<std::mutex> _lk(m_lk);
        time_t rawtime;
        char now[80];
    time(&amp;rawtime);
    struct tm *tt = localtime(&amp;rawtime);
    
    strftime(now, 80, "%Y-%m-%d %H:%M:%S", tt);
    
    std::string obuf = "";
    if (!m_filename.empty())
    {
        obuf += "[" + m_filename + ":" +
                std::to_string(m_line) + " " +
                m_funcname + "]";
    }
    
    obuf += "[" + std::string(now) + "][" +
            severity_str[static_cast&lt;int&gt;(m_severity)] + "] ";
    
    obuf += ss.str();
    
    if (m_log_level &gt;= m_severity)
    {
        /* syslog */
        if (m_sync_syslog)
            syslog(LOG_USER | m_severity, "%s", obuf.c_str());
    
        /* stdout/stderr */
        if (m_sync_stdout)
            std::cerr &lt;&lt; obuf &lt;&lt; std::endl;
    
        if (m_sync_file)
        {
            std::ofstream fout(m_logfile, std::ios::app);
            fout.write(obuf.c_str(), obuf.length());
            fout.close();
        }
    }
    
    ss.str("");
    m_funcname = "";
    m_filename = "";
    m_line = 0;
    } template <typename T> void operator()(T t) { ss << t; dump_line(); } template <typename T, typename... Args> void operator()(const T &t, const Args &... args) { ss << t; (*this)(args...); }

    };

    #define ENDL std::endl

    #ifndef NDEBUG
    #define LOG(v) Logger::Instance(v, FILE, LINE, func)
    #define LOGI Logger::Instance(Severity::INFO, FILE, LINE, func)
    #define LOGV Logger::Instance(Severity::NOTICE, FILE, LINE, func)
    #define LOGD Logger::Instance(Severity::DEBUG, FILE, LINE, func)
    #define LOGW Logger::Instance(Severity::WARNING, FILE, LINE, func)
    #define LOGE Logger::Instance(Severity::ERROR, FILE, LINE, func)

    #define LOGFI(a, v…) Logger::Instance(Severity::INFO, FILE, LINE, func)(a, ##v)
    #define LOGFV(a, v…) Logger::Instance(Severity::NOTICE, FILE, LINE, func)(a, ##v)
    #define LOGFD(a, v…) Logger::Instance(Severity::DEBUG, FILE, LINE, func)(a, ##v)
    #define LOGFW(a, v…) Logger::Instance(Severity::WARNING, FILE, LINE, func)(a, ##v)
    #define LOGFE(a, v…) Logger::Instance(Severity::ERROR, FILE, LINE, func)(a, ##v)

    #else
    #define LOG(v) Logger::Instance(v)
    #define LOGI Logger::Instance()
    #define LOGV Logger::Instance()
    #define LOGD Logger::Instance()
    #define LOGW Logger::Instance()
    #define LOGE Logger::Instance()

    #define LOGFI(a, v…) Logger::Instance()(a, ##v)
    #define LOGFV(a, v…) Logger::Instance()(a, ##v)
    #define LOGFD(a, v…) Logger::Instance()(a, ##v)
    #define LOGFW(a, v…) Logger::Instance()(a, ##v)
    #define LOGFE(a, v…) Logger::Instance()(a, ##v)
    #endif // NDEBUG

    #define LINE LOGI << FILE << LINE << ENDL
    #endif //__LOGGER

cpp 源码文件

#include "logger.h"

Severity Logger::m_log_level = Severity::INFO; /* only show log that with level
                                    not higher than m_log_level */
bool Logger::m_sync_syslog = false;            /* sync log to syslog ? */
bool Logger::m_sync_stdout = true;             /* sync log to stdout */
bool Logger::m_sync_file = false;              /* sync log to file */
std::string Logger::m_logfile;
Severity Logger::m_severity = Severity::INFO;
std::string Logger::m_filename;
int Logger::m_line;
std::string Logger::m_funcname;

头文件提供了5个宏,实现了5种log级别。目前没有加入色彩显示功能。如果定义了 DEBUG_MODE 宏,会有文件,行号等信息。

  1. 使用

    #include "logger.h"

    using namespace LOGGER;

    int main()
    {
    Logger::Init(Severity::DEBUG, "./log.log");
    LOG(Severity::ERROR) << "Severity error" << std::endl;
    LOGI << "INFO LOG" << std::endl;
    LOGV << "VERBOSE LOG" << std::endl;
    LOGD << "DEBUG LOG" << std::endl;
    LOGW << "WARNNING LOG" << std::endl;
    LOGE << "ERROR LOG" << std::endl;

    LOGFI ("INFO LOG");
    LOGFV ("VERBOSE LOG");
    LOGFD ("DEBUG LOG");
    LOGFW ("WARNNING LOG");
    LOGFE ("ERROR LOG");
    
    return 0;

    }

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章