实用日志模块

来源:互联网 发布:h5软件哪个好 编辑:程序博客网 时间:2024/05/21 22:26
/******************************************************************************
 * RunnigLog.h - easy log
 *
 * Copyright (c) 2007 xxxx (Hangzhou) Software Corp. Ltd.
 *
 * DESCRIPTION:
 *     easy log file
 * Modification history:
 *     
 * 07 Jan 2009, written by Yanqingwu
 * Note: 1.you can use easy log by a macro LOG_LOG(0,0,5)
 *       2.if you want specify log path and file use LOG_LOG("C://", "name.log", 5)
 ******************************************************************************/
 
/******************************************************************************
 * include file here:
 * eg. #include <xxx.h>
 ******************************************************************************/
 
 
/******************************************************************************
 * define MACRO here:
 * eg. DEFINE XXX ()
 ******************************************************************************/
 
 
/******************************************************************************
 * define global variable here:
 * eg. tpye g_xxx;
 ******************************************************************************/
 
 
/******************************************************************************
 * define function/class/.etc here:
 * eg. void xxx();
 ******************************************************************************/


#define _LOG_ON 1

#define LOG_ERROR   -1
#define LOG_OK         0

#define LOG_MAX_NODES        50
#define LOG_MAX_MSG_LEN        260

#define LOG_LEVEL_NO          0
#define LOG_LEVEL_INFO        1
#define LOG_LEVEL_WARNING     2
#define LOG_LEVEL_DEBUG       3
#define LOG_LEVEL_ERROR          4
#define LOG_LEVEL_ALL         5

#define THREAD_EXIT_WAIT_TIME        1000


#if _LOG_ON

#define LOG_LOG(path, name, level) do {/
                                    CEasyLog log;/
                                    log.LogInst()->SetPath(path);/
                                    log.LogInst()->SetName(name);/
                                    log.LogInst()->SetLogLevel(level);/
                                    log.LogInst()->DoLog();/
                                    } while (0);

#define INFO_LOG(x) do{/
                        CEasyLog log;/
                        char szMsg[MAX_PATH] = {0};/
                        sprintf(szMsg, "%s_%d:%s/r/n",__FILE__,__LINE__,x);/
                        log.LogInst()->PutMsg(LOG_LEVEL_INFO, szMsg);/
                        }while(0);

#define WARNING_LOG(x) do{/
                            CEasyLog log;/
                            char szMsg[MAX_PATH] = {0};/
                            sprintf(szMsg, "%s_%d:%s/r/n",__FILE__,__LINE__,x);/
                            log.LogInst()->PutMsg(LOG_LEVEL_WARNING, szMsg);/
                            }while(0);

#define DEBUG_LOG(x) do{/
                        CEasyLog log;/
                        char szMsg[MAX_PATH] = {0};/
                        sprintf(szMsg, "%s_%d:%s/r/n",__FILE__,__LINE__,x);/
                        log.LogInst()->PutMsg(LOG_LEVEL_DEBUG, szMsg);/
                        }while(0);

#define ERROR_LOG(x) do{/
                        CEasyLog log;/
                        char szMsg[MAX_PATH] = {0};/
                        sprintf(szMsg, "%s_%d:%s/r/n",__FILE__,__LINE__,x);/
                        log.LogInst()->PutMsg(LOG_LEVEL_ERROR, szMsg);/
                        }while(0);

#else

#define LOG_LOG(path, name, level)
#define INFO_LOG(x)
#define WARNING_LOG(x)
#define DEBUG_LOG(x)
#define ERROR_LOG(x)

#endif


typedef struct LogMsgNode
{
    unsigned short iNum;
    struct LogMsgNode *pNext;
} LOGMSGNODE;

typedef LOGMSGNODE* LOGMSGLIST;


class CLogCriticalSection
{
public:
    CLogCriticalSection()
    {
        ::InitializeCriticalSection(&m_cs);
    }
    ~CLogCriticalSection()
    {
        ::DeleteCriticalSection(&m_cs);
    }
    bool Lock()
    {
        ::EnterCriticalSection(&m_cs);
        return true;
    }
    bool UnLock()
    {
        ::LeaveCriticalSection(&m_cs);
        return true;
    }
protected:
    CRITICAL_SECTION m_cs;
};

