日志系统设计与实现

在软件开发过程中,日志系统是一个重要的组成部分。它可以帮助开发者追踪程序的运行状态,记录错误信息,以及进行性能分析等。本文将介绍如何设计和实现一个灵活的日志系统,包括日志级别的设置、日志颜色的调整以及如何获取程序的创建时间等。

日志条目的信息类型

日志条目可以包含多种类型的信息,如日期、数字和字符串等。首先,将介绍可以包含在每个日志条目中的信息类型。

调用函数

总是希望知道是哪个函数调用了每个日志条目。为此,可以在WriteLogFile()函数中添加一个参数,并通过宏自动添加以下预处理器指令的第一个参数:__FUNCTION__

一般信息

通常,希望日志条目包含一些一般信息,如当前日期和时间、应用程序启动的日期和时间(可选),以及应用程序创建的日期和时间(可选)。

循环计数

并非每个应用程序都需要这个功能,但有些应用程序确实需要。如果应用程序有一个主事件循环,通常会从一些初始化开始,然后启动这个循环,直到应用程序被终止。可能想要计算这个循环发生了多少次。

以下函数可以用来设置文本和背景颜色。这个函数应该根据设置的标准被一个包装器调用,以便于在运行时查看日志。例如,区分信息日志条目和错误/警告,以及为不同类型的紧急情况设置不同的颜色。

inline void setcolor(int textcol, int backcol) { if ((textcol % 16) == (backcol % 16)) textcol++; textcol %= 16; backcol %= 16; unsigned short wAttributes = ((unsigned)backcol << 4) | (unsigned)textcol; HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hStdOut, wAttributes); }

定义日志级别

通过以下代码,定义了不同的日志级别,允许后续根据选定的“日志级别”显示日志条目。

typedef enum { minimal = 1, // 必须显示的消息 normal = 2, // 通常会显示的消息 verbose = 3 // 不一定需要显示的消息 } LoggingLevel;

然后,可以使用宏来选择所需的日志级别作为WriteLogFile()的参数。

#define LOG_VERBOSE utils::LoggingLevel::verbose #define LOG_NORMAL utils::LoggingLevel::normal #define LOG_MINIMAL utils::LoggingLevel::minimal

程序创建日期的显示

将获取程序的创建日期,但首先,定义一个“友好”的格式来显示它:

#define FRIENDLY_DATEFORMAT L"%d-%m-%Y, %H:%M:%S"

这意味着:日-月-年 时:分:秒。例如:04-04-2019 10:00:00。使用以下代码获取程序的创建日期:

CTime GetFileDateTime(LPCWSTR FileName) { FILETIME ftCreate, ftAccess, ftWrite; HANDLE hFile; CTime result = NULL; CTime FileTime; hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { return result; } // 获取文件的时间。 if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) return result; FileTime = ftWrite; CloseHandle(hFile); result = (CTime)FileTime; return result; } // GetSelfDateTime- 返回运行程序的创建日期和时间 CTime GetSelfDateTime(void) { WCHAR szExeFileName[MAX_PATH]; GetModuleFileName(NULL, szExeFileName, MAX_PATH); return GetFileDateTime(szExeFileName); }

显示处理器类型

可能还想要显示处理器类型,很可能是32位(x86)或64位(x64)。使用以下函数来实现:

bool Isx64OS() { SYSTEM_INFO systemInfo; GetNativeSystemInfo(&systemInfo); return (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64); }

使用代码

现在是时候看看整个函数以及如何调用它了。使用WriteLogFile(),如下代码片段所示。注意:使用日志记录时,_LOG预处理器指令被设置,否则不会,这种代码的组织方式确保了当_LOG没有被打开时,不会包含所有日志消息在二进制可执行文件中,因为有时不希望这些消息被发布,而只是内部使用。

int myIntVar = 999; wchar_t *myStringVar = L"Test"; #if _LOG WriteLogFile(__FUNCTION__, LOG_COLOR_WHITE, LOG_VERBOSE, L"myStringVar = %s myIntVar = %d", myStringVar, myIntVar); #endif
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485