自开发的一个日志模板

       原以为一个日志模板写起来应该很简单才对,当自己真正开始动手做起来才知道没那么容易,有很多东西要考虑。事实上,写这篇博文的时候,我还没有完成我想要的日志模板,至少我认为我现在的模板不够健壮,没有达到我对它的要求。写下来,一方面是个阶段性的总结,一方面是重新审视自己的不足。

一、目标

       1、日志文件命名:程序名时间.log;

       2、实时记录,日志文件删除后,再调用会及时生成log日志文件;

       3、日志内容包含调用的文件名、行数、时间、内容;

       4、日志级别分5级:HINT、ALWAYS、DEBUG、ERROR、FATAL;

       5、日志接口:GLog(int Level,char *fmt,...);

二、开发中遇到的几个问题

       1、创建日志文件使用C库函数(如fopen、fwrite等)还是系统函数(如open、write等)?

             这个我还不确定哪个好,暂时用的是第一种,即C库函数

       2、占用资源尽量少

             使用4个全局变量,分别保存工作路径、程序名、创建log文件的开关、保存日志等级的二维字符数组;

             2个静态变量,分别是日志文件名和日志文件的文件指针;

       3、每次调用接口,写完文件后要不要关闭文件?

             如果每次调用都要开关文件的话,个人认为会很费时间,消耗资源(IO操作),所以每次调用我都没有关闭文件指针。每次写文件之前,我都会用stat函数检查文件是否存在,如果不存在就重新创建文件;我写了一个通信的程序测试。当服务端后台运行后,我尝试删除日志文件操作,删除两次就会出现程序自动退出的问题,而且没有产生core;前台运行,没有出现该问题。


附代码:

liblog.h:

#ifndef LIBLOG_H
#define LIBLOG_H


#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>

#define BUFFSIZE 1024
#define LOGNAMESIZE 120
#define TIMESIZE 15

#define HINT   0,__FILE__,__LINE__
#define ALWAYS 1,__FILE__,__LINE__
#define DEBUG  2,__FILE__,__LINE__
#define ERROR  3,__FILE__,__LINE__
#define FATAL  4,__FILE__,__LINE__

char LogPath[100];
char ProName[20];
int  iLogFlag;
char sLogLevel[5][10];

void LogInit(char *progress);
void GetLocalTime(char *localtime);
void GLog(int iLogLevel,char *file,int line,char *fmt, ...);

#endif

liblog.c:

#include "liblog.h"

/* init log module */
void LogInit(char *progress)
{
    if(NULL==progress)
    {
        strcpy(ProName,"LOG_INIT");
    }
    else
    {
        char *pro = NULL;
        int  iLen = 0;
   
        pro = strstr(progress,"./");
        if(NULL==pro)
        {
            strcpy(ProName,progress);
        }
        else
        {
            iLen = strlen(progress);
            strncpy(ProName,pro+2,iLen-2);
        }
    }
    
    strcpy(LogPath,"/home/dboslnk/project/log/");
    iLogFlag = 0;
    strcpy(sLogLevel[0],"HINT");
    strcpy(sLogLevel[1],"ALWAYS");
    strcpy(sLogLevel[2],"DEBUG");
    strcpy(sLogLevel[3],"ERROR");
    strcpy(sLogLevel[4],"FATAL");

    return ;
}

/* function : get loacal time */
void GetLocalTime(char *localtime)
{
    if(NULL==localtime)
    {
        fprintf(stderr,"GetLocalTime parameter error\n");
        return ;
    }

    time_t tNow = time(NULL);
    struct tm pTm = {0};
    char   sTime[TIMESIZE];

    localtime_r(&tNow,&pTm);
    memset(sTime,0x00,TIMESIZE);
    strftime(sTime,TIMESIZE,"%Y%m%d%H%M%S",&pTm);

    /* make sure that localtime is large enough for copy */
    strncpy(localtime,sTime,TIMESIZE);
}

/* function : parameter list */
void GLog(int iLogLevel,char *file,int line,char *fmt, ...)
{
    va_list argstr;
    static FILE *flogptr = NULL;
    int  iLen = 0,iRet = 0;
    char buffer[BUFFSIZE];
    static char LogName[LOGNAMESIZE];
    char sLocalTime[TIMESIZE];
    char sLogDetail[BUFFSIZE];
    struct stat fBuff;

    memset(buffer,0x00,BUFFSIZE);
    va_start(argstr,fmt);
    iLen = vsprintf(buffer,fmt,argstr);
    va_end(argstr);

OPENFILE:
    memset(sLocalTime,0x00,sizeof(sLocalTime));
    GetLocalTime(sLocalTime);
    if(iLogFlag==0)
    {
        /* create log file */
        memset(LogName,0x00,sizeof(LogName));
        sprintf(LogName,"%s%s%s.log",LogPath,ProName,sLocalTime);
        flogptr = fopen(LogName,"a");
        if(NULL==flogptr)
        {
            fprintf(stderr,"fopen log name[%s] iLogFlag[%d] error\n",LogName,iLogFlag);
        }

        iLogFlag = 1;
    }

    //sprintf(sLogDetail,"%s|%s|%d|%s|%s\n",sLocalTime,file,line,sLogLevel[iLogLevel],buffer);
    //iLen = strlen(sLogDetail);
    memset(&fBuff,0x00,sizeof(fBuff));
    iRet = stat(LogName,&fBuff);
    if(iRet<0)
    {
        fprintf(stderr,"stat [%s] error\n",LogName);
        iLogFlag = 0;
        goto OPENFILE;
    }

    sprintf(sLogDetail,"%s|%s|%d|%s|%s\n",sLocalTime,file,line,sLogLevel[iLogLevel],buffer);
    iLen = strlen(sLogDetail);
  
    fwrite(sLogDetail,1,iLen,flogptr);
    
    fflush(flogptr);
    
    return ;
}

         总体上讲,我觉得要实现一个功能容易,但是要写好一段高质量的代码,真的很难。特别是性能、鲁棒性等问题,没有经验的人和有经验的人差距是很大的。我依然是个菜鸟,是一只不断努力学习的菜鸟。上面的代码,只是现在初级的代码,我还要修改和完善,可能会有很大的变化,包括里面调用的函数,我也可能换掉。读者如果有什么意见,请记得留下脚印,让我来验证你的想法


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值