c/c++语言的一种日志的编写办法

今日分享一下,从某源码中看到这种日志编写方式,很强。可以借鉴。

这个函数调用的日志函数是不一样的,仔细观看:
在这里插入图片描述

这几种日志输出函数,背后都调用了相同的调用。
与之对应的区别就是,函数名称的差异取决于调用函数所传入参数的不同。

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 logfiles"int FLAGS_logtostderr;  // = false;  //--logtostderr=1, GLOG_logtostderr=1//"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 don't actually get logged anywhere"int FLAGS_minloglevel; // = google::GLOG_INFO;//"Buffer log messages logged at this level or lower (-1 means don't buffer; 0 means buffer INFO only;...)"int FLAGS_logbuflevel; // = -1;//"Buffer log messages for at most this many seconds"int 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/log"char 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/865970.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mpeg格式怎么转换成mp4?这四种转换方法非常好用!

mpeg格式怎么转换成mp4&#xff1f;在数字视频领域中&#xff0c;MPEG格式算是相对冷门的一种选择&#xff0c;然而&#xff0c;选择这种格式却不是没有代价的&#xff0c;首先&#xff0c;MPEG采用了有损压缩技术&#xff0c;这意味着在视频处理过程中&#xff0c;会丢失一些细…

单个企业年收入达24.7亿!银发游学市场按下“加速键”,兴趣教育平台抢滩布局

干货抢先看 1. 银发游学市场渐趋火热&#xff0c;美国最大的银发游学机构Road Scholar最新披露的财报显示&#xff0c;上个财年公司收入达3.395亿美元&#xff08;约合人民币24.7亿&#xff09;。 2. 在国内&#xff0c;一批专注银发兴趣教育的品牌纷纷入局&#xff0c;拓展游…

MYSQL8.0配置

1、下载安装包 2、解压软件包 将MySQL软件包解压在没有中文和空格的目录下 3、设置配置文件my.ini my.ini中加入以下内容 [client] #客户端设置&#xff0c;即客户端默认的连接参数 # 设置mysql客户端连接服务端时默认使用的端口 port3306#默认编码 default-character-set…

一个使用 g++ 模块化编译的 hello world 示例( Ubuntu 20.04 )

1. 确认 ubuntu 版本&#xff1a; 2. 文件夹结构&#xff1a; 3. 各个文件内容&#xff1a; 3.1. myadd.cpp&#xff1a; #include<iostream> using namespace std; int add_xxx( int a,int b ){int result a b;cout << a << " " << …

【C语言】return 关键字

在C语言中&#xff0c;return是一个关键字&#xff0c;用于从函数中返回值或者结束函数的执行。它是函数的重要组成部分&#xff0c;负责将函数的计算结果返回给调用者&#xff0c;并可以提前终止函数的执行。 主要用途和原理&#xff1a; 返回值给调用者&#xff1a; 当函数执…

技术成神之路:设计模式(二)建造者模式

1.定义 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它允许你分步骤创建复杂对象&#xff0c;而不必直接调用构造函数。建造者模式特别适合那些包含多个组成部分并且构造过程复杂的对象。 2. 结构 建造者模式的主要组成部分包括&#…

朗新天霁eHR GetFunc_code.asmx SQL注入致RCE漏洞复现

0x01 产品简介 朗新天霁人力资源管理系统(LongShine eHR)是一款由北京朗新天霁软件技术有限公司研发的人力资源管理系统,该产品融合了国外先进的人力资源管理理念和国内大量人力资源管理实践经验,是国内功能较为全面、性价比较高的人力资源管理系统之一,系统凭借其集成化…

中国农业会计编辑部中国农业会计杂志社2024年第10期目录

人物风采 为民服务守初心 平凡岗位担使命——记云南省漾濞县畜牧兽医管理服务中心高级畜牧师徐健春 2 会计研究 管理会计在企业全面管理中的应用——以D公司为例 蒯浠语; 3-5,《中国农业会计》投稿&#xff1a;cnqikantg126.com AI时代企业会计数据集成管理策略研究…

MySQL单表千万级数据查询优化大家怎么说(评论有亮点)

题图来自APOD 上次写了一篇MySQL优化实战的文章“MySQL千万级数据从190秒优化到1秒全过程”。 这篇文章主要还是在实战MySQL优化&#xff0c;所以从造数据到查询SQL优化SQL都没有业务或者其它依赖&#xff0c;优化的技巧也不涉及软件架构就是纯SQL优化。 由于笔者经验有限和…

SQL Server和Oracle数据库的实时同步

