C++多线程日志类

#ifndef LOGGER_H
#define LOGGER_H

#include <thread>
#include <mutex>
#include <queue>
#include <string>

class Logger
{
public:
    enum class LogLevel
    {
        ERROR,
        INFO,
        DEBUG
    };

    typedef struct _stLogInfo
    {
        std::string info;
        LogLevel level;
    }stLogInfo;

private:
    Logger();
    ~Logger();
    static void createInstance();

    std::string getLogLevelString(LogLevel level);
    void processEntries();
    void setLogFile(std::string file);
    std::string getLogFile();
    std::string getFileName();
public:
    static Logger* getInstance();

    Logger(const Logger& obj) = delete ;
    Logger& operator=(const Logger& obj) = delete ;

    void setLogLevel(LogLevel level);
    void log(std::string entry,LogLevel level);

private:
    static Logger* m_pInstance;
    std::mutex m_mutex;
    std::condition_variable m_condVar;
    std::queue<stLogInfo> m_queue;
    std::thread m_thread;
    bool m_bExit;
    LogLevel m_logLevel = LogLevel::ERROR;
    std::string m_logFile;

    class DestoryPtr
    {
    public:
        ~DestoryPtr()
        {
            if(Logger::m_pInstance)
            {
                delete  Logger::m_pInstance;
                Logger::m_pInstance = nullptr;
            }
        }
    };
};

#endif // LOGGER_H

 

#include "logger.h"
#include <fstream>
#include <QDateTime>
#include <ctime>
#include <iostream>
using namespace std;

Logger* Logger::m_pInstance = nullptr;
once_flag g_flag;

Logger::Logger()
    :m_bExit(false)
{
    m_thread = thread(&Logger::processEntries,this);
}

Logger::~Logger()
{
    {
        unique_lock<mutex> lock(m_mutex);
        m_bExit = true;
        m_condVar.notify_all();
    }

    m_thread.detach();
}

void Logger::createInstance()
{
    m_pInstance = new Logger;
    static DestoryPtr desPtr;
}

std::string Logger::getLogLevelString(Logger::LogLevel level)
{
    switch (level)
    {
    case LogLevel::ERROR:
        return "ERROR";
    case LogLevel::INFO:
        return  "INFO";
    case LogLevel::DEBUG:
        return  "DEBUG";
    }

    return "Invalid log level";
}

Logger *Logger::getInstance()
{
    call_once(g_flag,createInstance);
    return m_pInstance;
}

void Logger::setLogLevel(LogLevel level)
{
    m_logLevel = level;
}

void Logger::processEntries()
{
    string file = getFileName();

    ofstream logFile(file,ios::app);
    if(logFile.fail())
    {
        //cout<<file<<"打开失败!"<<endl;
        return;
    }

    setLogFile(file);

    unique_lock<mutex> lock(m_mutex);
    while(true)
    {
        if(!m_bExit)
            m_condVar.wait(lock);

        lock.unlock();

        while (true)
        {
            lock.lock();
            if(m_queue.empty())
                break;
            else
            {
                file = getFileName();
                if(strcmp(file.c_str(),m_logFile.c_str()) != 0)
                {
                    logFile.close();
                    logFile.open(file,ios::app);
                    if(logFile.fail())
                    {
                        return;
                    }

                    setLogFile(file);
                }

                logFile<<"["<< __TIME__<<"]-->";
                logFile<<"["<<getLogLevelString(m_queue.front().level)<<"]";
                logFile<<m_queue.front().info<<endl;
                logFile.flush();
                m_queue.pop();
            }
            lock.unlock();
        }

        if(m_bExit)
        {
            logFile.close();
            break;
        }
    }
}

void Logger::setLogFile(std::string file)
{
    m_logFile = file;
}

std::string Logger::getLogFile()
{
    return m_logFile;
}

std::string Logger::getFileName()
{
    char chDate[15] = {'\0'};
    time_t now = time(NULL);
    struct tm stInfo;
    localtime_s(&stInfo,&now);

    strftime(chDate,15,"%Y-%m-%d",&stInfo);

    string file("log");
    file = chDate;
    file.append(".txt");
    return file;
}

void Logger::log(std::string entry,LogLevel level)
{
    stLogInfo stInfo;
    unique_lock<mutex> lock(m_mutex);
    if(level > m_logLevel)
        return;

    stInfo.info = entry;
    stInfo.level = level;
    m_queue.push(stInfo);

    m_condVar.notify_all();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值