class CEasyLogLock
{
public:
    CEasyLogLock(CLogCriticalSection &lcs)
        :m_lcs(lcs)
    {
        m_lcs.Lock();
    }
    ~CEasyLogLock()
    {
        m_lcs.UnLock();
    }

protected:
    CLogCriticalSection &m_lcs;
};

class CRunnigLog  
{
public:
    void ReleaseLog();
    int SetLogLevel(unsigned short sLevel);
    unsigned short GetLogLevel();
    int SetPath(char *szPath);
    char* GetPath();
    int SetName(char *szName);
    char* GetName();
    bool DoLog();
    
    void PutMsg(unsigned short slevel, char *szMsg);
    void SerialMsg();
    char *GetMsg();

public:
    static CRunnigLog* Instance();
    
protected:
    CRunnigLog();
    CRunnigLog(const CRunnigLog &lg);
    CRunnigLog &operator=(const CRunnigLog &other);
    static int ThreadEntry(void **ppv)
    {
        (reinterpret_cast <CRunnigLog *> (ppv))->ThreadProc();
        return 1;
    }
    void ThreadProc();


protected:
    static CRunnigLog* _instance;
    

    CLogCriticalSection m_lcs;
    char m_szLogPath[MAX_PATH];
    char m_szLogName[MAX_PATH];
    LONG m_lLostMsgCount;
    LONG m_lRef;
    unsigned short m_sLevel;
    HANDLE m_hNewMsg;
    bool m_bRunningThread;
    HANDLE m_hThread;
    FILE* m_pStream;


    char m_ppMsgBuffer[LOG_MAX_NODES][LOG_MAX_MSG_LEN];
    int m_nMsgCount;
    int m_nMsgRead;
    int m_nMsgWrite;
};

class CEasyLog
{
public:
    CEasyLog()
    {
        m_log = CRunnigLog::Instance();
    }
    ~CEasyLog()
    {
        m_log->ReleaseLog();
    }
    CRunnigLog *LogInst()
    {
        return m_log;
    }
protected:
    CRunnigLog* m_log;
};




//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/******************************************************************************
 * RunnigLog.cpp - running log module
 *
 * Copyright (c) 2007 xxxx (Hangzhou) Software Corp. Ltd.
 *
 * DESCRIPTION:
 *     easy running log module
 * Modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 * Note: 1.
 *       2.
 ******************************************************************************/
 
/******************************************************************************
 * include file here:
 * eg. #include <xxx.h>
 ******************************************************************************/
 
 
/******************************************************************************
 * define MACRO here:
 * eg. DEFINE XXX ()
 ******************************************************************************/
 
 
/******************************************************************************
 * define global variable here:
 * eg. tpye g_xxx;
 ******************************************************************************/
 
 
/******************************************************************************
 * define function/class/.etc here:
 * eg. void xxx();
 ******************************************************************************/
#include "stdafx.h"
#include "RunnigLog.h"
#include "stdio.h"

#if _LOG_ON
CEasyLog g_EasyLog;
#endif

CRunnigLog* CRunnigLog::_instance = NULL;


