前言
- c语言没有现成的日志库,如果要记录日志,需要自己封装一个日志库。如果要实现日志级别和参数打印,还是比较麻烦的,正好在github找到了一个c语言开源日志库,可以实现日志级别打印,参数打印,而且还会记录日期和行号,最重要的是代码非常少,只有100多行,可以直接包含在我们自己的工程代码中,不需要任何依赖。
源码地址
- github源码连接
使用介绍
- 直接把工程目录下的log.c和log.h下载下来,包含到工程代码中即可,没有其他依赖。
- 日志级别由低到高,分别为 LOG_TRACE、LOG_DEBUG、LOG_INFO、LOG_WARN、LOG_ERROR、LOG_FATAL
- 如果设置日志级别为LOG_TRACE,则所有级别日志都会打印,如果设置日志级别为LOG_WARN,则只会打印LOG_WARN以及更高级别(即LOG_ERROR和LOG_FATAL)的日志
演示
- 测试代码 -
#include"log.h"#include<stdio.h>intmain(){ FILE *fp =fopen("log.txt","a+");if(fp ==NULL){printf("create log file failed.\n");return-1;}//设置日志级别(在终端打印)log_set_level(LOG_TRACE);//设置日志级别(在文件中打印)log_add_fp(fp, LOG_INFO);log_trace("start trace.");log_debug("start debug.");log_info("start info.");log_warn("start warn.");log_error("start error.");log_fatal("start fatal");// 支持参数打印log_info("number is %d, string is %s",10010,"helloword");fclose(fp);}
- 演示效果
源码
- 如果访问github有问题,我把源码贴到下面了。
- log.h -
#ifndefLOG_H#defineLOG_H#include<stdio.h>#include<stdarg.h>#include<stdbool.h>#include<time.h>#defineLOG_VERSION"0.1.0"typedefstruct{ va_list ap;constchar*fmt;constchar*file;structtm*time;void*udata;int line;int level;} log_Event;typedefvoid(*log_LogFn)(log_Event *ev);typedefvoid(*log_LockFn)(bool lock,void*udata);enum{ LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };#definelog_trace(...)log_log(LOG_TRACE,__FILE__,__LINE__, __VA_ARGS__)#definelog_debug(...)log_log(LOG_DEBUG,__FILE__,__LINE__, __VA_ARGS__)#definelog_info(...)log_log(LOG_INFO,__FILE__,__LINE__, __VA_ARGS__)#definelog_warn(...)log_log(LOG_WARN,__FILE__,__LINE__, __VA_ARGS__)#definelog_error(...)log_log(LOG_ERROR,__FILE__,__LINE__, __VA_ARGS__)#definelog_fatal(...)log_log(LOG_FATAL,__FILE__,__LINE__, __VA_ARGS__)constchar*log_level_string(int level);voidlog_set_lock(log_LockFn fn,void*udata);voidlog_set_level(int level);voidlog_set_quiet(bool enable);intlog_add_callback(log_LogFn fn,void*udata,int level);intlog_add_fp(FILE *fp,int level);voidlog_log(int level,constchar*file,int line,constchar*fmt,...);#endif
- log.c -
#include"log.h"#defineMAX_CALLBACKS32typedefstruct{ log_LogFn fn;void*udata;int level;} Callback;staticstruct{void*udata; log_LockFn lock;int level; bool quiet; Callback callbacks[MAX_CALLBACKS];} L;staticconstchar*level_strings[]={"TRACE","DEBUG","INFO","WARN","ERROR","FATAL"};#ifdefLOG_USE_COLORstaticconstchar*level_colors[]={"\x1b[94m","\x1b[36m","\x1b[32m","\x1b[33m","\x1b[31m","\x1b[35m"};#endifstaticvoidstdout_callback(log_Event *ev){char buf[16]; buf[strftime(buf,sizeof(buf),"%H:%M:%S", ev->time)]='\0';#ifdefLOG_USE_COLORfprintf(ev->udata,"%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", buf, level_colors[ev->level], level_strings[ev->level], ev->file, ev->line);#elsefprintf(ev->udata,"%s %-5s %s:%d: ", buf, level_strings[ev->level], ev->file, ev->line);#endifvfprintf(ev->udata, ev->fmt, ev->ap);fprintf(ev->udata,"\n");fflush(ev->udata);}staticvoidfile_callback(log_Event *ev){char buf[64]; buf[strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S", ev->time)]='\0';fprintf(ev->udata,"%s %-5s %s:%d: ", buf, level_strings[ev->level], ev->file, ev->line);vfprintf(ev->udata, ev->fmt, ev->ap);fprintf(ev->udata,"\n");fflush(ev->udata);}staticvoidlock(void){if(L.lock){ L.lock(true, L.udata);}}staticvoidunlock(void){if(L.lock){ L.lock(false, L.udata);}}constchar*log_level_string(int level){return level_strings[level];}voidlog_set_lock(log_LockFn fn,void*udata){ L.lock = fn; L.udata = udata;}voidlog_set_level(int level){ L.level = level;}voidlog_set_quiet(bool enable){ L.quiet = enable;}intlog_add_callback(log_LogFn fn,void*udata,int level){for(int i =0; i < MAX_CALLBACKS; i++){if(!L.callbacks[i].fn){ L.callbacks[i]=(Callback){ fn, udata, level };return0;}}return-1;}intlog_add_fp(FILE *fp,int level){returnlog_add_callback(file_callback, fp, level);}staticvoidinit_event(log_Event *ev,void*udata){if(!ev->time){time_t t =time(NULL); ev->time =localtime(&t);} ev->udata = udata;}voidlog_log(int level,constchar*file,int line,constchar*fmt,...){ log_Event ev ={.fmt = fmt,.file = file,.line = line,.level = level,};lock();if(!L.quiet && level >= L.level){init_event(&ev,stderr);va_start(ev.ap, fmt);stdout_callback(&ev);va_end(ev.ap);}for(int i =0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++){ Callback *cb =&L.callbacks[i];if(level >= cb->level){init_event(&ev, cb->udata);va_start(ev.ap, fmt); cb->fn(&ev);va_end(ev.ap);}}unlock();}
本文转载自: https://blog.csdn.net/new9232/article/details/132992574
版权归原作者 大草原的小灰灰 所有, 如有侵权,请联系我们删除。
版权归原作者 大草原的小灰灰 所有, 如有侵权,请联系我们删除。