一个轻量级的C++log日志库

一、简介

为了自己使用写的一个简单日志库,使用仅需包含一个头文件,支持Windows和Linux平台,支持多线程控制台输出以及写日志文件。

二、调用方式

#include "hdlog.h"//设置日志级别hdlog::SetLevel(hdlog::LogLevel::Info);//为Info时,以下函数将不会在控制台输出hdlog::trace("this is a {} test.", "trace");hdlog::debug("this is a {} test.", "debug");
//以下函数会在控制台输出hdlog::info("this is a {} test.", "info");hdlog::warn("this is a {} test.", "warn");hdlog::error("this is a {} test.", "error");
//设置分隔符, 默认为"{}"hdlog::SetPattern("[]");hdlog::info("this is a [] test.", "pattern");//写日志文件hdlog::trace_to_file("log.txt", "this is a {} test.", "file");hdlog::debug_to_file("log.txt", "this is a {} test.", "file");hdlog::info_to_file("log.txt", "this is a {} test.", "file");hdlog::warn_to_file("log.txt", "this is a {} test.", "file");hdlog::error_to_file("log.txt", "this is a {} test.", "file");

undefined

三、结果显示

一个轻量级的C++log日志库

一个轻量级的C++log日志库

四、hdlog.h

#ifndef HDLOG_H
#define HDLOG_H

#pragma once

#ifdef _WIN32
#include 
#include 
#else
//#include 
#include
#include #include #include #define RESET "\033[0m" #define BLACK "\033[30m" /* Black */ #define RED "\033[31m" /* Red */ #define GREEN "\033[32m" /* Green */ #define YELLOW "\033[33m" /* Yellow */ #define BLUE "\033[34m" /* Blue */ #define MAGENTA "\033[35m" /* Magenta */ #define CYAN "\033[36m" /* Cyan */ #define WHITE "\033[37m" /* White */ #define BOLDBLACK "\033[1m\033[30m" /* Bold Black */ #define BOLDRED "\033[1m\033[31m" /* Bold Red */ #define BOLDGREEN "\033[1m\033[32m" /* Bold Green */ #define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */ #define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */ #define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */ #define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */ #define BOLDWHITE "\033[1m\033[37m" /* Bold White */ #endif #include #include #include #include #include #include <string> #include #include #include namespace hdlog { enum class LogLevel { Trace, Debug, Info, Warn, Error }; static std::mutex io_mutex; static std::map<:>string, std::mutex> file_mutex; static LogLevel level = LogLevel::Info; static std::string pattern = "{}"; static const std::string enumstring[] = {"Trace", "Debug", "Info", "Warn", "Error"}; inline std::string GetSystemTime() { #ifdef _WIN32 time_t tNowTime; time(&tNowTime); //struct tm t; tm* tLocalTime = localtime(&tNowTime); char szTime[30] = { '\0' }; strftime(szTime, 30, "[%Y-%m-%d %H:%M:%S", tLocalTime); std::string strTime = szTime; SYSTEMTIME t; GetLocalTime(&t); int ms = t.wMilliseconds; if (ms < 10) { strTime += ".00" + std::to_string(t.wMilliseconds); } else if (ms < 100) { strTime += ".0" + std::to_string(t.wMilliseconds); } else { strTime += "." + std::to_string(t.wMilliseconds); } strTime += "]"; return strTime; #else //std::chrono::time_point<:chrono::system_clock> tp = std::chrono::time_point_cast<:chrono::milliseconds>(std::chrono::system_clock::now()); //auto tmp = std::chrono::duration_cast<:chrono::milliseconds>(tp.time_since_epoch()); //std::time_t timestamp = tmp.count(); //uint64_t milli = timestamp; //milli += (uint64_t)8 * 60 * 60 * 1000; //auto mTime = std::chrono::milliseconds(milli); //tp = std::chrono::time_point<:chrono::system_clock>(mTime); //auto tt = std::chrono::system_clock::to_time_t(tp); //std::tm* now = std::gmtime(&tt); //char rst[27] = { 0 }; //sprintf(rst, "[%04d-%02d-%02d %02d:%02d:%02d.%03d]", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, std::atoi(std::to_string(timestamp % 1000000).substr(3, 3).c_str()));
     