/******************************************************************************
 * Function: CRunnigLog.Instance
 * Purpose: -
 *    singleton instance
 * Parameter:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
CRunnigLog* CRunnigLog::Instance()
{
    if (NULL == _instance)
    {
        _instance = new CRunnigLog;
    }
    ::InterlockedIncrement(&_instance->m_lRef);
    return _instance;
}

/******************************************************************************
 * Function: CRunnigLog.CRunnigLog
 * Purpose: -
 *    construct running log class
 * Parameter:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
CRunnigLog::CRunnigLog()
{
    m_sLevel = LOG_LEVEL_NO;
    m_lRef = 0;
    m_pStream = NULL;
    m_hNewMsg = CreateEvent(NULL, FALSE, FALSE, NULL);

    memset(m_szLogPath, 0, MAX_PATH);
    memset(m_szLogName, 0, MAX_PATH);
    strcpy(m_szLogPath, "C://");

    SYSTEMTIME t;
    ::GetLocalTime(&t);
    sprintf(m_szLogName,"%04d-%02d-%02d-%02d-%02d-%02d-%04d.txt",t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute,t.wSecond,t.wMilliseconds);


    m_lLostMsgCount = 0;
    m_nMsgCount = 0;
    m_nMsgRead = 0;
    m_nMsgWrite = 0;

    for (int j = 0; j < LOG_MAX_NODES; j++)
    {
        memset(m_ppMsgBuffer[j], 0, LOG_MAX_MSG_LEN);
    }

    m_pStream = NULL;
    m_bRunningThread = false;
    m_hThread = NULL;
}

/******************************************************************************
 * Function: CRunnigLog.ReleaseLog
 * Purpose: -
 *    realse running log
 *    it olny delete log class while reference count less than 0
 * Parameter:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
void CRunnigLog::ReleaseLog()
{
    ::InterlockedDecrement(&m_lRef);
    if (m_lRef <= 0)
    {
        m_bRunningThread = false;
        if (m_hThread)
        {
            SetEvent(m_hNewMsg);
            WaitForSingleObject(m_hThread, THREAD_EXIT_WAIT_TIME);
            CloseHandle(m_hThread);           
        }   
        SerialMsg();

        if (m_pStream)
        {
            fputs("====end log======/r/n", m_pStream);
            char szTmp[MAX_PATH] = {0};
            sprintf(szTmp, "lost msg cout: %d/r/n", m_lLostMsgCount);
            fputs(szTmp, m_pStream);
            fclose(m_pStream);
        }
        delete _instance;
        _instance = NULL;
    }
}

/******************************************************************************
 * Function: CRunnigLog.SetLogLevel
 * Purpose: -
 *    set log level
 * Parameter:
 *     unsigned short sLevel:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
int CRunnigLog::SetLogLevel(unsigned short sLevel)
{
    if (NULL == _instance)
    {
        return LOG_ERROR;
    }
    if (sLevel < LOG_LEVEL_NO
        || sLevel > LOG_LEVEL_ALL)
    {
        return LOG_ERROR;
    }
    m_sLevel = sLevel;   
    return LOG_OK;
}

/******************************************************************************
 * Function: CRunnigLog.GetLogLevel
 * Purpose: -
 *     
 * Parameter:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
unsigned short CRunnigLog::GetLogLevel()
{
    if (NULL == _instance)
    {
        return LOG_ERROR;
    }
    return m_sLevel;
}

/******************************************************************************
 * Function: CRunnigLog.SetPath
 * Purpose: -
 *     
 * Parameter:
 *     char *szPath:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
int CRunnigLog::SetPath(char *szPath)
{
    if (!szPath)
    {
        return LOG_ERROR;
    }
    if (strlen(szPath) < MAX_PATH)
    {
        strcpy(m_szLogPath, szPath);
        return LOG_OK;       
    }
    return LOG_ERROR;
}

/******************************************************************************
 * Function: CRunnigLog.GetPath
 * Purpose: -
 *     
 * Parameter:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
char *CRunnigLog::GetPath()
{
    return m_szLogPath;
}

/******************************************************************************
 * Function: CRunnigLog.SetName
 * Purpose: -
 *     
 * Parameter:
 *     char *szName:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
int CRunnigLog::SetName(char *szName)
{
    if (!szName)
    {
        return LOG_ERROR;
    }
    if (strlen(szName) < MAX_PATH)
    {
        strcpy(m_szLogName, szName);
        return LOG_OK;       
    }
    return LOG_ERROR;
}

/******************************************************************************
 * Function: CRunnigLog.GetName
 * Purpose: -
 *     
 * Parameter:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
char *CRunnigLog::GetName()
{
    return m_szLogName;
}

/******************************************************************************
 * Function: CRunnigLog.DoLog
 * Purpose: -
 *    running log thread
 * Parameter:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
bool CRunnigLog::DoLog()
{
    char szfullpath[MAX_PATH] = {0};
    strcpy(szfullpath, m_szLogPath);
    if ('//' != szfullpath[strlen(szfullpath)])
    {
        strcat(szfullpath, "//");
    }
    strcat(szfullpath, m_szLogName);
    m_pStream = fopen(szfullpath, "a+t");
    if (m_pStream)
    {
        fputs("====begin log======/r/n", m_pStream);
    }

    m_bRunningThread = true;
    DWORD dwId;
    m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadEntry, this, 0, &dwId);
    if (m_hThread)
    {
        return true;
    }
    else
    {
        fputs("failed to create log thread!/r/n", m_pStream);
    }
    return false;
}

/******************************************************************************
 * Function: CRunnigLog.PutMsg
 * Purpose: -
 *    buffer a log message
 * Parameter:
 *     unsigned short slevel:
 *     char *szMsg:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
void CRunnigLog::PutMsg(unsigned short slevel, char *szMsg)
{
    if (NULL == szMsg || 0 >= strlen(szMsg))
    {
        return;
    }
    if (slevel <= m_sLevel)
    {
        CEasyLogLock lock(m_lcs);
        if (m_nMsgCount >= LOG_MAX_NODES)
        {
            int nRead;
            int nWritecount = 0;
            while (m_nMsgCount > 0)
            {
                nRead = m_nMsgRead;
                m_nMsgRead = ++m_nMsgRead % LOG_MAX_NODES;
                m_nMsgCount--;
                //write to file
                if (m_pStream)
                {
                    fputs(m_ppMsgBuffer[nRead], m_pStream);
                    memset(m_ppMsgBuffer[nRead], 0, LOG_MAX_MSG_LEN);
                    nWritecount++;
                }       
            }
            if (nWritecount)
            {
                fflush(m_pStream);
            }
        }
        if (m_nMsgCount < LOG_MAX_NODES)
        {
            int nWrite = m_nMsgWrite;
            m_nMsgWrite = ++m_nMsgWrite % LOG_MAX_NODES;
            strncpy(m_ppMsgBuffer[nWrite], szMsg, LOG_MAX_MSG_LEN - 1);
            m_nMsgCount++;
            SetEvent(m_hNewMsg);
        }
        else
        {
            m_lLostMsgCount++;
        }
    }   
}

/******************************************************************************
 * Function: CRunnigLog.SerialMsg
 * Purpose: -
 *    out put log messages in buffer
 * Parameter:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
void CRunnigLog::SerialMsg()
{
    int nRead;
    int nWritecount = 0;
    while (1)
    {
        CEasyLogLock lock(m_lcs);
        if (m_nMsgCount <= 0)
        {
            break;
        }
        nRead = m_nMsgRead;
        m_nMsgRead = ++m_nMsgRead % LOG_MAX_NODES;
        m_nMsgCount--;
        //write to file
        if (m_pStream)
        {
            fputs(m_ppMsgBuffer[nRead], m_pStream);
            memset(m_ppMsgBuffer[nRead], 0, LOG_MAX_MSG_LEN);
            nWritecount++;
        }       
    }
    if (nWritecount)
    {
        fflush(m_pStream);
    }
}

/******************************************************************************
 * Function: CRunnigLog.GetMsg
 * Purpose: -
 *     
 * Parameter:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
char *CRunnigLog::GetMsg()
{
    CEasyLogLock lock(m_lcs);
    if (m_nMsgCount > 0)
    {
        int nRead = m_nMsgRead;
        m_nMsgRead = ++m_nMsgRead % LOG_MAX_NODES;
        m_nMsgCount--;
        return m_ppMsgBuffer[nRead];
    }
    return NULL;
}

/******************************************************************************
 * Function: CRunnigLog.ThreadProc
 * Purpose: -
 *    thread loop here
 * Parameter:
 * Returns:
 *    
 * modification history:
 *    
 * 07 Jan 2009, written by Yanqingwu
 *
 ******************************************************************************/
void CRunnigLog::ThreadProc()
{
    while (m_bRunningThread)
    {
        WaitForSingleObject(m_hNewMsg, INFINITE);
        if (!m_bRunningThread)
        {
            break;
        }
        SerialMsg();
    }
}
原创粉丝点击