发布一个轻便易用、概念简单、高性能、跨平台、线程安全的纯c日志函数库iLOG3 ^_^

BetonArmEE 2014-02-09 08:25:48
iLOG3是一个轻便易用、概念简单,高性能、多层接口、原生跨平台、(规范使用时)线程安全的遵循LGPL开源协议的标准c日志函数库。

基本特性如下:
·原生跨平台,这意味着你的软件在日志层面上是可轻松移植的,目前支持WINDOWS & UNIX & Linux ,iLOG3会在不同的操作系统上做相应的实现和优化
·五类日志等级
·变参的日志函数和日志宏
·行日志风格方案选配
·输出介质有文件、标准输出、标准错误输出、syslogd或WINDOWS EVENT、自定义介质

高级特性如下:
·支持日志选项组合
·支持按日志文件大小、每天、每小时转档
·支持行日志风格自定义回调函数,很容易定制自己的行日志格式
·支持日志文件的打开、输出、关闭自定义回调函数,很容易扩展成日志输出到远程日志服务器落地
·线程安全、简易MDC、基于线程本地存储的缺省全局日志句柄

分层实施“日志句柄层(LOG)->日志句柄集合层(LOGS)->配置文件接口层(LOGCONF、LOGSCONF)”。其实大部分用户的日志需求很简单,一个进程写一个日志文件(使用日志句柄层函数即可),但也考虑到另外一些用户有多个输出对象需求(使用日志句柄集合层函数即可),还有用户喜欢用外部配置文件来配置日志(使用配置文件接口层函数即可),不同用户在不同项目场景中使用iLOG3的不同层接口,不至于杀鸡用牛刀、小刀砍大树。

我还开发了一个姐妹函数库iLOG3CONF_SML来支持用SML标记语言配置文件来配置日志句柄,有兴趣的朋友也可以调用日志句柄层或日志句柄集合层函数开发自己的iLOG3CONF_*,实现用XML或现在流行的json或自己项目统一配置文件格式,来实现用外部配置文件配置iLOG3日志句柄环境。

此外,源代码结构也比较简单,只有三对源文件,便于搬运、嵌入和修改。


#include <stdio.h>

#include “LOG.h”

#define LOG_STYLES_HELLO ( LOG_STYLE_DATETIMEMS | LOG_STYLE_LOGLEVEL | LOG_STYLE_PID | LOG_STYLE_TID | LOG_STYLE_SOURCE | LOG_STYLE_FORMAT | LOG_STYLE_NEWLINE )

int test_hello()
{
char buffer[ 64 + 1 ] = "" ;
long buflen = sizeof(buffer)-1 ;

/* 创建日志句柄 */
if(CreateLogHandleG() == NULL )
{
printf( "创建日志句柄失败errno[%d]\n" , errno );
return -1;
}
else
{
printf( "创建日志句柄成功\n" );
}

/* 设置日志输出文件名 */
SetLogOutputG( LOG_OUTPUT_FILE , "test_hello.log" , LOG_NO_OUTPUTFUNC );
/* 设置当前日志过滤等级 */
SetLogLevelG( LOG_LEVEL_INFO );
/* 设置当前行日志风格方案 */
SetLogStylesG( LOG_STYLES_HELLO , LOG_NO_STYLEFUNC);

/* 以不同日志等级写行日志 */
DebugLogG( __FILE__ , __LINE__ , "hello iLOG3" ); /* 这行日志因等级不够,被华丽的过滤了 */
InfoLogG( __FILE__ , __LINE__ , "hello iLOG3" );
WarnLogG( __FILE__ , __LINE__ , "hello iLOG3" );
ErrorLogG( __FILE__ , __LINE__ , "hello iLOG3" );
FatalLogG( __FILE__ , __LINE__ , "hello iLOG3" );

/* 以不同日志等级写十六进制块日志 */
DebugHexLogG( __FILE__ , __LINE__ , buffer , buflen , "缓冲区[%ld]" , buflen ); /* 又一个被华丽的过滤 */
InfoHexLogG( __FILE__ , __LINE__ , buffer , buflen , "缓冲区[%ld]" , buflen );
WarnHexLogG( __FILE__ , __LINE__ , buffer , buflen , "缓冲区[%ld]" , buflen );
ErrorHexLogG( __FILE__ , __LINE__ , buffer , buflen , "缓冲区[%ld]" , buflen );
FatalHexLogG( __FILE__ , __LINE__ , buffer , buflen , "缓冲区[%ld]" , buflen );

/* 销毁日志句柄 */
DestroyLogHandleG();
printf( "释放日志句柄\n" );

return 0;
}

