MFC 分段记录时间log类

发布于:2024-11-29 ⋅ 阅读:(26) ⋅ 点赞:(0)

在开发大型自动化系统或者多线程应用时,日志记录和时间追踪通常是系统调试和性能优化的关键部分。CAuxiliary 类是一个封装了文件日志记录和高精度计时功能的实用工具类,旨在为开发人员提供一种简便的方式,来实现系统运行的日志记录和时间性能分析。本文将详细介绍如何使用 CAuxiliary 类来记录日志和进行高精度的时间测量。

头文件

#pragma once
#include <chrono>     // std::chrono

class CAuxiliary
{
public:
	CAuxiliary() : mIsRecord(false) {}
	~CAuxiliary() { CloseFile(); }

	// 设置是否记录日志
	bool CreateAndOpenFile(CString fileName, bool IsRecord);
	void CloseFile();
	void AppendContent(CString content);

	// 插入开始时间,当bFirstBegin为true时表示首次开始
	void StartTime(bool bFirstBegin = false);

	// 插入结束时间,当bAllEnd为true时表示全部结束,这是将会记录总时间
	void EndTime(CString content, bool bAllEnd = false);

private:
	CStdioFile m_sf;
	bool mIsRecord;

	// 用于高精度计时
	std::chrono::high_resolution_clock::time_point m_start;
	std::chrono::high_resolution_clock::time_point m_firstBegin;
	std::chrono::high_resolution_clock::time_point m_end;
	std::chrono::high_resolution_clock::time_point m_mediu;
};

源文件

#include "stdafx.h"  // 适用于 MFC 项目,包含标准的 MFC 头文件
#include <iostream>
#include <chrono>     // std::chrono
#include <fstream>
#include"CAuxiliary.h"
using namespace std;


bool CAuxiliary::CreateAndOpenFile(CString fileName, bool IsRecord)
{
	mIsRecord = IsRecord;
	if (!mIsRecord) { return true; }

	// 如果文件已经打开,先关闭它
	if (m_sf.m_hFile != CFile::hFileNull) {
		CloseFile();
	}

	// 尝试打开文件
	if (m_sf.Open(fileName, CFile::modeCreate | CFile::modeWrite)) {
		return true;
	}

	return false;
}

void CAuxiliary::CloseFile()
{
	if (!mIsRecord) { return; }
	if (m_sf.m_hFile != CFile::hFileNull) {
		m_sf.Close();
	}
}

void CAuxiliary::AppendContent(CString content)
{
	if (!mIsRecord) { return; }
	if (m_sf.m_hFile == CFile::hFileNull) { return; }

	// 计算当前时间差(以毫秒为单位)
	auto now = std::chrono::high_resolution_clock::now();
	std::chrono::duration<int64_t, std::milli> duration = std::chrono::duration_cast<std::chrono::duration<int64_t, std::milli>>(now - m_mediu);
	m_mediu = now;

	// 获取当前时间(时:分:秒:毫秒)
	SYSTEMTIME st;
	GetLocalTime(&st);  // 获取本地时间

						// 格式化时间戳

	int ms = static_cast<int>(duration.count());  // 转换为毫秒
	CString timeStamp;
	timeStamp.Format(_T("%02d:%02d:%02d:%03d\t%dms\t%s\n"),
		st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, ms, content);

	m_sf.SeekToEnd();
	m_sf.WriteString(timeStamp);
}


void CAuxiliary::StartTime(bool bFirstBegin)
{
	if (!mIsRecord) { return; }

	m_start = std::chrono::high_resolution_clock::now();
	m_mediu = m_start;

	if (bFirstBegin) {
		m_firstBegin = m_start;
	}
}