struct tm* now;
     struct timeval time;,>,>

gettimeofday(&time, NULL);
now = localtime(&time.tv_sec);

char rst[27] = { 0 };
if (NULL != now)
{
sprintf(rst, “[%04d-%02d-%02d %02d:%02d:%02d.%03d]”, now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, time.tv_usec/1000);
}

return rst;
#endif
    }

    inline std::vector<:>string> split(std::string str, std::string pattern)
    {
        std::string::size_type pos;
        std::vector<:>string> result;
        str += pattern;//扩展字符串以方便操作
        int size = str.size();

        for (int i = 0; i < size; i++)
        {
            pos = str.find(pattern, i);
            if (pos < size)
            {
                std::string s = str.substr(i, pos - i);
                result.push_back(s);
                i = pos + pattern.size() - 1;
            }
        }
        return result;
    }

    inline bool Exist(const char *name)
    {
#ifdef _WIN32
        return _access(name, 0) != -1;
#else
        int r = access(name, F_OK);
        return r == 0;
#endif // linux

        return true;
    }

    inline bool WriteToFile(std::string filename, std::string content)
    {
        std::ofstream file(filename, std::ios::binary | std::ios::app);

        if (file.good())
        {
            file << content << "\n";
            file.close();

            return true;
        }
        else
        {
            return false;
        }
    }

    inline void SetLevel(LogLevel Level)
    {
        std::lock_guard<:mutex> guard(io_mutex);
        level = Level;
    }

    inline void SetPattern(std::string pat)
    {
        std::lock_guard<:mutex> guard(io_mutex);
        pattern = pat;
    }

    inline void Clear()
    {
        std::lock_guard<:mutex> guard(io_mutex);
        file_mutex.clear();
    }

    inline std::ostream& Red(std::ostream& s)
    {
#ifdef _WIN32
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
#else
        s << BOLDRED;
#endif
        return s;
    }

    inline std::ostream& Yellow(std::ostream& s)
    {
#ifdef _WIN32
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
#else
        s << BOLDYELLOW;
#endif
        return s;
    }

    inline std::ostream& Blue(std::ostream& s)
    {
#ifdef _WIN32
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
#else
        s << BOLDBLUE;
#endif
        return s;
    }

    inline std::ostream& Green(std::ostream& s)
    {
#ifdef _WIN32
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
#else
        s << BOLDGREEN;
#endif
        return s;
    }

    inline std::ostream& White(std::ostream& s)
    {
#ifdef _WIN32
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE);
#else
        s << BOLDWHITE;
#endif
        return s;
    }

    inline std::ostream& Reset(std::ostream& s)
    {
#ifdef _WIN32
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE);
#else
        s << RESET;
