用C++写的一个简单的Log类

这是参考网上的一个了例子【一个简易的C++日志记录类】写的,我的这个不需要boost,而是改成了用windows API。

这个Log类,使用了单例模式。思路是单独创建一个线程,获取log文本,并将其写入到文件中。

由于是多线程,所以要注意线程同步。

代码

★头文件:


MyLogger.h

#ifndef __INFO_LOGGER__
#define __INFO_LOGGER__

#include <string>
#include <time.h>
#include <stdio.h>

#include <windows.h>

#define MAX_STR_BUF_LEN      30000 //log缓冲
#define TIME_TO_WRITE_LOG    5000  //
enum LOG_LEVLE{
    LEVEL_NO = 0,
    LEVEL_DEBUG,
    LEVEL_ERROR
};

class CInfoLogger{
public:
    static CInfoLogger *instace();

    std::string LogInfo(LOG_LEVLE level,char *fmt,...); 

    std::string LogInfo(LOG_LEVLE level,std::string);

    void EnterFunction(std::string function) {
        LogInfo(LEVEL_ERROR,"Enter function:" + function);
    }

    void EnterFunction(const char *function) {
        LogInfo(LEVEL_ERROR,"Enter function:%s ", function);
    }

    void LeaveFunction(std::string function) {
        LogInfo(LEVEL_ERROR,"Leave function:" + function);
    }

    void LeaveFunction(const char * function) {
        LogInfo(LEVEL_ERROR,"Leave function:%s",function);
    }

    void SetExit() {m_bRun = false;}    

    enum TIME_STRING_MODE{
        FOR_FILE_NAME,
        FOR_TEXT
    };

    std::string GetCurTimeToString(TIME_STRING_MODE mod) {
        char tmp[66];
        SYSTEMTIME sys;
        GetLocalTime(&sys);
        if (mod == FOR_TEXT) {//写入log时用的时间格式
            _snprintf(tmp,sizeof(tmp),"%d/%02d/%02d %02d:%02d:%02d.%04d "    
            ,sys.wYear,sys.wMonth,sys.wDay,sys.wHour,sys.wMinute,sys.wSecond,sys.wMilliseconds);    
            std::string str(tmp);    
            return (str);
        } else if (mod == FOR_FILE_NAME) {//创建文件时用的时间格式,需要用到下划线
            _snprintf(tmp,sizeof(tmp),"%d_%02d_%02d %02d_%02d_%02d"
            ,sys.wYear,sys.wMonth,sys.wDay,sys.wHour,sys.wMinute,sys.wSecond);
            std::string str(tmp);
            return (str);
        }
    }

    ~CInfoLogger(){
        SetExit();
        if (_instance != NULL) {
            delete _instance;
            _instance = NULL;
        }
    }

    const char * GetLogFileName() {
        return  m_strLogFileName.c_str();
    }

    void setLogLevel(LOG_LEVLE logLevel) {
        if ((logLevel == LEVEL_NO)||(logLevel == LEVEL_DEBUG)||(logLevel == LEVEL_ERROR)) {
            m_LogLevel = logLevel;
        }
    }

    LOG_LEVLE getLogLevel() {
        return m_LogLevel;
    }
    static void lock() { m_lock = true;}

    static void unlock() {m_lock = false;}

    static bool isLock() {return m_lock;}

private:
    static CInfoLogger *_instance;
    static bool m_lock;

    HANDLE m_threadHandle;
    bool m_bRun;
    std::string m_strLogFileName;
    std::string m_strWriteStrInfo;

    LOG_LEVLE m_LogLevel;
    CInfoLogger(void);

    void WriteLog(LOG_LEVLE level,std::string strLog);

    void WriteLogToFile();

    static DWORD WINAPI LogProcStart(PVOID pArg);

};


#endif

★cpp文件:

MyLogger.cpp
#include "MyLogger.h"

CInfoLogger * CInfoLogger::_instance = NULL;//初始化静态变量
bool CInfoLogger::m_lock = false;//初始化静态变量

CInfoLogger::CInfoLogger() {
    m_strWriteStrInfo = "";
    m_strLogFileName = "C:\\Run_" + GetCurTimeToString(FOR_FILE_NAME) +".log";
    m_LogLevel = LEVEL_NO;
    m_bRun = true;
    m_threadHandle = CreateThread(NULL,0,LogProcStart,this,0,NULL);
}

