分享

一个简单实用的log tool

 思考的轨迹 2012-04-13

一个简单实用的log tool
      -- 多线程下打印可能会乱
      -- 没有分级打印
      -- 没有支持debugview
 
应付一般的debug需求还是可以的,实际中一直在用!
逐步完善吧!

另外参考一个开源的log工具liblogger -- 架构清晰 C语言实现
http:///projects/liblogger/

文件:liblogger_0.1.zip
大小:158KB
下载:下载

-------------------------------------------------
VC6下不支持可变参数宏__VA_ARGS__

int fprintf(FILE *stream, const char *format, ...)
fprintf转化并格式化地写入输出流。返回值是写入的字符个数;或者为负数,如果有错误发生。

int printf(const char *format, ...)
printf(...)与fprintf(stdout, ...)等价。

int sprintf(char *s, const char *format, ...)
sprintf与printf相同,只是输出被写入字符串s,并且以’\0’结束。s必须足够大以容纳结果。函数返回不包括’\0’的字符数。

int vprintf(const char *format, va_list arg)
函数vprintf与printf等价,只是用arg替换了变量参数列表,arg由va_start宏初始化,并且va_arg可能会调用它。

int vfprintf(FILE *stream,const char * format,va_list ap)
vfprintf()会根据参数format字符串来转换并格式化数据,然后将结果输出到参数stream指定的文件中,直到出现字符串结束(’\0’)为止

int _vsnprintf(char *, size_t, const char *, va_list)

int vsprintf(char *, const char *, va_list)

DebugOutputString -- 支持debugview
功能:发送一个字串到调试器的显示。
函数原型:void WINAPI OutputDebugString( LPCTSTR lpOutputString );

一.最简单的用法
#define MAX_DBG_MSG_LEN (1024)
char[MAX_DBG_MSG_LEN];
sprintf(msgbuf, "LastError=%ld\n", GetLastError());
OutputDebugString(msgbuf);
二.扩展的用法
按照printf的风格的对OutputDebugString进行封装
#define MAX_DBG_MSG_LEN (1024)
static void __dbg_printf (const char * format,...)
{
char buf[MAX_DBG_MSG_LEN];
va_list ap;
va_start(ap, format);
_vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
OutputDebugString(buf);
}
使用:
__dbg_printf( "LastError=%ld\n", GetLastError());
三.进一步的扩展
对DEBUG和RELEASE下的区分.
ifdef _DEBUG
static void __dbg_printf (const char * format,...)
{
char buf[MAX_DBG_MSG_LEN];
va_list ap;
va_start(ap, format);
_vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
OutputDebugString(buf);
}
#else
static void __dbg_printf (const char * format,...) {}
#endif


----------------------------------------------------
使用方法:
假设有class CTestApp, class CTestModule, 对应有两个.cpp文件testapp.cpp, testmodule.cpp
1)在testapp.cpp中: #include "log.h"
2)在testapp.cpp中: DefineVar();
3)在testapp.cpp类构造函数中: CTestApp::CTestApp(){TOpenFile(); ...; }
4)在testapp.cpp类析构函数中: CTestApp::~CTestApp(){...; TCloseFile();}
5)在testapp.cpp类其他函数中: CTestApp::SomeFunc(){...; LogText("Start to log data\n"); LogData("app value: %d\n", m_lValue);...;}
6)在testmodule.cpp中: #include "log.h"
7)在testmodule.cpp类其他函数中: CTestModule::SomeFunc(){...; LogData("module value: %d\n", m_lValue);...;}
8)要使得正式release版本不产生LOG,只需将log.h文件中"#define TEST" 注释掉即可,不需要删除所有LOG相关的宏定义
9)所有的LOG文件请缺省放置在C:\DebugLog\目录下,不同的模块请更改LOGFILENAME中tModule.txt的名字

一些格式要求:
1)错误情况,极少发生的事件,在LOG时加"!"前缀,如:LogText("! Parameter Error\n");
2)较少发生的事件,如用户调用,在LOG时加"#"前缀,如:LogText("# Seeking - SetPosition\n");
3)经常重复发生的事件不要加任何前缀
4)需要LOG系统时间时,调用LogSysTime()即可,如:LogSysTime(); LogData("Receive %n Bytes\n", lLength);
5)希望减少重复事件LOG的次数,可用到g_lLogCount,如:if(g_lLogCount%100==0) LogText("Sth is working\n"); g_lLogCount1++;
6)需要对齐或缩进用\t,64位整数用%I64d,如:LogData("\t frame pts: %I64d\n", tStart); LogData("\t frame size: %d\n", lLength);


