第一次发博客,不喜勿喷,谢谢!
之前在项目中,发现设备产生的log好乱,或许只有编写代码的人在编写代码的时候才能明确的知道是什么意思吧!作为一个菜鸟来说,Debug似乎很难,如果你要通过log找到其中的当前状态下的代码逻辑或者错误之处,都不是简单的事。我感觉最操蛋的是通过grep -nr ... 搜索log的出处。
所以,作为菜鸟的我,尝试写一个log输出的我自己的log输出方法,既方便自己在项目中使用又便于后续Debug。差不多半天的时间终于搞出来了,感觉还凑合(如果哪位大牛愿意指教的话,欢迎留言指导),所以拿出来分享和我一样的菜鸟们...
#ifndef _LOG_H_
#define _LOG_H_
#include <stdio.h>
#include <time.h>
#include <stdarg.h>
#ifdef NOLOG
#define LOG(...)
#define LogInfo(...)
#define LogError(...)
#define LogWarning(...)
#define LogDebug(...)
#else
#define NONECOLOR "\e[0m"
#define BLACKCOLOR "\e[0;30m"
#define L_BLACKCOLOR "\e[1;30m"
#define REDCOLOR "\e[0;31m"
#define L_REDCOLOR "\e[1;31m"
#define GREENCOLOR "\e[0;32m"
#define L_GREENCOLOR "\e[1;32m"
#define BROWNCOLOR "\e[0;33m"
#define YELLOWCOLOR "\e[1;33m"
#define BLUECOLOR "\e[0;34m"
#define L_BLUECOLOR "\e[1;34m"
#define PURPLECOLOR "\e[0;35m"
#define L_PURPLECOLOR "\e[1;35m"
#define CYANCOLOR "\e[0;36m"
#define L_CYANCOLOR "\e[1;36m"
#define GRAYCOLOR "\e[0;37m"
#define WHITECOLOR "\e[1;37m"
#define BOLDCOLOR "\e[1m"
#define UNDERLINECOLOR "\e[4m"
#define BLINKCOLOR "\e[5m"
#define REVERSECOLOR "\e[7m"
#define HIDECOLOR "\e[8m"
#define CLEARCOLOR "\e[2J"
#define CLRLINECOLOR "\r\e[K" //or "\e[1K\r"
#ifdef NOCOLOR
#define ERRORSTART "Error:"
#define ERROREND
#define WARNINGSTART "Warning:"
#define WARNINGEND
#else
#define ERRORSTART REDCOLOR "Error:" BROWNCOLOR
#define ERROREND NONECOLOR
#define WARNINGSTART PURPLECOLOR "Warning:" BLUECOLOR
#define WARNINGEND NONECOLOR
#endif
#define INFOSTART "Info:"
#define INFOEND
#define DEBUGSTART "Debug:"
#define DEBUGEND
void consolelogger_log(const char* format, ...);
#ifdef NOTIME
#define TIMEARG(_ptm)
#define TIMEFORMAT
#else
#define TIMEARG(_ptm) ((_ptm)->tm_year + 1900), ((_ptm)->tm_mon + 1), (_ptm)->tm_mday, (_ptm)->tm_hour, (_ptm)->tm_min, (_ptm)->tm_sec
#define TIMEFORMAT "%d-%d-%d %d:%d:%d "
#endif
#ifdef NOLOCALTION
#define LOCALTIONARG
#define LOCALTION
#else
#define LOCALTIONARG(_modulename) _modulename,__FILE__, __FUNCTION__, __LINE__
#define LOCALTION " %s %s %s():%d "
#endif
#define LOG(format,...) { consolelogger_log(format,##__VA_ARGS__); }
#ifdef NOLOGINFO
#define LogInfo(...)
#else
#define LogInfo(modulename,format,...) do{ \
time_t now = time(NULL); \
struct tm * localnow = localtime(&now); \
LOG(TIMEFORMAT INFOSTART LOCALTION format INFOEND,TIMEARG(localnow),LOCALTIONARG(modulename),##__VA_ARGS__);\
}while(false)
#endif
#ifdef NOLOGERROR
#define LogError(...)
#else
#define LogError(modulename,format,...) do{ \
time_t now = time(NULL); \
struct tm * localnow = localtime(&now); \
LOG(TIMEFORMAT ERRORSTART LOCALTION format ERROREND,TIMEARG(localnow),LOCALTIONARG(modulename),##__VA_ARGS__);\
}while(false)
#endif
#ifdef NOLOGWARNING
#define LogWarning(...)
#else
#define LogWarning(modulename,format,...) do{ \
time_t now = time(NULL); \
struct tm * localnow = localtime(&now); \
LOG(TIMEFORMAT WARNINGSTART LOCALTION format WARNINGEND,TIMEARG(localnow),LOCALTIONARG(modulename),##__VA_ARGS__);\
}while(false)
#endif
#ifdef NOLOGDEBUG
#define LogDebug(...)
#else
#define LogDebug(modulename,format,...) do{ \
time_t now = time(NULL); \
struct tm * localnow = localtime(&now); \
LOG(TIMEFORMAT DEBUGSTART LOCALTION format DEBUGEND,TIMEARG(localnow),LOCALTIONARG(modulename),##__VA_ARGS__);\
}while(false)
#endif
void consolelogger_log(const char* format, ...)
{
va_list args;
va_start(args, format);
(void)vprintf(format, args);
va_end(args);
(void)printf("\n");
}
#endif
#endif
这样主要有以下的好处:
第一是通过宏定义封装了一个输出函数,由宏定义的不同确定了log输出的等级之分(error,warning,info,debug);error和warning的log输出分别是红色和粉红色,便于调试和后期Debug;第二是封装了参数模块名称,这个可以通过模块内部通过宏定义再次封装(不需要每次输出都带有模块名称的参数),方便各个模块的log分离查看;第三是各个等级的log可以通过宏定义直接关掉,方便随时关掉某一类log;第四是log输出的完整性,有时间戳,有log输出的代码位置,还有log等级以及输出的描述信息(当然了,这些都可以通过宏定义关掉某个部分的);
就这样了,不知道还OK不?