C++中跟踪执行方法的一种简便日志记录方法

C++中跟踪执行方法的一种简便日志记录方法,第1张

1. 缘起

在做桌面程序时候,记录日志是一种很好的错误排查方法,特别是离线系统。
在重要的方法上,往往需要记录进入此方法和离开此方法的日志,用于执行效率、是否崩溃的判断。

2. 普通方法 2.1 方法定义

假设,对于日志的记录,存在如下方法:

// 省略部分
class Log
{
public:
    static void log(LogLevel logLevel, QString functionName, QString message);
    
private:
    Log() = delete;
    Log(const Log& other) = delete;
    Log &operator=(const Log& other) = delete;
};

#define LOG Log::log
2.2 记录一条日志

记录一条日志,调用如下方法:

LOG(LL_INFO, "VideoPrecessThread::run", "Enter function.");
2.3 在方法上的使用

例如,有一个重要的方法VideoPrecessThread::run,需要记录进入和离开此方法方法的痕迹,如下所示:

void VideoPrecessThread::run()
{
    LOG(LL_INFO, "VideoPrecessThread::run", "Enter function.");
    // 省略部分
    LOG(LL_INFO, "VideoPrecessThread::run", "Leave function.");
}
3. 问题分析 3.1 问题所在

这样可能存在如下的问题:

  1. 这个方法中存在多个返回,那么需要多处记录离开的痕迹,多、重复、容易漏记
  2. 如果带有返回值的情况,需要在真正离开方法之前就记录

对于上述的第2种情况,如下所示:

bool VideoPrecessThread::check()
{
    LOG(LL_INFO, "VideoPrecessThread::run", "Enter function.");
    // 省略部分
    LOG(LL_INFO, "VideoPrecessThread::run", "Leave function.");  // 1
    return true;	// 2
}

在上面的代码中,在“2”处才真正离开,但是在“1”就记录了离开。

3.2 可能的解决办法

观察上面的函数,有什么方法能够方便记录呢?
有一种方法就是利用对象的生命周期,如果在方法的最开始的时候创建一个对象,如果不是通过指针new出来的,那么它的生命周期将在执行完当前方法时候结束,就会进行析构,那么就可以创建一个对象,在其构造函数里面记录进入此函数的方法,在析构中记录离开的方法,那么就能满足这种要求。

4. 使用的方法

头文件FunctionTrackerLogger.h

#ifndef FUNCTIONTRACKERLOGGER_H
#define FUNCTIONTRACKERLOGGER_H

#include 
#include 

class FunctionTrackerLogger
{
public:
    FunctionTrackerLogger(QString functionName);
    ~FunctionTrackerLogger();

private:
    QString functionName;
};

#endif // FUNCTIONTRACKERLOGGER_H

源文件FunctionTrackerLogger.cpp:

#include "FunctionTrackerLogger.h"

#include "Log.h"

FunctionTrackerLogger::FunctionTrackerLogger(QString functionName)
{
    this->functionName = functionName;
    LOG(LL_INFO, functionName, "Enter funtion.");
}

FunctionTrackerLogger::~FunctionTrackerLogger()
{
    LOG(LL_INFO, functionName, "Leave funtion.");
}

调用的时候的使用:

bool VideoPrecessThread::check()
{
    FunctionTrackerLogger logger = "VideoPrecessThread::check";
    
	  if(条件1)
	  {
	  	return false; // 1
	  }
	  
	  if(条件2)
	  {
	  	return false; // 2
	  }

    return true;	// 3
}

这样无论在上述的1、2、3那处退出,都能得到如下等效的两条日志:

LOG(LL_INFO, "VideoPrecessThread::check", "Enter funtion.");
LOG(LL_INFO, "VideoPrecessThread::check", "Leave funtion.");

如果代码在这个函数执行中崩溃,那么只能得到进入函数的记录。

5. 带参数的方法的记录

对于带参数的方法的记录,不在这里累赘叙述,详见《C++中跟踪执行方法的一种简便日志记录方法(补充参数记录)》一文。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1353872.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-14
下一篇 2022-06-14

发表评论

登录后才能评论

评论列表(0条)

保存