int main()
{
return -test_hello();
}

输出日志如下:

2014-02-09 20:06:39.203000 | INFO | 3880:700:test_20060920.c:32 | hello iLOG3
2014-02-09 20:06:39.203000 | WARN | 3880:700:test_20060920.c:33 | hello iLOG3
2014-02-09 20:06:39.203000 | ERROR | 3880:700:test_20060920.c:34 | hello iLOG3
2014-02-09 20:06:39.203000 | FATAL | 3880:700:test_20060920.c:35 | hello iLOG3
2014-02-09 20:06:39.203000 | INFO | 3880:700:test_20060920.c:39 | 缓冲区[64]
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
2014-02-09 20:06:39.203000 | WARN | 3880:700:test_20060920.c:40 | 缓冲区[64]
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
2014-02-09 20:06:39.203000 | ERROR | 3880:700:test_20060920.c:41 | 缓冲区[64]
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
2014-02-09 20:06:39.203000 | FATAL | 3880:700:test_20060920.c:42 | 缓冲区[64]
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................


下载页面
http://git.oschina.net/calvinwilliams/iLOG3
欢迎使用,多提宝贵意见 ^_^
...全文
113 点赞 收藏 3
写回复
3 条回复
JiMoKuangXiangQu 2014年02月10日
回复 点赞
赵4老师 2014年02月10日
//循环向a函数每次发送200个字节长度(这个是固定的)的buffer,
//a函数中需要将循环传进来的buffer,组成240字节(也是固定的)的新buffer进行处理,
//在处理的时候每次从新buffer中取两个字节打印
#ifdef WIN32
    #pragma warning(disable:4996)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
    #include <windows.h>
    #include <process.h>
    #include <io.h>
    #define  MYVOID             void
    #define  vsnprintf          _vsnprintf
#else
    #include <unistd.h>
    #include <sys/time.h>
    #include <pthread.h>
    #define  CRITICAL_SECTION   pthread_mutex_t
    #define  MYVOID             void *
#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);
}
void sleep_ms(int ms) {
    Sleep(ms);
}
#else
void Lock(CRITICAL_SECTION *l) {
    pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
    pthread_mutex_unlock(l);
}
void sleep_ms(int ms) {
    usleep(ms*1000);
}
#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}
#define ASIZE    200
#define BSIZE    240
#define CSIZE      2
char Abuf[ASIZE];
char Cbuf[CSIZE];
CRITICAL_SECTION cs_HEX ;
CRITICAL_SECTION cs_BBB ;
struct FIFO_BUFFER {
    int  head;
    int  tail;
    int  size;
    char data[BSIZE];
} BBB;
int No_Loop=0;
void HexDump(int cn,char *buf,int len) {
    int i,j,k;
    char binstr[80];

    Lock(&cs_HEX);
    for (i=0;i<len;i++) {
        if (0==(i%16)) {
            sprintf(binstr,"%03d %04x -",cn,i);
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        } else if (15==(i%16)) {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
            sprintf(binstr,"%s  ",binstr);
            for (j=i-15;j<=i;j++) {
                sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
            }
            Log("%s\n",binstr);
        } else {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        }
    }
    if (0!=(i%16)) {
        k=16-(i%16);
        for (j=0;j<k;j++) {
            sprintf(binstr,"%s   ",binstr);
        }
        sprintf(binstr,"%s  ",binstr);
        k=16-k;
        for (j=i-k;j<i;j++) {
            sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
        }
        Log("%s\n",binstr);
    }
    Unlock(&cs_HEX);
}
int GetFromRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {
    int lent,len1,len2;

    lent=0;
    Lock(cs);
    if (fbuf->size>=len) {
        lent=len;
        if (fbuf->head+lent>BSIZE) {
            len1=BSIZE-fbuf->head;
            memcpy(buf     ,fbuf->data+fbuf->head,len1);
            len2=lent-len1;
            memcpy(buf+len1,fbuf->data           ,len2);
            fbuf->head=len2;
        } else {
            memcpy(buf     ,fbuf->data+fbuf->head,lent);
            fbuf->head+=lent;
        }
        fbuf->size-=lent;
    }
    Unlock(cs);
    return lent;
}
MYVOID thdB(void *pcn) {
    char        *recv_buf;
    int          recv_nbytes;
    int          cn;
    int          wc;
    int          pb;

    cn=(int)pcn;
    Log("%03d thdB              thread begin...\n",cn);
    while (1) {
        sleep_ms(10);
        recv_buf=(char *)Cbuf;
        recv_nbytes=CSIZE;
        wc=0;
        while (1) {
            pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);
            if (pb) {
                Log("%03d recv %d bytes\n",cn,pb);
                HexDump(cn,recv_buf,pb);
                sleep_ms(1);
            } else {
                sleep_ms(1000);
            }
            if (No_Loop) break;//
            wc++;
            if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
        }
        if (No_Loop) break;//
    }
