首页 > 代码库 > simplelogger

simplelogger

贵灯提供的简单打印函数,非原创;

注意:

do{}while(false); 的使用(内部多个判断,用 do false 中的 break 可以避免使用 if true 引起的嵌套层数过多);

关键段 CRITICAL_SECTION 的使用,封装了 lock 和 unlock 函数;

不定长参数 va_list 的使用;

 

 

#pragma once 

/*
 * 1. 简单日志:支持多字节和 unicode 工程, 线程安全, 生成的文件名有进程名称和进程id组成
 * 2. 调用接口: LOG_INFO 为主要日志输出函数, LOG_ERROR 为打印 lastError 错误信息
 * 3. 日志输出格式为:[9348] [5-15 9:55:44] [.\loggerTest.cpp - threadProc1 - 14]  this is a test
              其中:第一列 [9348] 为线程 id
                   第二列 [5-15 9:55:44] 为时间信息, 具体为月份日期小时分钟秒钟
                   弟三列 [.\loggerTest.cpp - threadProc1 - 14] 为所在对应文件对应函数对应代码行信息
                   第四列 this is a test 为具体日志信息

 * 
*/

#ifdef SIMPLE_LOGGER

#include <windows.h>
#include <assert.h>
#include <shlwapi.h>
#include <stdlib.h>

#pragma comment(lib, "shlwapi.lib")

#define MAX_LOGGER_BUFFER (1024)

#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFILE__ WIDEN(__FILE__)
#define __WFUNCTION__ WIDEN(__FUNCTION__)

#ifdef _UNICODE
#define __TFILE__ __WFILE__
#define __TFUNCTION__ __WFUNCTION__
#else
#define __TFILE__ __FILE__
#define __TFUNCTION__ __FUNCTION__
#endif

#define OutputDebugLastError()       \
{                                         DWORD errid = ::GetLastError();         TCHAR buf[MAX_PATH] = {0};           _stprintf_s(buf, sizeof(buf)/sizeof(TCHAR), _T("[%s - %s - %d] errorid=%d\n"), __TFILE__, __TFUNCTION__, __LINE__, errid);     OutputDebugString(buf);                                                                                                    }

class Logger
{
public:
    Logger()
    {
        do 
        {
            SECURITY_DESCRIPTOR secutityDese;
            BOOL bRes = ::InitializeSecurityDescriptor(&secutityDese, SECURITY_DESCRIPTOR_REVISION);
            if(!bRes)
            {
                OutputDebugLastError();
                break;
            }

            bRes = ::SetSecurityDescriptorDacl(&secutityDese, TRUE, NULL, FALSE);
            if(!bRes)
            {
                OutputDebugLastError();
                break;
            }

            SECURITY_ATTRIBUTES securityAttr;
            securityAttr.nLength = sizeof SECURITY_ATTRIBUTES;
            securityAttr.bInheritHandle = FALSE;
            securityAttr.lpSecurityDescriptor = &secutityDese;

            TCHAR szProcName[MAX_PATH] = {0};
            if( 0 == ::GetModuleFileName(NULL, szProcName, sizeof(szProcName) ) )
            {
                OutputDebugLastError();
                break;
            }

            PathStripPath(szProcName);

            TCHAR szDir[MAX_PATH] = _T("c:\\SimpleLog");

            ::CreateDirectory(szDir, &securityAttr);

            TCHAR szFileName[MAX_PATH] = {0};
            _stprintf_s(szFileName, sizeof(szFileName)/sizeof(TCHAR), _T("%s\\%s[%u].log"), szDir, szProcName, ::GetCurrentProcessId() );

            // 加上该描述符控制, 可以接受任何条件的访问
            _hFile = ::CreateFile(szFileName, FILE_GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &securityAttr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
            if(_hFile == INVALID_HANDLE_VALUE)
            {
                OutputDebugLastError();
                break;
            }

#ifdef _UNICODE
            DWORD dwWrited = 0;
            DWORD dwUnicode = 0xFEFF;

            bRes = WriteFile(_hFile, &dwUnicode, sizeof(DWORD), &dwWrited, NULL);
            if(!bRes || dwWrited != sizeof(DWORD))
            {
                OutputDebugLastError();
                break;
            }
#endif
                                    
        } while (FALSE);

        ::InitializeCriticalSection(&_cs);
    }

    ~Logger()
    {
        if(_hFile != INVALID_HANDLE_VALUE)
        {
            ::CloseHandle(_hFile);
            _hFile = INVALID_HANDLE_VALUE;
        }

        ::DeleteCriticalSection(&_cs);
    }

    void LogPrint(LPCTSTR pszFormat)
    {
        if(_hFile != INVALID_HANDLE_VALUE && pszFormat != NULL)
        {
            DWORD dwWrite = _tcslen(pszFormat) * sizeof(TCHAR);
            DWORD dwWrited = 0;

            BOOL bRes = WriteFile(_hFile, pszFormat, dwWrite, &dwWrited, NULL);
            if(!bRes || dwWrite != dwWrited)
            {
                OutputDebugLastError();
            }
        }        
    }

    void lock()
    {
        ::EnterCriticalSection(&_cs);
    }

    void unlock()
    {
        ::LeaveCriticalSection(&_cs);
    }

protected:
private:    
    HANDLE _hFile;
    CRITICAL_SECTION _cs;
};

static Logger g_logger;

inline void LogMessage(LPCTSTR pszFormat, ...)
{
    assert(pszFormat != NULL);

    if(pszFormat != NULL)
    {
        TCHAR szMsg[MAX_LOGGER_BUFFER] = {0};

        va_list pArg;

        va_start(pArg, pszFormat);
        _vstprintf_s(szMsg, sizeof(szMsg)/sizeof(TCHAR), pszFormat, pArg);
        va_end(pArg);

        g_logger.LogPrint(szMsg);
    }    
}


#define LOG_INFO(x, ...)                                                    \
{                                                                                g_logger.lock();                                                            SYSTEMTIME st = {0};                                                        GetSystemTime(&st);                                                            SYSTEMTIME stLocalTime = {0};                                                SystemTimeToTzSpecificLocalTime(NULL, &st, &stLocalTime);                    TCHAR szAppend[MAX_PATH] = {0};                                                _stprintf_s(szAppend, sizeof(szAppend)/sizeof(TCHAR), _T("[%u] [%d-%d %d:%d:%d] "), ::GetCurrentThreadId(), stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);     LogMessage(szAppend);                                                        LogMessage(_T("[%s - %s - %d]  "), __TFILE__, __TFUNCTION__, __LINE__);     LogMessage(x, __VA_ARGS__);                                                    LogMessage(_T("\r\n") );                                                    g_logger.unlock();                                                        }


#define LOG_ERROR()                                                        \
{                                                                              DWORD errid = ::GetLastError();                                            TCHAR buf[MAX_PATH] = {0};                                                _stprintf_s(buf, sizeof(buf)/sizeof(TCHAR), _T("errorid=%d"), errid);                    LOG_INFO(buf);                                                                         }

#else 

#define LOG_INFO(x, ...)
#define LOG_ERROR()

#endif