苏州知名网站制作,太原整站优化排名外包,网页设计代码td,wordpress插件中文版下载今日分享一下#xff0c;从某源码中看到这种日志编写方式#xff0c;很强。可以借鉴。
这个函数调用的日志函数是不一样的#xff0c;仔细观看#xff1a;
这几种日志输出函数#xff0c;背后都调用了相同的调用。 与之对应的区别就是#xff0c;函数名称的差异取决于…今日分享一下从某源码中看到这种日志编写方式很强。可以借鉴。
这个函数调用的日志函数是不一样的仔细观看
这几种日志输出函数背后都调用了相同的调用。 与之对应的区别就是函数名称的差异取决于调用函数所传入参数的不同。
PLAT_LOG_LEVEL_ERROR PLAT_LOG_LEVEL_WARN PLAT_LOG_LEVEL_INFO
这三个宏的不同代表不同的日志严重等级。
#define aloge(fmt, arg...) GLOG_PRINT(PLAT_LOG_LEVEL_ERROR, fmt, ##arg)
#define alogw(fmt, arg...) GLOG_PRINT(PLAT_LOG_LEVEL_WARN, fmt, ##arg)
#define alogd(fmt, arg...) GLOG_PRINT(PLAT_LOG_LEVEL_INFO, fmt, ##arg)
#define alogv(fmt, arg...)#define PLAT_LOG_LEVEL_INFO _GLOG_INFO#define PLAT_LOG_LEVEL_WARN _GLOG_WARN#define PLAT_LOG_LEVEL_ERROR _GLOG_ERROR#define PLAT_LOG_LEVEL_FATAL _GLOG_FATAL宏 GLOG_PRINT 是这样的
/*** brief 定义日志打印宏** 此宏用于在代码中方便地打印不同级别的日志信息。它自动包含文件名、函数名、行号以及自定义的日志级别和格式化字符串。** param[in] level 日志级别用于区分日志的重要程度如DEBUG、INFO、WARN、ERROR等。* param[in] fmt 格式化字符串遵循printf风格用于构造日志的具体文本内容。* param[in] arg... 可变参数列表与fmt字符串中的占位符对应支持多个参数输入。** note* - 使用##arg确保在参数为空的情况下宏展开正确。* - 宏通过do-while(0)结构保证其具有块语句的特性可直接作为单条语句使用而无需额外的大括号包裹。* - __FILE__、__func__、__LINE__是预处理器宏分别表示源文件名、函数名、当前行号提供日志的详细来源信息。** 示例* code* GLOG_PRINT(DEBUG, 这是一条调试信息变量x的值为%d, x);* endcode*/
#define GLOG_PRINT(level, fmt, arg...) \
do { \log_printf(__FILE__, __func__, __LINE__, level, fmt, ##arg); \
} while (0)定义宏 GLOG_PRINT用于打印日志信息。 宏中 ##arg 语法是C/C语言的变参宏技巧处理可变参数。## 的作用是在宏中将可变长度参数的前一个参数和后一个参数连接起来如果可变长度参数为空则不产生任何内容。
GLOG_PRINT 宏展开后会调用 log_printf 函数传递参数 __FILE__, __func__, __LINE__, level, fmt 以及可变数量的 arg 参数。##arg 确保在参数列表为空时不会生成多余的逗号或者括号。
代码定义日志打印宏 GLOG_PRINT通过变参的方式传递不定数量的参数。
_GLOG_INFO _GLOG_WARN _GLOG_ERROR _GLOG_FATAL 这4个宏配置在这个文件中
#ifndef LOG_PRINT_H_
#define LOG_PRINT_H_#define _GLOG_INFO 0
#define _GLOG_WARN 1
#define _GLOG_ERROR 2
#define _GLOG_FATAL 3#ifdef __cplusplus
extern C {
#endif
typedef struct GLogConfig
{//log messages go to stderr instead of logfilesint FLAGS_logtostderr; // false; //--logtostderr1, GLOG_logtostderr1//color messages logged to stderr (if supported by terminal)int FLAGS_colorlogtostderr; // true;//log messages at or above this level are copied to stderr in addition to logfiles. This flag obsoletes --alsologtostderr.int FLAGS_stderrthreshold; // google::GLOG_WARNING;//Messages logged at a lower level than this dont actually get logged anywhereint FLAGS_minloglevel; // google::GLOG_INFO;//Buffer log messages logged at this level or lower (-1 means dont buffer; 0 means buffer INFO only;...)int FLAGS_logbuflevel; // -1;//Buffer log messages for at most this many secondsint FLAGS_logbufsecs; // 0;//approx. maximum log file size (in MB). A value of 0 will be silently overridden to 1.int FLAGS_max_log_size; // 25;//Stop attempting to log to disk if the disk is full.int FLAGS_stop_logging_if_full_disk; // true;//e.g., /tmp/log/LOG-char LogDir[128]; //e.g., /tmp/logchar InfoLogFileNameBase[128]; //e.g., LOG-char LogFileNameExtension[128]; //e.g., SDV-
}GLogConfig;
void log_init(const char *program, GLogConfig *pConfig);
void log_quit();
int log_printf(const char *file, const char *func, int line, const int level, const char *format, ...);#ifdef __cplusplus
}
#endif#endif
GLOG_PRINT带参数宏调用的函数
/*** brief 打印格式化日志根据日志级别使用Google日志系统输出** 此函数接收一个文件名、函数名、行号、日志级别和一个可变参数列表用于生成和打印格式化的日志消息。* 它首先尝试在固定大小的缓冲区中格式化字符串如果需要更大的空间则动态分配内存。** param file 日志产生时的源代码文件名* param func 调用此函数的函数名* param line 产生日志的源代码行号* param level 日志级别可以是预定义的_GLOG_INFO, _GLOG_WARN, _GLOG_ERROR, _GLOG_FATAL* param format 格式化字符串类似于printf函数的格式控制符** return 返回0目前此函数没有实际返回值** note* - 使用vsnprintf进行安全的格式化字符串处理。* - 如果格式化后的字符串长度超过固定缓冲区大小将尝试动态分配内存以适应字符串长度。* - 动态分配的内存会在函数结束前释放。* - 根据日志级别使用google::LogMessage流对象将日志输出到相应的日志级别。*/int log_printf(const char *file, const char *func, int line, const int level, const char *format, ...)
{int result 0;char ChBuffer[128] {0}; // 初始化为零的固定大小缓冲区char *buffer NULL;char *p NULL;int n;int size sizeof(ChBuffer); // 缓冲区初始大小va_list args; // 变长参数列表指针// 初始化变长参数列表va_start(args, format);// 格式化字符串到固定大小的缓冲区n vsnprintf(ChBuffer, size, format, args);// 结束变长参数列表va_end(args);// 如果格式化成功且字符串长度小于固定缓冲区大小直接使用ChBufferif (n -1 n size){buffer ChBuffer;}// 否则如果需要更多空间尝试动态分配内存else if (n -1){size n 1; // 获取精确需要的内存大小if ((p (char*)malloc(size)) NULL){// 内存分配失败使用固定缓冲区printf((f:%s, l:%d) fatal error! n%d. use previous buffer\n, __FUNCTION__, __LINE__, n);buffer ChBuffer;}else{// 重新格式化到新分配的内存va_start(args, format);n vsnprintf(p, size, format, args);va_end(args);// 如果格式化成功使用新分配的内存if (n -1 n size){buffer p;}else{// 格式化失败使用固定缓冲区printf((f:%s, l:%d) fatal error! n%d. use previous buffer\n, __FUNCTION__, __LINE__, n);buffer ChBuffer;}}}else{// 格式化失败使用固定缓冲区printf((f:%s, l:%d) fatal error! n%d. use previous buffer\n, __FUNCTION__, __LINE__, n);buffer ChBuffer;}// 根据日志级别输出日志switch (level){case _GLOG_INFO:google::LogMessage(file, line).stream() XPOSTO(60) func // XPOSTO(90) buffer;break;case _GLOG_WARN:google::LogMessage(file, line, google::GLOG_WARNING).stream() XPOSTO(60) func // XPOSTO(90) buffer;break;case _GLOG_ERROR:google::LogMessage(file, line, google::GLOG_ERROR).stream() XPOSTO(60) func // XPOSTO(90) buffer;break;case _GLOG_FATAL:google::LogMessage(file, line, google::GLOG_FATAL).stream() XPOSTO(60) func // XPOSTO(90) buffer;break;default:google::LogMessage(file, line).stream() XPOSTO(60) func // XPOSTO(90) buffer;break;}// 释放动态分配的内存if (p){free(p);p NULL;}return result;
}