#endif
        return s;
    }

    template
    inline void readParas(std::vector<:>string>& content, T&& args)
    {
        std::stringstream ss;
        ss << args;
        std::string s = ss.str();
        content.push_back(s);
    }

    inline void Log(std::vector<:>string>& content)
    {
    }

    template
    inline void Log(std::vector<:>string>& content, T&& first, Args&&... args)
    {
        readParas(content, std::forward(first));
        Log(content, std::forward(args)...);
    }

    template
    inline void level_to_out(std::string content, LogLevel Level, Args... args)
    {
        try
        {
            std::lock_guard<:mutex> guard(io_mutex);
            if (level > Level) return;

            std::vector<:>string> cs = split(content, pattern);

            int paramcount = 0;
            paramcount = sizeof...(args);

            int amount = cs.size();

            if (Level == LogLevel::Trace)
            {
                std::cout << GetSystemTime().c_str() << " [" << White << enumstring[(int)Level] << Reset << "] ";
            }
            else if (Level == LogLevel::Debug)
            {
                std::cout << GetSystemTime().c_str() << " [" << Blue << enumstring[(int)Level] << Reset << "] ";
            }
            else if (Level == LogLevel::Warn)
            {
                std::cout << GetSystemTime().c_str() << " [" << Yellow << enumstring[(int)Level] << Reset << "] ";
            }
            else if (Level == LogLevel::Error)
            {
                std::cout << GetSystemTime().c_str() << " [" << Red << enumstring[(int)Level] << Reset << "] ";
            }
            else
            {
                std::cout << GetSystemTime().c_str() << " [" << Green << enumstring[(int)Level] << Reset << "] ";
            }

            if (paramcount == 0 || amount == 1)
            {
                std::cout << content << std::endl;
            }
            else
            {
                std::vector<:>string> paramlist;

                Log(paramlist, args...);

                if (amount - 1 < paramcount)
                {
                    for (int i = 0; i < amount - 1; ++i)
                    {
                        std::cout << cs[i] << paramlist[i];
                    }
                }
                else
                {
                    for (int i = 0; i < paramcount; ++i)
                    {
                        std::cout << cs[i] << paramlist[i];
                    }

                    for (int i = paramcount; i < amount - 1; ++i)
                    {
                        std::cout << cs[i] << pattern;
                    }
                }

                std::cout << cs[amount - 1] << std::endl;
            }
        }
        catch (std::exception& ex)
        {
            std::cout << GetSystemTime().c_str() << " [" << Red << "Error" << Reset << "] " << ex.what() << std::endl;
        }
    }

    template
    inline void level_to_file(std::string filename, std::string content, LogLevel loglevel, Args... args)
    {
        try
        {
            std::lock_guard<:mutex> guard(file_mutex[filename]);

            if (level > loglevel) return;

            std::vector<:>string> cs = split(content, pattern);

            std::string filedata = GetSystemTime() + " [" + enumstring[(int)loglevel] + "] ";
            int paramcount = 0;
            paramcount = sizeof...(args);

            int amount = cs.size();

            if (paramcount == 0 || amount == 1)
            {
                filedata += content;
            }
            else
            {
                std::vector<:>string> paramlist;

                Log(paramlist, args...);

                if (amount - 1 < paramcount)
                {
                    for (int i = 0; i < amount - 1; ++i)
                    {
                        filedata += cs[i] + paramlist[i];
                    }
                }
                else
                {
                    for (int i = 0; i < paramcount; ++i)
                    {
                        filedata += cs[i] + paramlist[i];
                    }

                    for (int i = paramcount; i < amount - 1; ++i)
                    {
                        filedata += cs[i] + pattern;
                    }
                }

                filedata += cs[amount - 1];
            }

            if (!WriteToFile(filename, filedata))
            {
                std::cout << GetSystemTime().c_str() << " [" << Red << "Error" << Reset << "] " << "Write log file failed!" << std::endl;
            }
        }
        catch (std::exception& ex)
        {
            std::cout << GetSystemTime().c_str() << " [" << Red << "Error" << Reset << "] " << ex.what() << std::endl;
        }
    }

    template
    inline void trace(std::string content, Args... args)
    {
        level_to_out(content, LogLevel::Trace, args...);
    }

    template
    inline void debug(std::string content, Args... args)
    {
        level_to_out(content, LogLevel::Debug, args...);
    }

    template
    inline void info(std::string content, Args... args)
    {
        level_to_out(content, LogLevel::Info, args...);
    }

    template
    inline void warn(std::string content, Args... args)
    {
        level_to_out(content, LogLevel::Warn, args...);
    }

    template
    inline void error(std::string content, Args... args)
    {
        level_to_out(content, LogLevel::Error, args...);
    }

    template
    inline void trace_to_file(std::string filename, std::string content, Args... args)
    {
        level_to_file(filename, content, LogLevel::Trace, args...);
    }

    template
    inline void debug_to_file(std::string filename, std::string content, Args... args)
    {
        level_to_file(filename, content, LogLevel::Debug, args...);
    }

    template
    inline void info_to_file(std::string filename, std::string content, Args... args)
    {
        level_to_file(filename, content, LogLevel::Info, args...);
    }

    template
    inline void warn_to_file(std::string filename, std::string content, Args... args)
    {
        level_to_file(filename, content, LogLevel::Warn, args...);
    }

    template
    inline void error_to_file(std::string filename, std::string content, Args... args)
    {
        level_to_file(filename, content, LogLevel::Error, args...);
    }
}

#endif

Original: https://www.cnblogs.com/Clark-Zhang/p/15699274.html
Author: 朔月の流光
Title: 一个轻量级的C++log日志库

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/710834/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球