本文档详细介绍TUTK P2P SDK的日志配置与调试方法,包括SDK库版本区分、日志参数配置、自定义回调输出、常见问题排查及问题与日志模块对应关系,帮助开发者快速定位设备掉线、连接失败、数据传输异常等问题。
一、概述
SDK 提供正式版本和调试版本两类库文件,调试版本(库名带'T')支持日志抓取功能,默认写入设备本地存储。各模块均提供独立的日志配置接口,可灵活设置日志路径、级别、文件大小限制等参数,用于排查设备掉线、连接失败、数据传输异常等问题。
核心说明:
- 1. 仅调试版本(带'T'库)支持日志输出,正式版本无日志功能;
- 2. 日志配置需在模块初始化前调用,确保生效;
- 3. 不同模块需调用对应日志接口,用到哪些模块则配置哪些;
- 4. 支持日志文件输出和自定义回调输出两种方式。
二、SDK库版本说明
SDK 库文件分为正式版本和调试版本,通过库名是否包含后缀 'T' 区分:
| 版本类型 | 库名示例 | 功能说明 | 适用场景 |
|---|---|---|---|
| 正式版本 | libIOTCAPIs.so、libAVAPIs.a | 无日志输出,体积更小、性能更优 | 生产环境部署 |
| 调试版本 | libIOTCAPIsT.so、libAVAPIsT.a | 支持日志输出,可配置日志参数 | 开发调试、问题排查 |
三、日志配置使用
日志配置需在对应模块初始化前调用,核心通过 LogAttr 结构体设置参数,各模块提供统一命名规范的日志接口:{ModuleName}_Set_Log_Attr。
(一)核心参数结构体(LogAttr)
| 字段名 | 类型 | 说明 | 取值示例 |
|---|---|---|---|
| path | const char* | 日志文件路径(含文件名),NULL 表示关闭日志 | "./log_iotc.txt" |
| log_level | logLevel_t | 日志级别(由细到粗) | LEVEL_VERBOSE/LEVEL_DEBUG/LEVEL_INFO/LEVEL_WARNING/LEVEL_ERROR/LEVEL_SILENCE |
| file_max_size | uint32_t | 单个日志文件最大大小(字节),0 表示无限制 | 1024*1024(1MB) |
| file_max_count | uint32_t | 日志文件最大个数,0 表示无限制(循环覆盖) | 5(最多保留5个日志文件) |
(二)IOTCAPIs 模块配置示例(核心模块)
// 1. 定义日志属性结构体并初始化
LogAttr logAttr;
memset(&logAttr, 0, sizeof(logAttr));
// 2. 配置日志参数
logAttr.path = "./log_iotc.txt"; // 日志文件路径(含文件名),NULL 关闭日志
logAttr.log_level = LEVEL_VERBOSE; // 日志级别:最详细(可按需调整)
logAttr.file_max_size = 0; // 单个文件无大小限制(0=无限制)
logAttr.file_max_count = 0; // 文件个数无限制(0=无限制)
// 3. 调用 IOTCAPIs 日志配置接口(模块初始化前调用)
IOTC_Set_Log_Attr(logAttr);
(三)其他模块日志配置示例
其他模块日志配置方式与 IOTCAPIs 一致,需根据使用的模块调用对应接口,建议同时开启依赖模块的日志(如下方示例):
LogAttr logAttr;
memset(&logAttr, 0, sizeof(logAttr));
logAttr.log_level = LEVEL_VERBOSE; // 日志级别(统一配置为最详细)
logAttr.file_max_size = 0; // 无大小限制
logAttr.file_max_count = 0; // 无个数限制
// 1. Global 模块日志(基础模块,建议必开)
logAttr.path = "./log_global.txt";
TUTK_Set_Log_Attr(logAttr);
// 2. RDTAPIs 模块日志(使用 RDT 相关功能时配置,需同时开 IOTC/Global)
logAttr.path = "./log_rdt.txt";
RDT_Set_Log_Attr(logAttr);
// 3. AVAPIs 模块日志(使用 AV 通道功能时配置,需同时开 IOTC/Global)
logAttr.path = "./log_av.txt";
AV_Set_Log_Attr(logAttr);
// 4. P2PTunnelAPIs 模块日志(使用 P2P 隧道功能时配置,需同时开 IOTC/RDT/Global)
logAttr.path = "./log_tunnel.txt";
P2PTunnel_Set_Log_Attr(logAttr);
// 5. Nebula 模块日志(使用 Nebula 相关功能时配置)
logAttr.path = "./log_nebula.txt";
Nebula_Set_Log_Attr(logAttr);
特别注意
iOS 平台所有库已封装为一个整体,必须通过上述对应模块的 Set_Log_Attr 接口明确设置日志路径,否则无法输出日志。
四、日志回调(自定义输出)
除日志文件输出外,SDK 支持通过回调函数自定义日志输出方式(如打印到控制台、上传至服务器等),核心通过 TUTK_Set_Log_Callback 注册回调。
(一)配置步骤
1. 设置日志级别(回调生效需先配置级别)
LogAttr logAttr;
memset(&logAttr, 0, sizeof(logAttr));
logAttr.log_level = LEVEL_VERBOSE; // 回调仅输出配置级别及以上的日志
// 为需要的模块设置日志级别(示例:Global/IOTC/AV 模块)
TUTK_Set_Log_Attr(logAttr);
IOTC_Set_Log_Attr(logAttr);
AV_Set_Log_Attr(logAttr);
2. 回调函数定义与注册
/*************** 回调函数原型定义 ***************/
// typedef void(*LogFunc)(const char *domName, logLevel_t level, const char *str);
// 参数说明:
// domName: 输出日志的模块名称(如 "IOTC", "AV", "RDT")
// level: 日志级别(对应 logLevel_t 枚举)
// str: 日志内容字符串
/***********************************************/
// 自定义日志输出回调函数
void LogOutFunc(const char *domName, logLevel_t level, const char *str)
{
if (str == NULL || domName == NULL) {
return;
}
// 按日志级别自定义输出格式(示例:区分级别打印)
switch (level) {
case LEVEL_ERROR:
printf("[ERROR] SDK-%s: %s\n", domName, str);
// print_ERROR("SDK, domName:%s, %s", domName, str); // 项目自定义错误打印接口
break;
case LEVEL_WARNING:
printf("[WARNING] SDK-%s: %s\n", domName, str);
// print_WARNING("SDK, domName:%s, %s", domName, str);
break;
case LEVEL_INFO:
printf("[INFO] SDK-%s: %s\n", domName, str);
// print_INFO("SDK, domName:%s, %s", domName, str);
break;
case LEVEL_DEBUG:
printf("[DEBUG] SDK-%s: %s\n", domName, str);
// print_DEBUG("SDK, domName:%s, %s", domName, str);
break;
case LEVEL_VERBOSE:
printf("[VERBOSE] SDK-%s: %s\n", domName, str);
// print_VERBOSE("SDK, domName:%s, %s", domName, str);
break;
case LEVEL_SILENCE:
break; // 静默级别,不输出任何日志
default:
printf("[UNKNOWN] SDK-%s: %s\n", domName, str);
break;
}
}
// 注册日志回调函数(需在模块初始化前调用)
TUTK_Set_Log_Callback(LogOutFunc);
五、FAQ(常见问题)
1. 带'T'的调试版本库能否用于正式环境?
可以。将日志级别设置为 LEVEL_SILENCE 即可关闭日志输出,性能与正式版本基本一致;后续需要排查问题时,可重新调整日志级别开启日志。
2. SDK 日志可用于排查哪些问题?
- ① 设备掉线问题:仅需设备端日志;
- ② APP 连线问题:一般需要 APP 端 + 设备端日志;
- ③ 数据传输不顺畅问题:一般需要 APP 端 + 设备端日志;
- ④ 特殊 API 报错:根据报错模块判断所需日志;
- ⑤ 崩溃问题:仅需崩溃发生端的日志。
3. 配置日志后无输出,可能原因有哪些?
- ① 未使用带'T'的调试版本库;
- ② 日志路径无写入权限(如 iOS 沙盒路径错误);
- ③ 日志级别设置过高(如设置为 LEVEL_ERROR,仅输出错误日志);
- ④ 日志配置接口调用时机晚于模块初始化;
- ⑤ iOS 平台未通过对应模块接口设置日志路径。
六、问题与日志对应表(IOTCAPIs+AVAPIs 场景)
下表列出常见问题所需的日志模块(√ 表示需要,空白表示不需要):
| 问题类型 | 客户端日志 | 设备端日志 | ||||
|---|---|---|---|---|---|---|
| IOTCAPIs | AVAPIs | GlobalAPIs | IOTCAPIs | AVAPIs | GlobalAPIs | |
| 设备掉线 | √ | √ | √ | |||
| 设备在线,IOTC 无法连接 | √ | √ | √ | √ | ||
| IOTC 连线成功,AV 通道创建失败 | √ | √ | √ | √ | √ | √ |
| 排查客户端端口占用 | √ | √ | √ | |||
| 排查设备端端口占用 | √ | √ | √ | |||
