关注:分享一个小巧的LinuxC日志模块(附代码)
来源:面包芯语     时间:2023-06-24 08:27:11


【资料图】

扫描关注一起学嵌入式,一起学习,一起成长

在产品研发的过程中,经常需要借助打印信息来帮助调试和后期维护。所以拥有一个完善的日志模块是至关重要的。

如下是从经手的项目中整理出来的日志模块及使用示例,以备后续项目开发时使用。(备注:Linux环境下)

log.c

#include#include#include#include#include#include#include#include#include#include#include"log.h"/*存储日志的文件名*/staticunsignedcharg_ucLogFileName[MAX_LOG_FILE_NUM][STR_COMM_SIZE]={{0}};/*指明是g_ucLogFileName中的哪个文件*/staticunsignedcharg_ucLogFileNo=0;/*输出日志位置标记,0-输出到终端,1-输出到日志文件*/unsignedlongg_ulPrintLogPlaceFlag=0;/*是否打印调试日志标记,0-不打印调试日志,1-打印调试日志*/unsignedlongg_ulPrintDebugLogFlag=0;/*日志文件大小*/staticunsignedlongg_ulLogFileSize=0;/*日志文件句柄*/staticFILE*pFile=NULL;/*日志存储互斥锁*/staticpthread_mutex_tg_stSaveLogMutexLock;/*日志模块初始化标记*/staticunsignedlongg_ulLogInitFlag=0;voidLOG_SetPrintLogPlaceFlag(unsignedlongflag){g_ulPrintLogPlaceFlag=flag;}voidLOG_SetPrintDebugLogFlag(unsignedlongflag){g_ulPrintDebugLogFlag=flag;}/*******************************************************************函数名:get_file_size**输入:char*path**输出:**功能描述:获取指令文件大小**返回值:long****************************************************************/staticlongget_file_size(constchar*path){longfilesize=-1;structstatstatbuff;if(stat(path,&statbuff)<0){returnfilesize;}else{filesize=statbuff.st_size;}returnfilesize;}/*******************************************************************函数名:unsignedlongLOG_PrintLogTime**输入:unsignedlongulBufLen存储时间的空间长度**输出:unsignedchar*ucTime存储时间**功能描述:日志输出**返回值:unsignedlong****************************************************************/unsignedlongLOG_PrintLogTime(unsignedchar*ucTime,unsignedlongulBufLen){structtm*pstTmSec;structtimevalstTmMsec;if(NULL==ucTime){return-1;}gettimeofday(&stTmMsec,NULL);pstTmSec=localtime(&stTmMsec.tv_sec);snprintf((char*)ucTime,ulBufLen-1,"%04d-%02d-%02d%02d:%02d:%02d%03ldms",pstTmSec->tm_year+1900,pstTmSec->tm_mon+1,pstTmSec->tm_mday,pstTmSec->tm_hour,pstTmSec->tm_min,pstTmSec->tm_sec,stTmMsec.tv_usec/1000);return0;}/*******************************************************************函数名:unsignedchar*LOG_LogTypeToStr**输入:unsignedcharucType日志类型unsignedlongulBufLen存储日志类型字符串空间的长度**输出:unsignedchar*pucTypeString根据日志类型将其转换成相应的字符串**功能描述:根据日志类型转换成相应的字符串**返回值:unsignedlong****************************************************************/unsignedlongLOG_LogTypeToStr(unsignedcharucType,unsignedchar*pucTypeString,unsignedlongulBufLen){if(NULL==pucTypeString){return-1;}/*防止发生越界*/ulBufLen-=1;switch(ucType){caseLOG_DEBUG:{strncpy((char*)pucTypeString,"DEBUG",ulBufLen);break;}caseLOG_ERROR:{strncpy((char*)pucTypeString,"ERROR",ulBufLen);break;}caseLOG_WARNING:{strncpy((char*)pucTypeString,"WARNING",ulBufLen);break;}caseLOG_ACTION:{strncpy((char*)pucTypeString,"ACTION",ulBufLen);break;}caseLOG_SYSTEM:{strncpy((char*)pucTypeString,"SYSTEM",ulBufLen);break;}default:{strncpy((char*)pucTypeString,"UNKNOWN",ulBufLen);break;}}return0;}/*******************************************************************函数名:unsignedlongLOG_OpenLogFile**输入:void**输出:void**功能描述:打开日志文件**返回值:unsignedlong****************************************************************/unsignedlongLOG_OpenLogFile(void){char*path=(char*)g_ucLogFileName[g_ucLogFileNo];char*flag=NULL;intlen=0;/*判断文件是否已经打开*/if(NULL!=pFile){LOG_PRINT("[ACTION]fileopened!");return0;}/*判断文件名是否有定义*/if(NULL==path){LOG_PRINT("[ERROR]filenameisNULL.");return-1;}/*判断文件是否存在*/if(!access(path,0)){/*获取文件大小*/if(0>(len=get_file_size(path))){LOG_PRINT("[ERROR]getfilesizefailed!");return-1;}}flag=(len>0&&len=g_ulLogFileSize){fclose(pFile);pFile=NULL;g_ucLogFileNo=(g_ucLogFileNo+1)%MAX_LOG_FILE_NUM;}}pthread_mutex_unlock(&g_stSaveLogMutexLock);return0;}/*******************************************************************函数名:LOG_Init**输入:constunsignedchar*ucLogFileName用来保存日志的文件名unsignedlongulFileSize存储日志的文件大小**输出:void**功能描述:日志打印初始化**返回值:unsignedlong****************************************************************/unsignedlongLOG_Init(constunsignedchar*ucLogFileName,unsignedlongulFileSize){unsignedinti=0;/*判断参数的合法性*/if((NULL==ucLogFileName)||!(ulFileSize>0)){return-1;}/*判断是否将日志输出到日志文件*/if((PRINT_LOG_TO_FILE!=g_ulPrintLogPlaceFlag)||(0!=g_ulLogInitFlag)){printf("g_ulPrintLogPlaceFlag=%ldg_ulLogInitFlag=%ld\n",g_ulPrintLogPlaceFlag,g_ulLogInitFlag);LOG_PRINT("printlogtotermination!!");return0;}/*记录日志模块已经被初始化(防止改模块被重复初始化)*/g_ulLogInitFlag=1;/*生成存储日志的文件名*/for(i=0;i

