当前位置: 首页 > article >正文

简单日志宏实现(C++)

意义:
快速定位程序运行逻辑出错的位置。

背景:
项目在运行中可能会遇到各种问题,而出问题是开发过程中不可避免的一部分。关键在于能够有效地找到,并解决问题

解决问题的方式:

  • GDB调试:

    • 适用于:程序崩溃后的定位。
    • 局限性:逐步调试过程繁琐且耗时较长。
  • 系统运行日志分析:

    • 方法:在程序中任何可能存在逻辑错误的地方输出提示信息。
    • 目的:通过日志快速定位**逻辑问题**的具体位置。
    • 优势:相比GDB调试更为高效,能更快地识别和理解问题所在。

1. 宏定义和日志级别

#define LDBG 0
#define LINF 1
#define LERR 2
#define LDEFAULT LINF
  • LDBG (Debug): 调试级别的日志,用于记录详细的调试信息。
  • LINF (Info): 信息级别的日志,用于记录一般性运行信息。
  • LERR (Error): 错误级别的日志,用于记录严重错误信息。
  • LDEFAULT: 定义了默认的日志级别,当前设置为 LINF即仅输出等于或高于 LINF 的日志信息。

通过设置不同的日志级别,可以控制日志的输出粒度。


2. 日志宏实现

#define LOG(level, format, ...) {\
 if (level >= LDEFAULT){\
 time_t t = time(NULL);\
 struct tm *lt = localtime(&t);\
 char time_tmp[32] = {0};\
 strftime(time_tmp, 31, "%m-%d %T", lt);\
 fprintf(stdout, "[%s][%s:%d] " format "\n", time_tmp, __FILE__, \
__LINE__, ##__VA_ARGS__);\
 }\
}
核心功能解析
  1. LOG(level, format, ...)

    • 这是一个可变参数的宏,用于生成带有特定级别的日志。
    • 参数:
      • level:日志级别,决定日志是否输出。
      • format:格式化字符串,与 printf 风格一致。
      • ...可变参数,与 format 匹配。
  2. 日志级别判断

    if (level >= LDEFAULT)
    
    • 只有当日志级别不低于默认级别 LDEFAULT 时,日志才会输出。
    • 例如,如果 LDEFAULTLINF,则只有 LINFLERR 级别的日志会被打印。
  3. 获取当前时间

    time_t t = time(NULL);
    struct tm *lt = localtime(&t);
    char time_tmp[32] = {0};
    strftime(time_tmp, 31, "%m-%d %T", lt);
    
    • 使用 time() 获取当前时间
      在这里插入图片描述

    • 使用 localtime() 将时间转换为本地时间。
      在这里插入图片描述

    • 使用 strftime() 将时间格式化为字符串,格式为 月-日 时:分:秒%m-%d %T)。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  1. 格式化日志输出
    fprintf(stdout, "[%s][%s:%d] " format "\n", time_tmp, __FILE__, \
    __LINE__, ##__VA_ARGS__);
    
    • 将日志输出到标准输出 stdout
    • 输出格式:
      • [时间]:如 [01-19 14:23:45]
      • [文件名:行号]:使用预定义宏 __FILE____LINE__ 获取当前文件名和行号。
      • format__VA_ARGS__:用户指定的日志内容,支持 printf 风格的格式化。
      • ❗## 处理__VA_ARGS__

3. 简化的日志宏

#define DLOG(format, ...) LOG(LDBG, format, ##__VA_ARGS__);
#define ILOG(format, ...) LOG(LINF, format, ##__VA_ARGS__);
#define ELOG(format, ...) LOG(LERR, format, ##__VA_ARGS__);
  • DLOG: 调试日志,等价于 LOG(LDBG, ...)
  • ILOG: 信息日志,等价于 LOG(LINF, ...)
  • ELOG: 错误日志,等价于 LOG(LERR, ...)

开发者可以直接使用这些宏记录不同级别的日志,就不需要手动指定日志级别啦。


4. 示例代码

#include "log_macro.h"

int main() {
    ILOG("This is an info log.");
    DLOG("This is a debug log.");
    ELOG("This is an error log: %s", "Critical failure!");

    return 0;
}

输出结果(假设 LDEFAULTLINF):

[01-19 14:23:45][main.c:4] This is an info log.
[01-19 14:23:45][main.c:6] This is an error log: Critical failure!
  • DLOG 的日志没有输出,因为 LDBG < LDEFAULT

5. 优点和意义

  1. 快速定位问题

    • 日志输出包括文件名和行号,无需手动查找代码位置。
    • 时间戳记录了日志发生的时间,便于分析问题的时间线。
  2. 简单易用

    • 宏封装了复杂的日志格式和级别控制,开发者只需调用 DLOGILOGELOG 即可。
  3. 灵活性

    • 默认日志级别可以通过修改 LDEFAULT 轻松调整。
    • 支持可变参数,适应各种格式的日志内容。

6. 改进建议

  1. 日志输出到文件

    • 当前日志输出到标准输出,实际应用中可能需要写入日志文件。可以扩展宏,增加输出目的地的选择。
  2. 线程安全

    • 多线程程序中,日志写入可能会产生竞争。可以结合互斥锁或线程安全的 I/O 函数实现线程安全。
  3. 日志级别动态配置

    • 提供运行时修改日志级别的能力,而不是通过编译时宏定义固定。

这种简单的日志系统一般就可以应对大多数小型项目的调试需求啦


http://www.kler.cn/a/510389.html

相关文章:

  • Java测试开发平台搭建(九)前端
  • Visual Studio Code + Stm32 (IAR)
  • 基于本地消息表实现分布式事务
  • 技术洞察:C++在后端开发中的前沿趋势与社会影响
  • 【MySQL】复合查询+表的内外连接
  • Nginx三种不同类型的虚拟主机(基于域名、IP 和端口)
  • Invicti-Professional-V25.1
  • MATLAB基础应用精讲-【数模应用】基于粒子群算法的风光储微电网经济运行优化调度(附MATLAB代码实现)
  • 《自动驾驶与机器人中的SLAM技术》ch8:基于预积分和图优化的紧耦合 LIO 系统
  • Qt Desiogn生成的ui文件转化为h文件
  • kubernetes简介
  • LLM - 大模型 ScallingLaws 的 CLM 和 MLM 中不同系数(PLM) 教程(2)
  • 图论DFS:黑红树
  • Python库之PyAutoGUI安装以及使用方法
  • 使用 Hadoop 实现大数据的高效存储与查询
  • 题海拾贝:力扣 反转链表
  • Source insight快捷导入工程流程 Source insight导入MDK工程文件
  • C# 委托和事件(Lambda表达式)
  • STL--list(双向链表)
  • Mousetrap:打造高效键盘快捷键体验的JavaScript库
  • PageHelper快速使用
  • 令牌主动失效机制实现——Redis登录优化
  • 基于 WEB 开发的房屋中介租赁销售系统设计与实现
  • Unity中实现伤害跳字效果(简单好抄)
  • springboot基于微信小程序的智慧乡村政务服务系统
  • 大数据治理:提升数据质量与合规性,助力企业数字化转型