所谓日志分级,就是将日志按照不同的层次,有选择的输出。
参考一些高级语言的分级日志设计,我们根据对程序运行信息的类型把控,可以把日志分为5个级别DEBUG、INFO、WARN、ERROR、FATAL。
一个好的日志分级设计,有助于我们快速定位问题,主要是方便后续开发和维护。在设计软件的时候,可以根据问题出现的轻重缓急,有决策的去添加分层信息,在必要的时候有针对性的打开和关闭一些日志。
目前有两种粗浅的设计策略,一种是或的关系,即各个日志等级彼此独立,可以单独打开关闭;一种是顺序打印,根据设置打印等级,低于或者高于这个等级的才打印。
两种没有孰好孰坏,根据需要选择合适策略即可。本文将以后者介绍。
设置打印级别
/* 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 "test"
int 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),也可以是文件名;然后是行号、函数名,最后是打印信息。
当然具体打印信息和风格用户可以根据需要,自行设计。
审核编辑 :李倩
全部0条评论
快来发表一下你的评论吧 !