763 lines
22 KiB
Markdown
763 lines
22 KiB
Markdown
# 公共组件API参考
|
||
|
||
## 目录
|
||
|
||
- [公共组件API参考](#公共组件api参考)
|
||
- [目录](#目录)
|
||
- [概述](#概述)
|
||
- [错误处理系统](#错误处理系统)
|
||
- [错误码](#错误码)
|
||
- [异常层次结构](#异常层次结构)
|
||
- [错误处理器](#错误处理器)
|
||
- [工具函数](#工具函数)
|
||
- [宏定义](#宏定义)
|
||
- [日志系统](#日志系统)
|
||
- [日志级别](#日志级别)
|
||
- [日志接口](#日志接口)
|
||
- [模块日志](#模块日志)
|
||
- [日志配置](#日志配置)
|
||
- [使用示例](#使用示例)
|
||
- [错误处理示例](#错误处理示例)
|
||
- [日志记录示例](#日志记录示例)
|
||
- [集成示例](#集成示例)
|
||
- [最佳实践](#最佳实践)
|
||
- [错误处理最佳实践](#错误处理最佳实践)
|
||
- [日志记录最佳实践](#日志记录最佳实践)
|
||
- [跨平台考虑](#跨平台考虑)
|
||
|
||
## 概述
|
||
|
||
公共组件模块提供了错误处理和日志记录等基础功能,为整个音频后端系统提供统一的异常处理和日志记录机制。这些组件设计为高性能、线程安全且跨平台,使开发者能够轻松地进行错误处理和系统状态监控。
|
||
|
||
核心特性:
|
||
|
||
- **统一的错误处理**:提供清晰的错误码、异常层次结构和错误处理工具
|
||
- **灵活的日志系统**:支持多级别、多目标(控制台/文件)的日志记录
|
||
- **模块化设计**:允许按模块进行日志和错误处理
|
||
- **高性能**:所有组件设计时考虑了性能开销,适用于实时音频处理
|
||
- **线程安全**:支持多线程环境下的并发操作
|
||
|
||
## 错误处理系统
|
||
|
||
错误处理系统提供了一套完整的错误处理机制,包括错误码、异常类和错误处理工具。
|
||
|
||
### 错误码
|
||
|
||
`ErrorCode`枚举定义了系统中所有可能的错误状态:
|
||
|
||
```cpp
|
||
enum class ErrorCode {
|
||
// 通用错误 (0-999)
|
||
SUCCESS = 0,
|
||
UNKNOWN_ERROR = 1,
|
||
INVALID_ARGUMENT = 2,
|
||
INVALID_OPERATION = 3,
|
||
NOT_IMPLEMENTED = 4,
|
||
OUT_OF_MEMORY = 5,
|
||
OPERATION_TIMED_OUT = 6,
|
||
NOT_INITIALIZED = 7,
|
||
ALREADY_INITIALIZED = 8,
|
||
|
||
// 文件和I/O错误 (1000-1999)
|
||
FILE_NOT_FOUND = 1000,
|
||
FILE_ACCESS_DENIED = 1001,
|
||
FILE_READ_ERROR = 1002,
|
||
FILE_WRITE_ERROR = 1003,
|
||
FILE_FORMAT_ERROR = 1004,
|
||
|
||
// 音频处理错误 (2000-2999)
|
||
AUDIO_FORMAT_ERROR = 2000,
|
||
AUDIO_DEVICE_ERROR = 2001,
|
||
AUDIO_BUFFER_UNDERRUN = 2002,
|
||
AUDIO_BUFFER_OVERRUN = 2003,
|
||
AUDIO_SAMPLE_RATE_MISMATCH = 2004,
|
||
AUDIO_CHANNEL_COUNT_MISMATCH = 2005,
|
||
|
||
// 插件错误 (3000-3999)
|
||
PLUGIN_LOAD_ERROR = 3000,
|
||
PLUGIN_NOT_FOUND = 3001,
|
||
PLUGIN_VERSION_MISMATCH = 3002,
|
||
PLUGIN_INITIALIZATION_ERROR = 3003,
|
||
PLUGIN_COMMUNICATION_ERROR = 3004,
|
||
PLUGIN_EXECUTION_ERROR = 3005,
|
||
PLUGIN_TIMEOUT = 3006,
|
||
|
||
// 通信错误 (4000-4999)
|
||
COMMUNICATION_ERROR = 4000,
|
||
CONNECTION_ERROR = 4001,
|
||
DISCONNECTED = 4002,
|
||
MESSAGE_FORMAT_ERROR = 4003,
|
||
PROTOCOL_ERROR = 4004,
|
||
TIMEOUT = 4005,
|
||
|
||
// 系统错误 (5000-5999)
|
||
SYSTEM_ERROR = 5000,
|
||
PERMISSION_DENIED = 5001,
|
||
NOT_ENOUGH_RESOURCES = 5002
|
||
};
|
||
```
|
||
|
||
错误码按功能域分组,便于管理和扩展。系统还提供了错误分类枚举:
|
||
|
||
```cpp
|
||
enum class ErrorCategory {
|
||
GENERAL,
|
||
FILE,
|
||
AUDIO,
|
||
PLUGIN,
|
||
COMMUNICATION,
|
||
SYSTEM
|
||
};
|
||
```
|
||
|
||
获取错误描述和分类的辅助函数:
|
||
|
||
```cpp
|
||
// 获取错误分类
|
||
ErrorCategory get_error_category(ErrorCode code);
|
||
|
||
// 获取错误码对应的描述信息
|
||
std::string get_error_description(ErrorCode code);
|
||
```
|
||
|
||
### 异常层次结构
|
||
|
||
系统定义了一个异常层次结构,以`AudioBackendException`为基类:
|
||
|
||
```cpp
|
||
// 基础异常类
|
||
class AudioBackendException : public std::exception {
|
||
public:
|
||
explicit AudioBackendException(ErrorCode code,
|
||
const std::string& message = "",
|
||
const std::string& details = "");
|
||
|
||
// 获取错误码
|
||
ErrorCode code() const noexcept;
|
||
|
||
// 获取错误消息
|
||
const std::string& message() const noexcept;
|
||
|
||
// 获取详细信息
|
||
const std::string& details() const noexcept;
|
||
|
||
// 获取完整错误消息
|
||
const char* what() const noexcept override;
|
||
|
||
// 获取错误分类
|
||
ErrorCategory category() const noexcept;
|
||
|
||
// 获取std::error_code
|
||
std::error_code error_code() const noexcept;
|
||
|
||
// 是否是某个错误码
|
||
bool is(ErrorCode code) const noexcept;
|
||
|
||
// 是否属于某个错误分类
|
||
bool is_category(ErrorCategory category) const noexcept;
|
||
};
|
||
```
|
||
|
||
基于基础异常类,系统还定义了特定领域的异常类:
|
||
|
||
```cpp
|
||
// 文件异常
|
||
class FileException : public AudioBackendException;
|
||
|
||
// 音频异常
|
||
class AudioException : public AudioBackendException;
|
||
|
||
// 插件异常
|
||
class PluginException : public AudioBackendException;
|
||
|
||
// 通信异常
|
||
class CommunicationException : public AudioBackendException;
|
||
|
||
// 系统异常
|
||
class SystemException : public AudioBackendException;
|
||
```
|
||
|
||
### 错误处理器
|
||
|
||
`ErrorHandler`类提供了集中式的错误处理机制:
|
||
|
||
```cpp
|
||
class ErrorHandler {
|
||
public:
|
||
// 错误处理回调函数类型
|
||
using ErrorCallback = std::function<void(const AudioBackendException&)>;
|
||
|
||
// 获取单例实例
|
||
static ErrorHandler& instance();
|
||
|
||
// 添加全局错误处理回调
|
||
void add_error_handler(const ErrorCallback& handler);
|
||
|
||
// 移除错误处理回调
|
||
void remove_error_handler(const ErrorCallback& handler);
|
||
|
||
// 处理错误
|
||
void handle_error(const AudioBackendException& exception);
|
||
|
||
// 处理错误(从错误码创建异常)
|
||
void handle_error(ErrorCode code,
|
||
const std::string& message = "",
|
||
const std::string& details = "");
|
||
|
||
// 处理异常捕获
|
||
void handle_exception(std::exception_ptr eptr);
|
||
|
||
// 清除所有错误处理回调
|
||
void clear_handlers();
|
||
};
|
||
```
|
||
|
||
系统还提供了RAII风格的错误处理辅助类:
|
||
|
||
```cpp
|
||
class ScopedErrorHandler {
|
||
public:
|
||
explicit ScopedErrorHandler(ErrorHandler::ErrorCallback handler);
|
||
~ScopedErrorHandler();
|
||
};
|
||
```
|
||
|
||
### 工具函数
|
||
|
||
错误处理系统提供了一系列工具函数:
|
||
|
||
```cpp
|
||
// 根据错误码创建适当的异常
|
||
std::exception_ptr create_exception(ErrorCode code,
|
||
const std::string& message = "",
|
||
const std::string& details = "");
|
||
|
||
// 根据错误码抛出异常
|
||
[[noreturn]] void throw_exception(ErrorCode code,
|
||
const std::string& message = "",
|
||
const std::string& details = "");
|
||
|
||
// 错误检查函数(条件为true时抛出异常)
|
||
void check_error(bool condition,
|
||
ErrorCode error_code,
|
||
const std::string& message = "",
|
||
const std::string& details = "");
|
||
|
||
// 将系统错误码转换为AudioBackend错误码
|
||
ErrorCode system_error_to_error_code(int system_error);
|
||
|
||
// 将std::error_code转换为AudioBackend错误码
|
||
ErrorCode std_error_to_error_code(const std::error_code& ec);
|
||
```
|
||
|
||
### 宏定义
|
||
|
||
系统提供了便捷的错误处理宏:
|
||
|
||
```cpp
|
||
// 检查条件并抛出异常
|
||
#define AUDIO_CHECK_ERROR(condition, error_code, message)
|
||
|
||
// 直接抛出异常
|
||
#define AUDIO_THROW_ERROR(error_code, message)
|
||
|
||
// 处理错误(调用ErrorHandler)
|
||
#define AUDIO_HANDLE_ERROR(error_code, message)
|
||
|
||
// try-catch简化宏
|
||
#define AUDIO_TRY_CATCH_ALL()
|
||
#define AUDIO_CATCH_ALL()
|
||
```
|
||
|
||
## 日志系统
|
||
|
||
日志系统基于spdlog库实现,提供了灵活、高性能的日志记录功能。
|
||
|
||
### 日志级别
|
||
|
||
日志系统定义了以下日志级别:
|
||
|
||
```cpp
|
||
enum class LogLevel {
|
||
TRACE, // 最详细的调试信息
|
||
DEBUG, // 详细的调试信息
|
||
INFO, // 一般信息
|
||
WARN, // 警告信息
|
||
ERR, // 错误信息
|
||
CRITICAL, // 严重错误
|
||
OFF // 关闭日志
|
||
};
|
||
```
|
||
|
||
### 日志接口
|
||
|
||
`Logger`类提供了日志系统的核心功能:
|
||
|
||
```cpp
|
||
class Logger {
|
||
public:
|
||
// 获取单例实例
|
||
static Logger& instance();
|
||
|
||
// 初始化日志系统
|
||
void initialize(const std::string& app_name = "AudioBackend",
|
||
LogLevel console_level = LogLevel::INFO,
|
||
bool file_logging = true,
|
||
const std::string& log_dir = "logs",
|
||
size_t max_file_size = 5 * 1024 * 1024,
|
||
size_t max_files = 3);
|
||
|
||
// 关闭日志系统
|
||
void shutdown();
|
||
|
||
// 设置全局日志级别
|
||
void set_level(LogLevel level);
|
||
|
||
// 设置控制台日志级别
|
||
void set_console_level(LogLevel level);
|
||
|
||
// 设置文件日志级别
|
||
void set_file_level(LogLevel level);
|
||
|
||
// 获取当前日志级别
|
||
LogLevel get_level() const;
|
||
|
||
// 获取日志器
|
||
std::shared_ptr<spdlog::logger> get_logger() const;
|
||
|
||
// 获取特定模块的日志器
|
||
std::shared_ptr<spdlog::logger> get_module_logger(const std::string& module_name);
|
||
|
||
// 刷新日志缓冲区
|
||
void flush();
|
||
|
||
// 便捷的日志记录方法
|
||
template<typename... Args>
|
||
void trace(std::string_view fmt, const Args&... args);
|
||
|
||
template<typename... Args>
|
||
void debug(std::string_view fmt, const Args&... args);
|
||
|
||
template<typename... Args>
|
||
void info(std::string_view fmt, const Args&... args);
|
||
|
||
template<typename... Args>
|
||
void warn(std::string_view fmt, const Args&... args);
|
||
|
||
template<typename... Args>
|
||
void err(std::string_view fmt, const Args&... args);
|
||
|
||
template<typename... Args>
|
||
void critical(std::string_view fmt, const Args&... args);
|
||
};
|
||
```
|
||
|
||
系统还提供了全局日志函数,无需直接访问Logger实例:
|
||
|
||
```cpp
|
||
template<typename... Args>
|
||
inline void log_trace(std::string_view fmt, const Args&... args);
|
||
|
||
template<typename... Args>
|
||
inline void log_debug(std::string_view fmt, const Args&... args);
|
||
|
||
template<typename... Args>
|
||
inline void log_info(std::string_view fmt, const Args&... args);
|
||
|
||
template<typename... Args>
|
||
inline void log_warn(std::string_view fmt, const Args&... args);
|
||
|
||
template<typename... Args>
|
||
inline void log_err(std::string_view fmt, const Args&... args);
|
||
|
||
template<typename... Args>
|
||
inline void log_critical(std::string_view fmt, const Args&... args);
|
||
```
|
||
|
||
### 模块日志
|
||
|
||
系统支持按模块进行日志记录,提供了便捷的模块日志宏:
|
||
|
||
```cpp
|
||
// 创建模块日志器
|
||
#define AUDIO_MODULE_LOGGER(module_name)
|
||
|
||
// 模块级别日志记录宏
|
||
#define AUDIO_LOG_TRACE(...)
|
||
#define AUDIO_LOG_DEBUG(...)
|
||
#define AUDIO_LOG_INFO(...)
|
||
#define AUDIO_LOG_WARN(...)
|
||
#define AUDIO_LOG_ERR(...)
|
||
#define AUDIO_LOG_CRITICAL(...)
|
||
```
|
||
|
||
### 日志配置
|
||
|
||
日志系统支持以下配置选项:
|
||
|
||
- **应用名称**:日志中显示的应用名称
|
||
- **控制台日志级别**:显示在控制台的最低日志级别
|
||
- **文件日志**:是否启用文件日志
|
||
- **日志目录**:日志文件的存储目录
|
||
- **最大文件大小**:单个日志文件的最大大小
|
||
- **最大文件数**:轮转日志的最大文件数量
|
||
|
||
## 使用示例
|
||
|
||
### 错误处理示例
|
||
|
||
**基本错误检查和处理:**
|
||
|
||
```cpp
|
||
#include "common/error.h"
|
||
#include <iostream>
|
||
|
||
using namespace audio_backend::common;
|
||
|
||
void example_error_handling() {
|
||
// 使用错误检查宏
|
||
try {
|
||
bool condition = false; // 假设这是一个失败条件
|
||
AUDIO_CHECK_ERROR(condition, ErrorCode::INVALID_OPERATION,
|
||
"操作无法执行,参数无效");
|
||
} catch (const AudioBackendException& e) {
|
||
std::cout << "捕获异常: " << e.what() << std::endl;
|
||
std::cout << "错误码: " << static_cast<int>(e.code()) << std::endl;
|
||
std::cout << "错误类别: " << static_cast<int>(e.category()) << std::endl;
|
||
}
|
||
|
||
// 直接抛出异常
|
||
try {
|
||
AUDIO_THROW_ERROR(ErrorCode::FILE_NOT_FOUND, "找不到配置文件");
|
||
} catch (const FileException& e) {
|
||
std::cout << "捕获文件异常: " << e.what() << std::endl;
|
||
} catch (const AudioBackendException& e) {
|
||
std::cout << "这不会被执行,因为FileException已经捕获" << std::endl;
|
||
}
|
||
|
||
// 使用错误处理器
|
||
ErrorHandler::instance().add_error_handler([](const AudioBackendException& e) {
|
||
std::cout << "错误处理器: " << e.what() << std::endl;
|
||
});
|
||
|
||
// 当触发错误时,会调用错误处理器
|
||
AUDIO_HANDLE_ERROR(ErrorCode::AUDIO_DEVICE_ERROR, "音频设备初始化失败");
|
||
}
|
||
```
|
||
|
||
**使用作用域错误处理器:**
|
||
|
||
```cpp
|
||
void example_scoped_error_handler() {
|
||
// 创建一个局部作用域的错误处理器
|
||
{
|
||
ScopedErrorHandler handler([](const AudioBackendException& e) {
|
||
std::cout << "作用域错误处理器: " << e.what() << std::endl;
|
||
});
|
||
|
||
// 在这个作用域内,所有错误都会被处理器捕获
|
||
AUDIO_HANDLE_ERROR(ErrorCode::COMMUNICATION_ERROR, "连接超时");
|
||
|
||
} // 离开作用域,错误处理器自动移除
|
||
|
||
// 此处的错误不会被上面的处理器捕获
|
||
AUDIO_HANDLE_ERROR(ErrorCode::PLUGIN_LOAD_ERROR, "插件加载失败");
|
||
}
|
||
```
|
||
|
||
**全局错误处理:**
|
||
|
||
```cpp
|
||
// 全局错误处理函数
|
||
void global_error_handler(const AudioBackendException& e) {
|
||
std::cerr << "全局错误处理: " << e.what() << std::endl;
|
||
|
||
// 可以根据错误类别执行不同操作
|
||
switch (e.category()) {
|
||
case ErrorCategory::FILE:
|
||
// 处理文件错误...
|
||
break;
|
||
case ErrorCategory::AUDIO:
|
||
// 处理音频错误...
|
||
break;
|
||
// 其他错误类别...
|
||
}
|
||
}
|
||
|
||
int main() {
|
||
// 设置全局错误处理器
|
||
ErrorHandler::instance().add_error_handler(global_error_handler);
|
||
|
||
// 现在所有通过ErrorHandler处理的错误都会被全局处理器捕获
|
||
|
||
try {
|
||
// 应用代码...
|
||
} catch (...) {
|
||
// 捕获所有未处理的异常
|
||
ErrorHandler::instance().handle_exception(std::current_exception());
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
### 日志记录示例
|
||
|
||
**基本日志记录:**
|
||
|
||
```cpp
|
||
#include "common/logger.h"
|
||
|
||
using namespace audio_backend::common;
|
||
|
||
void example_logging() {
|
||
// 初始化日志系统
|
||
Logger::instance().initialize("MyAudioApp", LogLevel::DEBUG);
|
||
|
||
// 使用全局日志函数
|
||
log_info("应用启动");
|
||
log_debug("调试信息: {}", "测试消息");
|
||
|
||
// 带参数的日志
|
||
int param1 = 42;
|
||
std::string param2 = "测试";
|
||
log_info("参数值: {} 和 {}", param1, param2);
|
||
|
||
// 错误日志
|
||
log_err("发生错误: {}", "找不到文件");
|
||
|
||
// 直接使用Logger实例
|
||
Logger::instance().critical("严重错误: 系统无法继续运行");
|
||
|
||
// 刷新日志缓冲区(确保写入磁盘)
|
||
Logger::instance().flush();
|
||
}
|
||
```
|
||
|
||
**模块日志:**
|
||
|
||
```cpp
|
||
#include "common/logger.h"
|
||
|
||
using namespace audio_backend::common;
|
||
|
||
// 定义模块日志器
|
||
AUDIO_MODULE_LOGGER("AudioEngine");
|
||
|
||
class AudioEngine {
|
||
public:
|
||
void initialize() {
|
||
AUDIO_LOG_INFO("音频引擎初始化中...");
|
||
|
||
// 一些初始化代码...
|
||
|
||
if (true /* 初始化成功 */) {
|
||
AUDIO_LOG_INFO("音频引擎初始化成功");
|
||
} else {
|
||
AUDIO_LOG_ERR("音频引擎初始化失败");
|
||
}
|
||
}
|
||
|
||
void process() {
|
||
AUDIO_LOG_TRACE("处理音频数据...");
|
||
|
||
// 一些处理代码...
|
||
|
||
if (false /* 假设发生了问题 */) {
|
||
AUDIO_LOG_WARN("处理过程中发生警告");
|
||
}
|
||
|
||
AUDIO_LOG_DEBUG("完成音频处理,输出样本数: {}", 1024);
|
||
}
|
||
};
|
||
```
|
||
|
||
**日志配置:**
|
||
|
||
```cpp
|
||
void configure_logging() {
|
||
// 完整配置
|
||
Logger::instance().initialize(
|
||
"MyAudioApp", // 应用名称
|
||
LogLevel::INFO, // 控制台日志级别
|
||
true, // 启用文件日志
|
||
"logs", // 日志目录
|
||
5 * 1024 * 1024, // 最大文件大小(5MB)
|
||
3 // 最大文件数
|
||
);
|
||
|
||
// 动态调整日志级别
|
||
Logger::instance().set_level(LogLevel::DEBUG); // 全局级别
|
||
Logger::instance().set_console_level(LogLevel::INFO); // 控制台级别
|
||
Logger::instance().set_file_level(LogLevel::TRACE); // 文件级别
|
||
|
||
// 为特定模块创建日志器
|
||
auto engine_logger = Logger::instance().get_module_logger("Engine");
|
||
auto plugin_logger = Logger::instance().get_module_logger("Plugin");
|
||
|
||
// 使用模块日志器
|
||
engine_logger->info("引擎模块信息");
|
||
plugin_logger->debug("插件模块调试信息");
|
||
}
|
||
```
|
||
|
||
### 集成示例
|
||
|
||
以下示例展示了如何将错误处理和日志系统集成在一起:
|
||
|
||
```cpp
|
||
#include "common/error.h"
|
||
#include "common/logger.h"
|
||
#include <iostream>
|
||
#include <stdexcept>
|
||
|
||
using namespace audio_backend::common;
|
||
|
||
// 自定义错误处理器,将错误记录到日志
|
||
void log_error_handler(const AudioBackendException& e) {
|
||
// 根据错误严重性选择合适的日志级别
|
||
switch (e.category()) {
|
||
case ErrorCategory::SYSTEM:
|
||
case ErrorCategory::PLUGIN:
|
||
log_critical("严重错误: {}", e.what());
|
||
break;
|
||
|
||
case ErrorCategory::AUDIO:
|
||
case ErrorCategory::COMMUNICATION:
|
||
log_err("错误: {}", e.what());
|
||
break;
|
||
|
||
case ErrorCategory::FILE:
|
||
case ErrorCategory::GENERAL:
|
||
default:
|
||
log_warn("警告: {}", e.what());
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 示例函数,模拟可能出错的操作
|
||
void perform_risky_operation() {
|
||
// 假设条件检查失败
|
||
bool success = false;
|
||
|
||
if (!success) {
|
||
// 记录错误并抛出异常
|
||
log_debug("操作失败,即将抛出异常");
|
||
AUDIO_THROW_ERROR(ErrorCode::OPERATION_TIMED_OUT, "操作超时");
|
||
}
|
||
}
|
||
|
||
// 完整集成示例
|
||
int main() {
|
||
try {
|
||
// 初始化日志系统
|
||
Logger::instance().initialize("AudioApp", LogLevel::DEBUG);
|
||
log_info("应用程序启动");
|
||
|
||
// 设置将错误记录到日志的处理器
|
||
ErrorHandler::instance().add_error_handler(log_error_handler);
|
||
log_debug("已注册错误处理器");
|
||
|
||
try {
|
||
// 尝试执行风险操作
|
||
log_info("开始执行操作...");
|
||
perform_risky_operation();
|
||
} catch (const AudioBackendException& e) {
|
||
// 本地处理异常,但不退出
|
||
log_debug("捕获到异常: {}", e.what());
|
||
|
||
// 也可以重新抛出
|
||
throw;
|
||
}
|
||
|
||
log_info("应用程序正常退出");
|
||
} catch (const std::exception& e) {
|
||
// 捕获所有未处理的异常
|
||
log_critical("未处理的异常: {}", e.what());
|
||
return 1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
## 最佳实践
|
||
|
||
### 错误处理最佳实践
|
||
|
||
1. **选择适当的错误处理方式**:
|
||
- 使用错误码返回值处理预期的错误
|
||
- 使用异常处理非预期的错误和严重故障
|
||
- 在性能关键路径上避免使用异常
|
||
|
||
2. **合理分类错误**:
|
||
- 按照错误的性质和严重程度分类
|
||
- 为不同类型的错误提供明确的上下文信息
|
||
|
||
3. **提供详细的错误信息**:
|
||
- 描述发生了什么(错误内容)
|
||
- 解释为什么会发生(错误原因)
|
||
- 建议如何解决(修复方法)
|
||
|
||
4. **集中处理错误**:
|
||
- 使用全局错误处理器统一处理错误
|
||
- 将错误处理与业务逻辑分离
|
||
|
||
5. **实时系统的错误处理**:
|
||
- 避免在音频回调线程中抛出异常
|
||
- 使用错误标志和延迟处理
|
||
- 预先分配错误处理资源,避免动态内存分配
|
||
|
||
### 日志记录最佳实践
|
||
|
||
1. **选择适当的日志级别**:
|
||
- TRACE: 最详细的调试信息,通常仅在开发时启用
|
||
- DEBUG: 详细的调试信息,有助于问题诊断
|
||
- INFO: 正常操作信息,记录系统状态和重要事件
|
||
- WARN: 警告信息,表明可能的问题,但不会导致系统失败
|
||
- ERR: 错误信息,表明功能无法正常工作
|
||
- CRITICAL: 严重错误,系统无法继续运行
|
||
|
||
2. **结构化日志信息**:
|
||
- 使用一致的格式记录日志
|
||
- 包含时间戳、日志级别、模块名称、线程ID等元数据
|
||
- 使用参数化日志而不是字符串拼接
|
||
|
||
3. **避免过多日志**:
|
||
- 避免在高频率循环中记录日志
|
||
- 使用采样或节流技术减少重复日志
|
||
- 注意日志对性能的影响
|
||
|
||
4. **按模块记录日志**:
|
||
- 每个模块使用专门的日志器
|
||
- 模块名称应反映代码结构
|
||
|
||
5. **实时系统的日志记录**:
|
||
- 使用异步日志记录,避免阻塞音频线程
|
||
- 考虑使用环形缓冲区进行临时日志存储
|
||
- 定期刷新日志,而不是每条日志都刷新
|
||
|
||
## 跨平台考虑
|
||
|
||
公共组件模块设计为跨平台工作,但在不同平台上仍有一些注意事项:
|
||
|
||
1. **文件路径处理**:
|
||
- Windows使用反斜杠(`\`)作为路径分隔符
|
||
- Unix/Linux/macOS使用正斜杠(`/`)作为路径分隔符
|
||
- 使用平台无关的路径处理函数
|
||
|
||
2. **文件权限和访问**:
|
||
- 不同平台的文件权限模型存在差异
|
||
- 日志文件创建可能受系统权限限制
|
||
|
||
3. **系统错误转换**:
|
||
- 不同平台的系统错误码不同
|
||
- 使用`system_error_to_error_code()`函数进行统一转换
|
||
|
||
4. **线程安全性**:
|
||
- 所有公共组件都设计为线程安全
|
||
- 不同平台的线程模型存在差异,但API保持一致
|
||
|
||
5. **性能考虑**:
|
||
- 不同平台上日志和错误处理的性能特性可能有所不同
|
||
- 高性能应用应当在各目标平台上进行性能测试 |