小巧。快速。可靠。
三选二。
错误和警告日志

概述

SQLite 可以配置为在发生异常时调用一个回调函数,该函数包含错误代码和简短的错误消息。这种机制对于跟踪很少发生且在现场发生的模糊问题非常有帮助。鼓励应用程序开发人员在其产品中利用 SQLite 的错误日志记录功能,因为它非常节省 CPU 和内存,但可以极大地帮助调试。

1. 设置错误日志回调

每个进程只能有一个错误日志回调。错误日志回调是在启动时使用类似于以下内容的 C 代码注册的

sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, pData);

错误日志回调函数可能看起来像这样

void errorLogCallback(void *pArg, int iErrCode, const char *zMsg){
  fprintf(stderr, "(%d) %s\n", iErrCode, zMsg);
}

上面的示例说明了错误日志回调的签名。但是,在嵌入式应用程序中,通常不会在 stderr 上打印消息。相反,可能会将消息存储在一个预分配的循环缓冲区中,以便在调试期间需要诊断信息时可以访问它们。或者,消息可以发送到Syslog。无论如何,需要将消息存储在开发人员可以访问的地方,而不是显示给最终用户。

不要误解:从技术上讲,将错误日志消息显示给最终用户没有任何问题。这些消息不包含必须防止未经授权查看的敏感或私人信息。相反,这些消息本质上是技术性的,对于典型的最终用户来说没有用处或意义。来自错误日志的消息旨在供数据库专家使用。相应地显示它们。

2. 接口细节

sqlite3_config(SQLITE_CONFIG_LOG,...) 接口的第三个参数(上面示例中的“pData”参数)是指向任意数据的指针。SQLite 将此指针传递给错误日志回调的第一个参数。如果需要,可以使用该指针传递特定于应用程序的设置或状态信息。或者它可以只是一个空指针,回调会忽略它。

错误日志回调的第二个参数是整数扩展错误代码。错误日志的第三个参数是错误消息的文本。错误消息文本存储在调用函数中的固定长度堆栈缓冲区中,因此仅在错误日志回调函数的持续时间内有效。如果需要保留消息,则错误日志应将此消息复制到持久存储中。

错误日志回调应像信号处理程序一样对待。应用程序应保存或以其他方式处理错误,然后尽快返回。不应该直接或间接地从错误日志调用其他 SQLite API。通过错误日志回调,SQLite不是可重入的。特别是,当内存分配失败时会调用错误日志回调,因此通常不建议尝试在错误日志内部分配内存。甚至不要考虑尝试将错误消息存储在另一个 SQLite 数据库中。

如果需要,应用程序可以使用sqlite3_log(E,F,..) API 将新消息发送到日志,但不建议这样做。 sqlite3_log() 接口仅供扩展使用,不供应用程序使用。

3. 错误消息种类

可能发送到错误日志的错误消息及其确切格式可能会在不同版本之间发生变化。因此,应用程序不应依赖任何特定的错误消息文本格式或错误代码。事情不会反复无常地改变,但它们有时确实会改变。

以下是可能出现在错误日志回调中的一些消息类型。

SQLite 努力保持错误日志流量较低,并且仅在确实存在问题时才将消息发送到错误日志。应用程序可以通过故意忽略他们不关心的某些类别的错误消息来进一步剔除错误消息流量。例如,频繁更改数据库模式的应用程序可能希望忽略所有 SQLITE_SCHEMA 错误。

4. 总结

强烈建议使用错误日志回调。错误日志提供的调试信息已被证明在跟踪应用程序进入现场后发生的模糊问题方面非常有用。错误日志回调还被证明有助于捕获应用程序由于 API 返回代码检查不一致而错过的偶尔错误。鼓励开发人员在开发周期的早期实现错误日志回调,以便快速发现意外行为,并在部署过程中保持错误日志回调处于打开状态。如果错误日志从未发现问题,则不会造成任何损害。但是,未能设置适当的错误日志可能会在以后影响诊断功能。