数据同步在大数据应用中扮演着关键角色&#xff0c;它确保了数据的实时性和一致性&#xff0c;为数据分析和决策提供了重要支持。常见的数据同步方式包括ETL实时同步和实时ETL工具&#xff0c;后者可以基于日志追踪或触发器进行分类。不同的数据库系统针对实时同步也有各自的实…

数据采集技术:selenium/正则匹配/xpath/beautifulsoup爬虫实例

专栏介绍 1.专栏面向零基础或基础较差的机器学习入门的读者朋友&#xff0c;旨在利用实际代码案例和通俗化文字说明&#xff0c;使读者朋友快速上手机器学习及其相关知识体系。 2.专栏内容上包括数据采集、数据读写、数据预处理、分类\回归\聚类算法、可视化等技术。 3.需要强…

电影解说 剪辑实战带货全新蓝海市场,电影解说实战课程(16节)

课程目录 1-影视解说自媒体带货新玩法_1.mp4 2-影视解说选品及解说规范标准_1.mp4 3-电影解说的脚本模版及流程_1.mp4 4-电影解说编写文案及爆火规律_1.mp4 5-手把手教你影视素材哪里找_1.mp4 6-影视解说剪辑、配音及创收方式_1.mp4 7-电影解说剪辑的实操课程A_1.mp4 8…

关于Ubuntu系统中.config文件夹如何找到

Ubuntu中QT项目使用了setting保存配置&#xff0c;但是找不到配置文件保存了在哪里&#xff0c;找了一下&#xff1a; 因为QT里取的名字是&#xff1a; 于是下载everything搜索Nio&#xff0c;发现目录为/home/nio/.config 虽然已经下载了everything找到了&#xff0c;但是发现…

fyne常用内置颜色

常用内置颜色 在theme包里有一个关于颜色的color.go 常用颜色如下: theme.PrimaryColor() theme.WarningColor() theme.SuccessColor() theme.ErrorColor() theme.ShadowColor() theme.HyperlinkColor()最终这些会返回color.Color接口。 效果图: theme.HyperlinkColor()和t…

VTK- 面绘制体绘制

在VTK中&#xff0c;面绘制&#xff08;Surface Rendering&#xff09;和体绘制&#xff08;Volume Rendering&#xff09;是两种常见的三维数据可视化方法。面绘制和体绘制是计算机图形学中用于三维数据可视化的重要技术&#xff0c;尤其在医学成像、科学可视化和计算机辅助设…

Android广播机制

简介 某个网络的IP范围是192.168.0.XXX&#xff0c;子网 掩码是255.255.255.0&#xff0c;那么这个网络的广播地址就是192.168.0.255。广播数据包会被发送到同一 网络上的所有端口&#xff0c;这样在该网络中的每台主机都将会收到这条广播。为了便于进行系统级别的消息通知&…

游戏行业情报 | 手机玩3A终是空想?iOS版3A大作销量滑铁卢

2023年9月的苹果发布会上&#xff0c;苹果宣布iPhone15 Pro系列首发配备的A17 Pro芯片将能够支持3A游戏的游玩&#xff0c;随着该系列设备的发布&#xff0c;《生化危机 4》、《生化危机&#xff1a;村庄》、《死亡搁浅》和《刺客信条&#xff1a;幻景》等大作先后登陆iOS平台。…

Qt 使用 QZipReader 解压文件

Qt 使用 QZipReader 解压文件 文章目录 Qt 使用 QZipReader 解压文件摘要关于 QZipReader使用 QZipReader代码解释&#xff1a; 快速解 extractAll 关键字&#xff1a; Qt、 QZipReader、 extractAll、 Zip、 解压缩 摘要 每日一坑&#xff0c;坑坑难过&#xff0c;今日在…

2024年度 | 推荐PC端时间规划、项目管理软件(最新)

PingCode&#xff1a;适用于IT团队的项目/任务管理。 https://pingcode.com/ Worktile&#xff1a;团队通用的任务规划工具。 https://worktile.com/ Todoist&#xff1a;个人任务管理工具&#xff0c;支持跨平台同步。 Todoist | 管理您工作和生活的To Do List Pomodoro Ti…

Android选择题界面的设计——线性布局实操

目录 任务目标任务分析任务实施 任务目标 使用TextView、Button、CheckBox等实现一个选择题界面&#xff0c;界面如图1所示。 图1 选择题界面效果图 任务分析 上述界面可以分解为上下两部分&#xff0c;上面部分可以使用横向的线性布局来完成&#xff0c;下面部分可以使用…