#ifndef WIN32
    pthread_exit(NULL);
#endif
}
int PutToRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {
    int lent,len1,len2;

    Lock(cs);
    lent=len;
    if (fbuf->size+lent>BSIZE) {
        lent=BSIZE-fbuf->size;
    }
    if (fbuf->tail+lent>BSIZE) {
        len1=BSIZE-fbuf->tail;
        memcpy(fbuf->data+fbuf->tail,buf     ,len1);
        len2=lent-len1;
        memcpy(fbuf->data           ,buf+len1,len2);
        fbuf->tail=len2;
    } else {
        memcpy(fbuf->data+fbuf->tail,buf     ,lent);
        fbuf->tail+=lent;
    }
    fbuf->size+=lent;
    Unlock(cs);
    return lent;
}
MYVOID thdA(void *pcn) {
    char        *send_buf;
    int          send_nbytes;
    int          cn;
    int          wc;
    int           a;
    int          pa;

    cn=(int)pcn;
    Log("%03d thdA              thread begin...\n",cn);
    a=0;
    while (1) {
        sleep_ms(100);
        memset(Abuf,a,ASIZE);
        a=(a+1)%256;
        if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop
        send_buf=(char *)Abuf;
        send_nbytes=ASIZE;
        Log("%03d sending %d bytes\n",cn,send_nbytes);
        HexDump(cn,send_buf,send_nbytes);
        wc=0;
        while (1) {
            pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);
            Log("%03d sent %d bytes\n",cn,pa);
            HexDump(cn,send_buf,pa);
            send_buf+=pa;
            send_nbytes-=pa;
            if (send_nbytes<=0) break;//
            sleep_ms(1000);
            if (No_Loop) break;//
            wc++;
            if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
        }
        if (No_Loop) break;//
    }
#ifndef WIN32
    pthread_exit(NULL);
#endif
}
int main() {
#ifdef WIN32
    InitializeCriticalSection(&cs_log);
    InitializeCriticalSection(&cs_HEX );
    InitializeCriticalSection(&cs_BBB );
#else
    pthread_t threads[2];
    int threadsN;
    int rc;
    pthread_mutex_init(&cs_log,NULL);
    pthread_mutex_init(&cs_HEX,NULL);
    pthread_mutex_init(&cs_BBB,NULL);
#endif
    Log("Start===========================================================\n");

    BBB.head=0;
    BBB.tail=0;
    BBB.size=0;

#ifdef WIN32
    _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);
    _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2);
#else
    threadsN=0;
    rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
    rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
#endif

    if (!access("No_Loop",0)) {
        remove("No_Loop");
        if (!access("No_Loop",0)) {
            No_Loop=1;
        }
    }
    while (1) {
        sleep_ms(1000);
        if (No_Loop) break;//
        if (!access("No_Loop",0)) {
            No_Loop=1;
        }
    }
    sleep_ms(3000);
    Log("End=============================================================\n");
#ifdef WIN32
    DeleteCriticalSection(&cs_BBB );
    DeleteCriticalSection(&cs_HEX );
    DeleteCriticalSection(&cs_log);
#else
    pthread_mutex_destroy(&cs_BBB);
    pthread_mutex_destroy(&cs_HEX);
    pthread_mutex_destroy(&cs_log);
#endif
    return 0;
}
回复 点赞
赵4老师 2014年02月10日
尺有所短,寸有所长。
#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;
}
//1-78行添加到你带main的.c或.cpp的那个文件的最前面
//81-85行添加到你的main函数开头
//89-93行添加到你的main函数结束前
//在要写LOG的地方仿照第87行的写法写LOG到文件MyLog1.log中
回复 点赞
发动态
发帖子
非技术区
创建于2007-09-28

4415

社区成员

5.8w+

社区内容

C/C++ 非技术区
社区公告
暂无公告