首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

C/C++ logging日记类分享

2013-02-24 
C/C++ logging日志类分享参考google的libjingle库,写了一个简单的日志记录类,功能相对来说不是很复杂,但是

C/C++ logging日志类分享
参考google的libjingle库,写了一个简单的日志记录类,功能相对来说不是很复杂,但是很方便实用,现拿来分享,欢迎个位拍砖。

logging.h:


#ifndef CLASSES_LOGGING_H__
#define CLASSES_LOGGING_H__

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

// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName)    \
    TypeName(const TypeName&);                    \
    void operator=(const TypeName&)


// Note that the non-standard LoggingSeverity aliases exist because they are
// still in broad use.  The meanings of the levels are:
//  LS_SENSITIVE: Information which should only be logged with the consent
//   of the user, due to privacy concerns.
//  LS_VERBOSE: This level is for data which we do not want to appear in the
//   normal debug log, but should appear in diagnostic logs.
//  LS_INFO: Chatty level used in debugging for all sorts of things, the default
//   in debug builds.
//  LS_WARNING: Something that may warrant investigation.
//  LS_ERROR: Something that should not have occurred.
enum LoggingSeverity 

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

// LogErrorContext assists in interpreting the meaning of an error value.
//  ERRCTX_ERRNO: the value was read from global 'errno'
//  ERRCTX_HRESULT: the value is a Windows HRESULT
enum LogErrorContext
{
    ERRCTX_NONE,
    ERRCTX_ERRNO, 
    ERRCTX_HRESULT
};

class LogMessage
{
public:
    LogMessage(const char* file, // source file name,is not the log filename.
        int line,
        LoggingSeverity sev,
        LogErrorContext err_ctx = ERRCTX_NONE,
        int err = 0,
        const char* module = NULL);

    ~LogMessage();


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




    // Timestamps begin with program execution, but can be reset with this
    // function for measuring the duration of an activity, or to synchronize
    // timestamps between multiple instances.
    static void ResetTimestamps();

private:
    // These assist in formatting some parts of the debug output.
    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);
    
    // The ostream that buffers the formatted message before output
    std::ostringstream print_stream_;


    // The severity level of this message
    LoggingSeverity severity_;

    // String data generated in the constructor, that should be appended to
    // the message before output.
    std::string extra_;

    // The timestamp at which logging started.
    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()


// The _F version prefixes the message with the current function name.
#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "


// PLOG and LOG_ERR attempt to provide a string description of an errno derived
// error.  LOG_ERR reads errno directly, so care must be taken to call it before
// errno is reset.
#define PLOG(sev, err) LogMessage(__FILE__, __LINE__, sev, ERRCTX_ERRNO, err).stream()

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

// LOG_GLE(M) attempt to provide a string description of the HRESULT returned
// by GetLastError.  The second variant allows searching of a dll's string
// table for the error description.
#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  // CLASSES_LOGGING_H__



logging.cpp:

#include "logging.h"

extern "C" BOOL WINAPI IsDebuggerPresent(void);

// Program start time
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);
        }
    }
}



libjingle库下载地址:http://download.csdn.net/detail/china_jeffery/5038519

[解决办法]
鼓励一下,发扬勤动手的好习惯!现在越来越懒了,唉~~~~~~~
[解决办法]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
    #include <windows.h>
    #include <io.h>
#else
    #include <unistd.h>
    #include <sys/time.h>
    #include <pthread.h>
    #define  CRITICAL_SECTION   pthread_mutex_t
    #define  _vsnprintf         vsnprintf
#endif
//Log{
#define MAXLOGSIZE 20000000
#define MAXLINSIZE 16000
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
static char logstr[MAXLINSIZE+1];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
    EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
    LeaveCriticalSection(l);
}
#else
void Lock(CRITICAL_SECTION *l) {
    pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
    pthread_mutex_unlock(l);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
    struct tm *now;
    struct timeb tb;

    if (NULL==pszFmt
[解决办法]
0==pszFmt[0]) return;
    _vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);
    ftime(&tb);
    now=localtime(&tb.time);
    sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
    sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );
    sprintf(mss,"%03d",tb.millitm);
    printf("%s %s.%s %s",datestr,timestr,mss,logstr);
    flog=fopen(logfilename1,"a");


    if (NULL!=flog) {
        fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
        if (ftell(flog)>MAXLOGSIZE) {
            fclose(flog);
            if (rename(logfilename1,logfilename2)) {
                remove(logfilename2);
                rename(logfilename1,logfilename2);
            }
        } else {
            fclose(flog);
        }
    }
}
void Log(const char *pszFmt,...) {
    va_list argp;

    Lock(&cs_log);
    va_start(argp,pszFmt);
    LogV(pszFmt,argp);
    va_end(argp);
    Unlock(&cs_log);
}
//Log}
int main(int argc,char * argv[]) {
    int i;
#ifdef WIN32
    InitializeCriticalSection(&cs_log);
#else
    pthread_mutex_init(&cs_log,NULL);
#endif
    for (i=0;i<10000;i++) {
        Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);
    }
#ifdef WIN32
    DeleteCriticalSection(&cs_log);
#else
    pthread_mutex_destroy(&cs_log);
#endif
    return 0;
}


[解决办法]
收藏了,楼主辛苦了
[解决办法]
收藏了,多向楼主学习。
[解决办法]
mark一下,感谢楼主分享
[解决办法]
mark了,LZ辛苦了
[解决办法]
Thanks for sharing
[解决办法]
使用方法挺新颖,我喜欢
[解决办法]
用google的glog的路过

热点排行