log.h

#ifndef_LOG_H_#define_LOG_H_#include/*通用字符串存储大小定义*/#defineSTR_COMM_SIZE128#defineSTR_MAX_SIZE1024#defineMAX_LOG_FILE_NUM(3)#defineNUMBER(type)sizeof(type)/sizeof(type[0])#define__FILENAME__(strrchr(__FILE__,"/")?(strrchr(__FILE__,"/")+1):__FILE__)/*日志类型*/enum{LOG_DEBUG=0,/*调试日志*/LOG_ERROR,/*错误日志*/LOG_WARNING,/*告警日志*/LOG_ACTION,/*运行日志*/LOG_SYSTEM,/*系统日志*/BUTTOM};/*将日志输出到终端*/#definePRINT_LOG_TO_TERM(0)/*将日志输出到文件中*/#definePRINT_LOG_TO_FILE(1)/*调试日志宏定义*/#defineDEBUG_PRINT0#defineLOG_PRINT(fmt,...)do{\if(DEBUG_PRINT)\{\printf(fmt"[line:%d][%s]\n",##__VA_ARGS__,__LINE__,__FUNCTION__);\}\}while(0);/*错误日志打印(在日志打印模块还未启动时使用)*/#defineLOG_ERR(fmt,...)do{\printf("[ERROR]"fmt"[line:%d][%s]\n",##__VA_ARGS__,__LINE__,__FUNCTION__);\}while(0);/*存储日志标记.0-不存储日志,1-存储日志*/externunsignedlongg_ulPrintLogPlaceFlag;/*是否打印调试日志标记,0-不打印调试日志,1-打印调试日志*/externunsignedlongg_ulPrintDebugLogFlag;unsignedlongLOG_PrintLog(unsignedcharucType,unsignedchar*pucLogInfo);/*日志打印宏定义*/#defineLOG_INFO(type,fmt,...)do{\if(PRINT_LOG_TO_TERM==g_ulPrintLogPlaceFlag)\{\if((0==g_ulPrintDebugLogFlag)&&(LOG_DEBUG==type))\{\break;\}\unsignedcharucLogInfo[STR_MAX_SIZE]={0};\snprintf((char*)ucLogInfo,sizeof(ucLogInfo)-1,fmt"[%s][line:%d][%s]\n",##__VA_ARGS__,__FILENAME__,__LINE__,__FUNCTION__);\LOG_PrintLog(type,ucLogInfo);\}\else\{\unsignedcharucLogInfo[STR_MAX_SIZE]={0};\snprintf((char*)ucLogInfo,sizeof(ucLogInfo)-1,fmt"[%s][line:%d][%s]\n",##__VA_ARGS__,__FILENAME__,__LINE__,__FUNCTION__);\LOG_PrintLog(type,ucLogInfo);\}\}while(0)/*是否打印调试日志标记,0-不打印调试日志,1-打印调试日志*/externvoidLOG_SetPrintDebugLogFlag(unsignedlongflag);/*存储日志标记.0-不存储日志,1-存储日志*/externvoidLOG_SetPrintLogPlaceFlag(unsignedlongflag);externunsignedlongLOG_Init(constunsignedchar*ucLogFileName,unsignedlongulFileSize);externvoidLOG_Destroy(void);#endif//_LOG_H_

main.c

#include#include"log.h"inttest_func1(){LOG_INFO(LOG_DEBUG,"%s","helloworld!!");return0;}intmain(intargc,char*argv[]){LOG_SetPrintDebugLogFlag(1);//打印调试信息//LOG_SetPrintLogPlaceFlag(1);//保存打印信息到文件LOG_Init("info",8000);LOG_INFO(LOG_DEBUG,"%s","Initlog!!");test_func1();LOG_INFO(LOG_DEBUG,"%s","Destroylog!!");LOG_Destroy();}

执行结果:

由执行结果可以看出一条打印信息包含了时间、日志类型、内容、文件名、行号、函数名等信息,这样就能够方便快速的定位问题,其使用方法也与printf函数类似,简单方便。

其次该日志模块还支持将日志存至文件,可以自行定义文件的大小及个数,日志循环覆盖。

觉得文章不错,点击“分享”、“赞”、“在看” 呗!

关键词:

新闻推荐