log.c是什么?

描述

这两天发现一个还不错的开源项目,记录一下学习心得。对于嵌入式底层应用开发,基本离不开日志功能,这种轮子有很多,log.c 最简单,达到了开箱即用的级别。
 

log.c 是什么?


	https://github.com/rxi/log.c 简单地说,log.c 就是一个 C 语言的日志功能模块。开源项目点击查看大图log.c 的几个特点:代码简洁,就一个 .c 和 .h 文件,一共 200 行。设计优雅,打印日志的 API 只有 1 个。提供了将 log 输入到不同目标的接口,例如输入到文件。提供了实现线程安全的接口。 

log.c 怎么用?

打印日志的 API:

	log_trace(const char *fmt, ...); log_debug(const char *fmt, ...); log_info(const char *fmt, ...); log_warn(const char *fmt, ...); log_error(const char *fmt, ...); log_fatal(const char *fmt, ...); 它们都是对 log_log() 的简单封装,用法和 printf() 一样。示例:下面的例子会将日志同时输出到标准输出和文件中。

	#include "log.h" int main(int argc, char *argv[]) {     log_set_level(0);     log_set_quiet(0);     FILE *fp1, *fp2;     fp1 = fopen("./log_info.txt""ab");     if(fp1 == NULL)         return -1;     fp2 = fopen("./log_debug.txt""ab");     if(fp2 == NULL)         return -1;     log_add_fp(fp1, LOG_INFO);     log_add_fp(fp2, LOG_DEBUG);     log_debug("debug");     log_info("info");     log_warn("warn");     fclose(fp2);     fclose(fp1);     return 0; } 运行:

	$ ./example1  2305 DEBUG example1.c debug 2305 INFO  example1.c info 2305 WARN  example1.c warn $ cat log_debug.txt  2022-05-08 2305 DEBUG example1.c debug 2022-05-08 2305 INFO  example1.c info 2022-05-08 2305 WARN  example1.c warn $ cat log_info.txt  2022-05-08 2305 INFO  example1.c info 2022-05-08 2305 WARN  example1.c warn 关于线程安全:log.c 代码虽然少,但是仍然考虑了线程安全,下面是用法示例。

	#include "log.h" pthread_mutex_t MUTEX_LOG; void log_lock(bool lock, void *udata); int main() {     log_set_level(0);     log_set_quiet(0);     pthread_mutex_init(&MUTEX_LOG, NULL);     log_set_lock(log_lock, &MUTEX_LOG);     /* Insert threaded application code here... */     log_info("I'm threadsafe");     pthread_mutex_destroy(&MUTEX_LOG);     return 0; } void log_lock(bool lock, void* udata) {     pthread_mutex_t *LOCK = (pthread_mutex_t*)(udata);     if (lock)         pthread_mutex_lock(LOCK);     else         pthread_mutex_unlock(LOCK); } 

log.c 的内部实现?

私有数据结构:开源项目点击查看大图全局变量 L 维护了 log.c 所需要的所有信息。void *udata 用于保存用户数据,用户可以将其用作任意用途。lock 是一个函数指针:。

	typedef void (*log_LockFn)(bool lock, void *udata); 用户可以用它来指定自己想用的锁机制,例如 Pthread 的互斥量。int level 用于保存当前的 log 等级,等级大于 level 的 log 才会被输出到标准输出。bool quiet 用于打开、关闭 log 输出。数组 callbacks 用于保存多种输出方式,目前仅支持输出到标准输出和文件,有需要的话我们还可以将其扩展成输出到 syslog、网络等,每增加一种输出方式就是构造一个 Callback,成员回调函数 log_LogFn 负责真正地 log 输出功能:

	typedef void (*log_LogFn)(log_Event *ev); 公共数据结构:开源项目点击查看大图一条 log 信息对应一个 log_Event。暴露这个数据结构是为了用户可以编写自己的 log 打印函数 log_LogFn 以输出 log。公共的 API:整个 log.c 其实只提供了一个打印相关的 API:log_log()。log_trace() 等宏只是对 log_log() 的简单封装,这种简洁地设计无论是对库的用户还是对库的开发者而言,都是最幸福的事情。剩下的几个 API 用于控制和功能扩展。log_log() 的实现思路1> 根据用于提供的 log 信息构造 1个 log_Event。2> 将 log 信息输出到标准输出。3> 遍历所有 log Callback,逐一调用它们的打印函数 log_LogFn。 

总结

log.c 代码优雅、设计简洁、功能实用,这对库的用户和库的开发者而言,都是一种幸福。如果你的项目需要一个简单好用的日志功能,可以考虑集成开箱即用的 log.c

审核编辑 :李倩


打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分