背景
项目代码的打印函数,有的用printf,有的用std::cout,风格不统一,也不方便查看,因此需要编写一个统一的函数接口。
需求及实现
- 时间戳
该打印函数需要有时间戳,精确到毫秒。这样能直观观察程序运行时间。获取时间使用localtime函数,毫秒的获取使用gettimeofday函数。获取时间戳函数get_timestamp没有使用静态局部变量,使用4线程测试,时间戳没有错误情况发生。
- 打印等级
函数需要有打印等级,目前分为ERROR、WARNING、INFO、DEBUG几种,等级越高,数字越小。在使用时需要根据实际情况,出错的情况使用ERROR。为代码简洁起见,使用gcc扩展语法。
代码如下:
1 | static const char* s_loginfo[] = { |
这样通过s_loginfo数组即可获取等级对应的字符串。注意,这种语法只能在C语言中使用,C++代码编译报错。
- 附加信息
打印时,要附带文件名、行号信息(当然,也可打印函数名称),此举在于方便定位代码。由于Makefile可能不与实现文件在同一目录,因此,文件名可能会带有路径信息,需要用strrchr查找“/”,达到保留文件名的目的。详细参考代码。
- 检查参数
代码实现需要严谨,传入参数需要严格检查。这里再次使用gcc扩展语法:__attribute__((format(printf,N,M)));
这样的好处是,能避免参数不一致。比如字符串使用%d打印时,会提示编译警告。
扩展(未完事宜)
打印等级控制没有很好实现,只是在代码中固定定义一个宏,理论上应该在Makefile中定义,这样无须修改代码。另外,也可以通过配置文件的形式,在执行程序时手动配置等级。
没有添加syslog,因为考虑到docker部署,也考虑到调试权限问题,所以未添加。
处理不同的等级,如ERROR等级的,需要写入EEPROM或flash指定分区文件,以方便长久保存。
完整代码
头文件声明如下:
1 | #ifndef LOG_H_ |
实现代码如下:
1 | /** |
注:本文所示代码可随意使用。代码不是最终应用到实际项目版本。
李迟 XX