c - C 中错误记录/通知库的设计注意事项

标签 c error-handling

我现在正在处理几个程序,并且对我调试程序和记录错误的一些随意方式感到沮丧。因此,我决定花几天时间编写一个错误库,我可以在我的所有程序中使用它。我在 Windows 中进行大部分开发,广泛使用 Windows API,但这里的关键是灵 active :理想情况下,这个库需要保持灵 active ,在 Windows 和类 Unix 环境的控制台应用程序和 GUI 应用程序中提供程序员通知选项.

我最初的想法是使用一个库,该库使用基于当前环境的 Windows 和 Unix header 的预处理器条件包含。例如,在 win32 应用程序中,控制台错误消息通知(虽然可能)不是必需的;相反,一个简单的

MessageBoxA/W(hWndParent, TEXT("Some error message that makes sense in context"), TEXT("Application Name"), MB_ICONERROR | MB_OK)

最有意义。另一方面,在 Linux 上事情要复杂一些:

GtkWindow *w;
w = gtk_message_dialog_new(pOwner, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, TEXT("Some error message");
gtk_window_set_title(w, TEXT("Application Name"));

在任一操作中,包含有关错误(函数、文件、行等)的更多信息的简单文件日志记录对于查明源头和跟踪流程也很有用。

此外,日志记录应该是可能的:即使调用需要错误日志记录/通知的函数,如果激活了该级别的日志记录,也应该可以显示程序中函数调用的顺序。

因此,我最初的考虑是拥有一个包含所有这些功能的库,并通过预处理器条件将开销降到最低。我认为将其分解为几个结构最有意义:

  • “主”结构,传递给主程序中需要日志记录的每个函数,并包含
    • 包含需要文件记录的状态代码的位掩码(例如,NOERROR | WARNING | CRITICALERROR 或 CRITICALERROR | CRASH)
    • 指向“输出”结构的指针
    • “错误信息”节点的链表
  • “输出”结构,处理打印到文件、显示消息框和打印到控制台
  • “错误信息”结构,其中包含有关错误的信息(函数、文件、行、消息、类型等)

这只是我对这个库的初步想法。你们中有人能想到我应该包含的更多信息吗?对我来说,另一个主要问题是错误添加的原子性:很可能是另一个线程创建错误而不是记录错误的线程,所以我需要确保创建和添加错误节点实际上是一个原子操作。因此,互斥锁可能是我进行同步的方式。

感谢您的帮助!

最佳答案

在不是CRITICALERROR的情况下| CRASH,应用程序应该在日志记录调用后继续,最好将每个日志结构排队(线程安全的生产者 - 消费者队列)到执行请求的操作的日志记录线程。日志记录线程通常会在处理完结构后释放它们。一些优点:

1) 对每个日志记录请求采取的操作减少为分配结构、加载它并将其推送到队列中。如果磁盘暂时繁忙,或者因为它在网络上而具有高延迟,或者实际上变得不可用,则调用线程将继续几乎正常运行。这样一来,仅因为日志记录已打开而失败的应用程序集就会减少。可以指示遇到一些您无法重现的间歇性问题的用户打开日志记录器,日志记录几乎不可能影响正常操作,或者更糟的是,引入延迟来掩盖错误。

2) 出于与 (1) 相同的原因,即使在运行时添加/更改记录器功能也容易得多。例如,也许你想限制日志文件的大小或每天生成一个新的日期/时间戳日志文件。在关闭旧文件并打开新文件时,“正常”调用会在调用线程中引入长时间延迟。如果日志记录排队关闭,您得到的只是排队日志结构数量的临时增加。

3) 控制日志记录更容易。在 GUI 应用程序中,记录器可以有自己的表单,可以在其中修改日志记录选项。您可以有一个“立即新建日志文件”按钮,单击该按钮时,会将“LOGCONTROL”结构与所有其他日志消息一起排队到日志线程。当线程获取它时,它会打开一个新的日志文件。

4) 转发日志消息相当容易。也许您想查看记录的消息,以及将它们写入磁盘 - 排队一个“LOGCONTROL”结构,该结构指示线程保存在该结构中传递的函数 ptr,并在将它们写入之后使用后续的日志消息调用此函数磁盘。传递的函数可以将消息排队到您的 GUI,以便在“终端”类型的窗口中显示(Windows、Qt 等上的 PostMessage 具有类似的功能以允许将数据传递到 GUI)。当然,在 ***x 上,您可以打开一个控制台窗口并“tail-f”日志文件,但这对 GUI 用户来说并不是特别优雅,对用户来说更难管理,而且无论如何都不是标准的在 Windows 上,(有多少用户知道如何从控制台窗口复制粘贴并通过电子邮件向您发送错误消息?)。

另一种可能性是,可能会指示日志记录线程将日志文本流式传输到远程服务器 - 另一个“LOGCONTROL”结构可能会将主机名/端口传递给记录器线程。由于排队的通信,打开与服务器的网络连接的临时延迟无关紧要。

5) “懒惰的写作”和其他类似的性能增强变得更容易,但是:

缺点:

1)主要是当日志调用返回请求者时,日志操作很可能还没有发生。对于 CRITICALERROR |,这是一个非常坏的消息。 CRASH,并且在某些情况下可能是 Not Acceptable ,即使是“普通”记录进度消息等。在这些情况下应该有一个绕过的选项,并且直接磁盘写入/刷新 - fOpen/CreateFile 一个单独的“Direct.log”,附加、写入、刷新、关闭。缓慢 - 但安全,以防应用程序在日志调用返回后爆炸。

2) 更复杂,因此需要更多的开发、更多的条件、更大的 API 接口(interface)。

Rgds, 马丁

关于c - C 中错误记录/通知库的设计注意事项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6222042/

相关文章:

c - C 中的内联 ASM,使用 "-masm=intel": "undefined reference" 使用 MinGW/GCC 编译

c - 权限被拒绝 Hello world Yocto/Openembedded

c++ - 将 int 值分配给地址

php - 如何处理解析和 fatal error ?

sql - oracle中的错误/异常处理

php - android 使用 json 连接 php/mysql 选择查询不起作用

c - 在 C 上动态声明的矩阵的大小

c - 如何使用TMS3705 RFID应答器基站IC

error-handling - 仅第一个MVC ErrorHandler属性应运行

javascript - 为什么在异步函数中捕获后仍然抛出异常?