#include "log.h"
DefineVar();

int main()
{
    int i = 3;

    TOpenFile();


    LogText("--------------------\n")
    LogData("i: %d, const : %d\n", i, 5);
    LogSysTime();
    LogData("---- i: %d\n", i);
    LogData("+++++++++++++++++++\n");


    TCloseFile();
    return 0;
}


//=====================================================
//simple log tool for debug
//=====================================================

#ifndef _LOGTOOL_H_
#define _LOGTOOL_H_

#include <windows.h>
#include <stdio.h>

#define TEST

#define LOGFILENAME "C:\\DebugLog\\tModule.txt"

#ifdef TEST

/*  #ifndef EnableModuleLog
        #pragma message("@ log invalid: need define macro EnableModuleLog before log.h to enable log!!")
    #else
        #pragma message("@ enable this module log!!")
    #endif
*/

    #ifdef __cplusplus
    extern "C" {
    #endif

        extern FILE* g_pLogFile;
        extern char g_LogTextBuf[256];
        extern LONG g_lLogCount1;
        extern LONG g_lLogCount2;

    #ifdef __cplusplus
    }
    #endif

/*  #define LogData vl_printf
#ifdef EnableModuleLog    
    static void vl_printf(const char* fmt, ...)
    {
        va_list ap;
        va_start(ap, fmt);
        vfprintf(g_pLogFile, fmt, ap);
        va_end(ap);
    }

    #define LogText(str) {                            \
            sprintf(g_LogTextBuf,str);                \
            fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
        }
    #define LogSysTime() {                            \
            SYSTEMTIME st;                            \
            GetLocalTime(&st);                        \
            sprintf(g_LogTextBuf,"[%02u:%02u:%02u:%03u] ",st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);\
            fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
        }
#else
    static void vl_printf(const char* fmt, ...) {}
    #define LogText(str)
    #define LogSysTime()
#endif
*/

    #define LogData vl_printf
    static void vl_printf(const char* fmt, ...)
    {
        va_list ap;
        va_start(ap, fmt);
        vfprintf(g_pLogFile, fmt, ap);
        va_end(ap);
    }
        
    #define LogText(str) {                            \
        sprintf(g_LogTextBuf,str);                    \
        fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
        }
    #define LogSysTime() {                            \
        SYSTEMTIME st;                                \
        GetLocalTime(&st);                            \
        sprintf(g_LogTextBuf,"[%02u:%02u:%02u:%03u] ",st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);\
        fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
        }
    #define TOpenFile()    {                          \
            CreateDirectory("C:\\DebugLog",NULL);     \
            g_pLogFile=fopen(LOGFILENAME,"w");        \
            SYSTEMTIME st;                            \
            GetLocalTime(&st);                        \
            sprintf(g_LogTextBuf,"====Open file at %02u:%02u:%02u====\n",st.wHour,st.wMinute,st.wSecond );\
            fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
        }
    #define TCloseFile()    {                         \
            SYSTEMTIME st;                            \
            GetLocalTime(&st);                        \
            sprintf(g_LogTextBuf,"====Close file at %02u:%02u:%02u====\n",st.wHour,st.wMinute,st.wSecond );\
            fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
            fclose(g_pLogFile);                        \
        }
    #define DefineVar()                              \
            FILE* g_pLogFile;                        \
            char g_LogTextBuf[256];                  \
            LONG g_lLogCount1=0;                     \
            LONG g_lLogCount2=0;            
    
    #define FlushData() fflush(g_pLogFile)
        
#else
    #pragma warning(disable: 4002 4003)

    #define LogData(fmt,var)
    #define LogText(str)
    #define LogSysTime()
    #define TOpenFile()
    #define TCloseFile()
    #define DefineVar()
    #define FlushData()
#endif //TEST

#endif //_LOGTOOL_H_    

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多