首页 > 代码库 > (转)日志类

(转)日志类

#ifndef CLASSES_LOGGING_H__
#define CLASSES_LOGGING_H__

#include <iostream>
#include <iomanip>
#include <sstream>
#include <Windows.h>

#define DISALLOW_EVIL_CONSTRUCTORS(TypeName)    \
    TypeName(const TypeName&);                        void operator=(const TypeName&)

enum LoggingSeverity 
{ 
    LS_SENSITIVE, 
    LS_VERBOSE,
    LS_INFO,
    LS_WARNING,
    LS_ERROR,
    INFO = LS_INFO,
    WARNING = LS_WARNING,
    LERROR = LS_ERROR 
};

enum LogErrorContext
{
    ERRCTX_NONE,
    ERRCTX_ERRNO, 
    ERRCTX_HRESULT
};

class LogMessage
{
public:
    LogMessage(const char* file, 
        int line,
        LoggingSeverity sev,
        LogErrorContext err_ctx = ERRCTX_NONE,
        int err = 0,
        const char* module = NULL);

    ~LogMessage();


    std::ostream& stream()
    { 
        return print_stream_;
    }

    static void ResetTimestamps();

private:
    static const char* Describe(LoggingSeverity sev);
    static const char* DescribeFile(const char* file);
    static long TimeDiff(unsigned long later, unsigned long earlier);
    static bool TimeIsBetween(unsigned long later, unsigned long middle, unsigned long earlier);

    std::ostringstream print_stream_;

    LoggingSeverity severity_;
    std::string extra_;
    static unsigned long start_;
    HANDLE hFile_;
    DISALLOW_EVIL_CONSTRUCTORS(LogMessage);
};


#define LOG_INFO() LogMessage(__FILE__, __LINE__, LS_INFO).stream()

#define LOG(sev) LogMessage(__FILE__, __LINE__, sev).stream()

#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "

#define PLOG(sev, err) LogMessage(__FILE__, __LINE__, sev, ERRCTX_ERRNO, err).stream()

#define LOG_ERR(sev) LogMessage(__FILE__, __LINE__, sev, ERRCTX_ERRNO, errno).stream()

#define LOG_GLE(sev) LogMessage(__FILE__, __LINE__, sev, \
    ERRCTX_HRESULT, GetLastError()).stream()

#define LOG_GLEM(sev, mod) LogMessage(__FILE__, __LINE__, sev, \
    ERRCTX_HRESULT, GetLastError(), mod)     .stream()
#endif  

 

 

#include "logging.h"

extern "C" BOOL WINAPI IsDebuggerPresent(void);

unsigned long LogMessage::start_ = GetTickCount();

LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev,
    LogErrorContext err_ctx, int err, const char* module)
    : severity_(sev)
{
    unsigned long time = TimeDiff(GetTickCount(), start_);
    print_stream_ << "[" << std::setfill(0) << std::setw(3) << (time / 60000)
        << ":" << std::setw(2) << (time %60000)/1000
        << ":" << std::setw(3) << time %1000 << std::setfill( )
        << "] ";

    DWORD id = GetCurrentThreadId();
    print_stream_ << "[0x" << std::setfill(0) << std::setw(8) 
        << std::hex << id << std::dec << "] ";


    print_stream_ << Describe(sev) << "(" << DescribeFile(file)
        << ":" << line << "): ";

    if (err_ctx != ERRCTX_NONE)
    {
        std::ostringstream tmp;
        tmp << "[0x" << std::setfill(0) << std::hex << std::setw(8) << err << "]";
        switch (err_ctx)
        {
        case ERRCTX_ERRNO:
            {
                tmp << " " << strerror(err);
                break;
            }
        case ERRCTX_HRESULT: 
            {
                char msgbuf[256]={0};
                DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM;
                HMODULE hmod = GetModuleHandleA(module);
                if (hmod)
                    flags |= FORMAT_MESSAGE_FROM_HMODULE;
                if (DWORD len = FormatMessageA(
                    flags, hmod, err,
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                    msgbuf, sizeof(msgbuf) / sizeof(msgbuf[0]), NULL))
                {
                    while ((len > 0) &&
                        isspace(static_cast<unsigned char>(msgbuf[len-1])))
                    {
                        msgbuf[--len] = 0;
                    }
                    tmp << " " << msgbuf;
                }
                break; 
            }

        default:
            break;
        }
        extra_ = tmp.str();
    }
}


LogMessage::~LogMessage()
{
    if (!extra_.empty())
        print_stream_ << " : " << extra_;
    print_stream_ << "\r\n";
    const std::string& str = print_stream_.str();

    static bool debugger_present = (IsDebuggerPresent() != FALSE);
    if (debugger_present)
    {
        OutputDebugStringA(str.c_str());
    }
    else
    {
        hFile_ = ::CreateFileA("Test.txt",GENERIC_WRITE,0,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
        if(INVALID_HANDLE_VALUE != hFile_)
        {
            unsigned long written=0L;

            ::SetFilePointer (hFile_, 0, NULL, FILE_END);
            ::WriteFile(hFile_, str.data(), str.size(), &written, 0);

            FlushFileBuffers(hFile_);
            ::CloseHandle(hFile_);
        }
        else
        {
            hFile_ = NULL;
        }
    }
}



void LogMessage::ResetTimestamps() 
{
    start_ = GetTickCount();
}



const char* LogMessage::Describe(LoggingSeverity sev)
{
    switch (sev)
    {
    case LS_SENSITIVE: return "Sensitive";
    case LS_VERBOSE:   return "Verbose";
    case LS_INFO:      return "Info";
    case LS_WARNING:   return "Warning";
    case LS_ERROR:     return "Error";
    default:           return "<unknown>";
    }
}

const char* LogMessage::DescribeFile(const char* file)
{
    const char* end1 = ::strrchr(file, /);
    const char* end2 = ::strrchr(file, \\);
    if (!end1 && !end2)
        return file;
    else
        return (end1 > end2) ? end1 + 1 : end2 + 1;
}


bool LogMessage::TimeIsBetween(unsigned long later, unsigned long middle, unsigned long earlier) 
{
    if (earlier <= later)
    {
        return ((earlier <= middle) && (middle <= later));
    } 
    else
    {
        return !((later < middle) && (middle < earlier));
    }
}


long LogMessage::TimeDiff(unsigned long later, unsigned long earlier) 
{
    unsigned long LAST = 0xFFFFFFFF;
    unsigned long HALF = 0x80000000;
    if (TimeIsBetween(earlier + HALF, later, earlier))
    {
        if (earlier <= later)
        {
            return static_cast<long>(later - earlier);
        } 
        else 
        {
            return static_cast<long>(later + (LAST - earlier) + 1);
        }
    }
    else
    {
        if (later <= earlier) 
        {
            return -static_cast<long>(earlier - later);
        } 
        else 
        {
            return -static_cast<long>(earlier + (LAST - later) + 1);
        }
    }
}