void CAuxiliary::EndTime(CString content, bool bAllEnd)
{
	if (!mIsRecord) { return; }
	if (m_sf.m_hFile == CFile::hFileNull) { return; }

	m_end = std::chrono::high_resolution_clock::now();

	// 计算时间差(以毫秒为单位)
	std::chrono::duration<int64_t, std::milli> duration = bAllEnd ? std::chrono::duration_cast<std::chrono::duration<int64_t, std::milli>>(m_end - m_firstBegin)
		: std::chrono::duration_cast<std::chrono::duration<int64_t, std::milli>>(m_end - m_start);

	int ms = static_cast<int>(duration.count());  // 转换为毫秒

	CString result;
	result.Format(_T("%s:\t%dms\n"), content, ms);
	m_sf.SeekToEnd();
	m_sf.WriteString(result);
}

类的设计与功能

CAuxiliary 类设计上非常简洁,主要实现了以下功能:

  1. 日志记录: 该类可以创建一个日志文件,并在文件中附加内容。
  2. 高精度计时: 使用 std::chrono 提供的高精度计时器来记录时间,适合记录程序的执行时间。
  3. 开始和结束时间记录: 通过设置开始时间和结束时间,可以计算程序执行的时长,支持记录部分执行时间和总体执行时间。

类的成员函数解析

1. CreateAndOpenFile

bool CAuxiliary::CreateAndOpenFile(CString fileName, bool IsRecord)

此函数用于创建并打开日志文件。如果 IsRecordtrue,它将打开指定路径的日志文件。如果文件已存在,则会先关闭再重新打开文件。否则,如果 IsRecordfalse,该函数将直接返回 true,而不执行文件操作。

使用示例:

CAuxiliary aux;
aux.CreateAndOpenFile(_T("log.txt"), true);
2. CloseFile

void CAuxiliary::CloseFile()

该函数用于关闭打开的日志文件。当不再需要记录日志时,可以调用此函数释放资源。文件会在不再记录日志时被关闭。

使用示例:

aux.CloseFile();
3. AppendContent

void CAuxiliary::AppendContent(CString content)

此函数用于向日志文件中追加内容。它会在内容前加上当前时间戳(包括小时、分钟、秒和毫秒)以及从上次调用 AppendContent 以来的时间差(以毫秒为单位)。如果没有开启记录日志功能,函数不会执行任何操作。

使用示例:

aux.AppendContent(_T("Processing step 1"));
4. StartTime

void CAuxiliary::StartTime(bool bFirstBegin)

此函数用于记录操作的开始时间。如果 bFirstBegintrue,则会记录首次开始时间。此时间点将作为后续计算时间差的基准。

使用示例:

aux.StartTime(true);
5. EndTime

void CAuxiliary::EndTime(CString content, bool bAllEnd)

此函数用于记录操作的结束时间并计算与开始时间的差值。它支持两种模式:

  • 部分结束模式(默认):计算从 StartTimeEndTime 的时间差。
  • 全部结束模式:计算从首次开始时间(即 StartTime(true))到当前结束时间的时间差。这个功能对于记录整个任务的总耗时非常有用。

使用示例:

aux.EndTime(_T("Processing step 1 finished"));

 

示例代码

下面是一个完整的示例,展示了如何使用 CAuxiliary 类来记录日志并进行时间测量:

#include "CAuxiliary.h"
#include <thread>

	int main() {
		CAuxiliary aux;

		// 创建并打开日志文件
		if (aux.CreateAndOpenFile(_T("process_log.txt"), true)) {
			// 开始时间记录
			aux.StartTime(true);
			std::this_thread::sleep_for(std::chrono::seconds(1));  // 模拟延迟
		    //阶段一
			aux.StartTime();
			aux.AppendContent(_T("Start processing step 1"));// 模拟处理步骤
			std::this_thread::sleep_for(std::chrono::seconds(1));  // 模拟延迟
			aux.EndTime(_T("Processing step 1 finished"));	// 阶段一结束时间记录
			//阶段二
			aux.StartTime();
			aux.AppendContent(_T("Start processing step 2"));	// 模拟处理步骤
			std::this_thread::sleep_for(std::chrono::seconds(1));  // 模拟延迟
			aux.EndTime(_T("Processing step 2 finished"));// 阶段二结束时间记录
		
			aux.EndTime(_T("Process finished"),true);//总的时间
			aux.CloseFile();	// 关闭文件
		}

		return 0;
	}