DWORD CInfoLogger::LogProcStart(PVOID pArg) {

    CInfoLogger * CL = NULL;
    CL = (CInfoLogger * )pArg;
    int nCount = 1;
    clock_t preSaveTime = clock();
    while(CL->m_bRun) {
        Sleep(250);
        if ((clock() - preSaveTime ) > TIME_TO_WRITE_LOG) {//开始往文件写的间隔时间
            preSaveTime = clock();
            CL->WriteLogToFile();
        }
    }
    printf("exit LogProcStart\n");
    return 1;
}

void CInfoLogger::WriteLog(LOG_LEVLE level,std::string strLog) {
    //if (!m_strWriteStrInfo.empty()){
        m_strWriteStrInfo += GetCurTimeToString(FOR_TEXT);
        if (level == LEVEL_DEBUG) {
            m_strWriteStrInfo += " Debug ";
        }
        if (level == LEVEL_ERROR) {
            m_strWriteStrInfo += " Error ";
        }
        m_strWriteStrInfo += strLog;
        m_strWriteStrInfo += "\n";
    //}

    if (m_strWriteStrInfo.size() > MAX_STR_BUF_LEN) {
        WriteLogToFile();
    }
}

void CInfoLogger::WriteLogToFile() {
    HANDLE hFile;
    DWORD NumberOfBytesRead;
    if (!isLock()) {
        lock();
        hFile = ::CreateFile(m_strLogFileName.c_str(),GENERIC_READ|GENERIC_WRITE,0,NULL,FILE_APPEND_DATA ,FILE_ATTRIBUTE_NORMAL,NULL);
        if (hFile != INVALID_HANDLE_VALUE) {
            try {
                SetFilePointer(hFile,0,NULL,FILE_END); 
                WriteFile(hFile,m_strWriteStrInfo.c_str(),m_strWriteStrInfo.size(),&NumberOfBytesRead,NULL);
                printf("write file success \n");
                m_strWriteStrInfo = "";
            }catch(std::exception e) {
                 printf("write file error %s\n",e.what());
            }
        } else {
            printf("open file error\n");
        }
        CloseHandle(hFile);
        unlock();
    }

}

///////////////////////////////////////
CInfoLogger *CInfoLogger::instace() {
    if (!isLock()) {  //由于用的单例模式,所以整个线程只有这一个对象。如果不用锁的话
        lock();       //万一两个线程都判断到_instance == NULL,会创建2个对象,违反单一原则
                      //最好用Mutex,等我有空在进行修改
        if (_instance == NULL) {
            _instance = new CInfoLogger();
        }
        unlock();
    }
    return _instance;
}

std::string CInfoLogger::LogInfo(LOG_LEVLE level,char *fmt,...) {
    char out[1024];
    va_list body;
    va_start(body,fmt);
    vsprintf(out,fmt,body);
    va_end(body);

    std::string str(out);
    if (level <= getLogLevel()) {
        return str;
    }
    WriteLog(level,str);
    OutputDebugStringA(out);
    OutputDebugStringA("\n");
    return str;
}

std::string CInfoLogger::LogInfo(LOG_LEVLE level,std::string info) {        
    if (level <= getLogLevel()) {
        return info;
    }
    WriteLog(level,info);
    OutputDebugStringA(info.c_str());
    OutputDebugStringA("\n");
    return info;
}
/////////////////////////////
//int main () {
//    CInfoLogger *d  = CInfoLogger::instace();
//    int i = 0;
//    while(1){
//        i++;
//        Sleep(1000);
//        char * a = "sdgag;agpo";
//        d->LogInfo(LEVEL_ERROR,"times i = %s",a);
//        //d->SetExit();
//    }
//    return 1;
//}

/*
* other c file,"extern void CLogInfo(int Level,const char * fmt,...);" ok
* 为了让c文件引用C++的函数  
*
*/
//#ifdef __cplusplus 
//extern "C"{
//#endif
//void CLogInfo(int Level,const char * fmt,...) {
//  char buf[1024];
//  va_list body;
//  va_start(body,fmt);
//  vsprintf(buf,fmt,body);
//  va_end(body);
//  CInfoLogger::instace()->LogInfo((LOG_LEVLE)Level,buf);      
//}

//#ifdef __cplusplus
//}
//#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值