给大家分享一下嵌入式 c 语言日志分级
日志分级概念
所谓日志分级,就是将日志按照不同的层次,有选择的输出。
参考一些高级语言的分级日志设计,我们根据对程序运行信息的类型把控,可以把日志分为5个级别debug、info、warn、error、fatal。
debug:主要用于程序开发测试阶段的打印输出,用于验证程序的设计逻辑是否满足上层应用的设计需求,在经过测试检验后的发布程序可以把它关掉。
info:这个级别的打印输出是用来告诉测试人员或者开发人员一些提示的信息
wran:这是一种警告的打印输出,它一般是用来输出诸如用户输入错误的数据之类的警告打印,这个级别的打印输出在程序发布后也建议保留,以方面后期程序的维护追踪。
error:运行出错的打印,这个级别的打印在发布的软件不可关闭,否则无法从发布软件中获取一些反馈信息来指导我们新的程序优化设计。
fatal :程序运行遇到这种级别的问题,很难修复,一般伴随着程序的闪退或重启,此时fatal error的打印则非常关键了,可以帮助我们定位到程序跑飞的原因,fatal error级别的打印在任何时刻都不可以关闭。
为什么要有日志分级?
一个好的日志分级设计,有助于我们快速定位问题,主要是方便后续开发和维护。在设计软件的时候,可以根据问题出现的轻重缓急,有决策的去添加分层信息,在必要的时候有针对性的打开和关闭一些日志。
如何设计?
目前有两种粗浅的设计策略,一种是或的关系,即各个日志等级彼此独立,可以单独打开关闭;一种是顺序打印,根据设置打印等级,低于或者高于这个等级的才打印。
两种没有孰好孰坏,根据需要选择合适策略即可。本文将以后者介绍。
设置打印级别
/* module_debug.h *//*1. 设置打印级别 */enum { log_level_none, log_level_debug, log_level_info, log_level_warn, log_level_error, log_level_fatal,};/* 2. log 打印 重写 */void log_fun(int level, const char *opt, const char* tag, int line, const char *func, const char *fmt, ...);/* 3. 各打印级别宏 *//* *@log_dbg */ #define log_dbg(tag, fmt, ...) log_fun(log_level_debug, d, tag , __line__, __func__, fmt, ##__va_args__)/* *@log_info */ #define log_info(tag, fmt, ...) log_fun(log_level_info, i, tag , __line__, __func__, fmt, ##__va_args__)/* *@log_warn */ #define log_warn(tag, fmt, ...) log_fun(log_level_warn, w, tag , __line__, __func__, fmt, ##__va_args__)/* *@log_err */ #define log_err(tag, fmt, ...) log_fun(log_level_error, e, tag , __line__, __func__, fmt, ##__va_args__)/* *@log_fatal */ #define log_fatal(tag, fmt, ...) log_fun(log_level_fatal, f, tag , __line__, __func__, fmt, ##__va_args__)
注释:... 和 __va_args__.省略点表示可变参数,__va_args__表示可变参数的宏,是c99规范中新增的,用来替换宏定义中的可变参数(...); ##运算符将两个宏参数连接在一起。##__va_args__ 这里主要是为了解决当__va_args__为空时编译问题,使用##防止编译出错。
根据打印级别控制输出范围
/* module_debug.c */#include #include #include #include #include #include #include int g_current_dbg_level = log_level_debug;void log_fun(int level, const char *opt, const char* tag, int line, const char *func, const char *fmt, ...){ if (level > g_current_dbg_level) { char msg_buf[20*1024]; va_list ap; va_start(ap,fmt); sprintf(msg_buf,%s/%s (%d): %s() ,opt, tag, line, func); vsprintf(msg_buf+strlen(msg_buf),fmt,ap); fprintf(stderr,%s,msg_buf); /* 输出到标准输出 */ va_end(ap); }}/* 设置 打印级别 */void moduledebuginit(int level){ g_current_dbg_level = level;}
测试
/* main.c */#include #define tag testint main (int argc , char *argv[]){ log_dbg(tag, log_debug %d , log_level_debug); log_info(tag, log_info %d , log_level_info); log_warn(tag, log_warn ); log_err(tag, log_err ); return 0;}
输出打印信息:
i/test (61): main() log_info 2 w/test (62): main() log_warn e/test (63): main() log_err
其中i表示info、w表示warn、e表示error;紧接着跟着模块(test),也可以是文件名;然后是行号、函数名,最后是打印信息。
当然具体打印信息和风格用户可以根据需要,自行设计。
中兴通讯MEC业务连续性优化方案,满足5G新应用差异化的需求
5款手机告诉你什么是真正的旗舰
五百左右哪款蓝牙耳机好用?适合学生党的蓝牙耳机测评
4层板,板边铺地打屏蔽过孔对打静电有效果没?
交管大数据治理的挑战及应对方法 易华录构建交管数据治理体系
如何设计嵌入式C语言日志分级?
TI的集成式变压器模块技术有助于进一步增加混动和电动汽车的行驶时间
星和推出首个“非独立”的5G网络服务
联建光电携手国星光电国内首发Mini LED
什么叫超融合基础架构,它的作用是什么
华为展示黑科技凤凰引擎,或为自研GPU铺路
汽车电子EMC的标准,EMC测试出现的主要问题
天齐锂业与SKI签订协议 将向下游新能源汽车厂商提供先进的高镍可充电锂离子电池
LWGY系列涡轮流量传感器的工作原理及特点应用
用于高通量单液滴的操纵和生成的有源矩阵数字微流控芯片
智能镜子显示屏可实现全宅的智能化管理和控制
关于单片机输出用推挽还是开漏 哪个更好
Exar将在ESC上展示最新电源管理和接口解决方案
mysql中的数据大于千万怎么办
英创WinCE工控主板的3种不同的WiFi解决方案