帮你快速理解、总结文档立即下载

数据上报验证

最近更新时间:2026-09-30 17:29:02
本文档已由 AI 辅助审校
我的收藏
本文介绍接入用户体验监控 iOS SDK 后,如何验证各监控能力的数据上报是否成功。

前提条件

崩溃、卡顿、启动、网络、挣扎检测、设备信息默认开启,无需额外配置;用户行为(behavior.enabled)与 Session Replay(replay.enabled)默认关闭,需在初始化时显式开启。崩溃为100% 上报、不支持采样,其余能力均支持采样。
建议在接入期间将所有采样率调为1.0(如 replay.sessionSampleRate = 1.0),方便验证数据上报;接入完成后再按需调整。

步骤1:检查上报请求

初始化后,SDK 会发出下列请求(Session Replay 默认关闭,开启后才有回放上报)。HTTP 状态码 2xx 且响应体中 code 为 0 时视为成功:
端点
内容
POST {url}/api/v1/config
远程配置,仅在返回启用时才挂载各监控模块
POST {url}/api/v1/collect/events
标准事件(崩溃 / 卡顿 / 启动 / 网络 / 行为 / 挣扎 / 自定义事件等)
POST {url}/api/v1/collect/replay
Session Replay 录屏数据
url 填站点根地址即可,SDK 会自行拼接路径,无需手动补 /api/v1。SDK 自身与采集服务之间的同源请求会被自动排除,不会产生递归上报。

步骤2:验证各监控能力

崩溃监控

说明:
崩溃捕获依赖系统的 signal 监听接口,若 App 中接入其他具备类似能力的 SDK 或存在监听 signal 的逻辑,可能影响崩溃捕获成功率。请确保 SDK 初始化在其他监听逻辑注册之后,以减少对崩溃捕获的影响。
崩溃事件为 100% 上报,不参与采样,与其他监控能力相互独立。SDK 捕获范围覆盖以下四类异常:
Mach 异常(kscrash_mach)。
信号异常(kscrash_signal),如 SIGSEGV、SIGABRT。
OC 异常(kscrash_nsexception),即未被捕获的 NSException。
C++ 异常(kscrash_cpp)。
崩溃发生前若存在关联的点击行为记录,SDK 会额外派生一条 error_click 挣扎事件,用于定位「点击后崩溃」场景。

模拟异常

初始化完成后,可通过模拟 OC 异常、信号异常、C++ 异常来验证崩溃上报:
Swift
Objective-C
// 模拟 OC 异常
let data: Any = NSArray(object: "Hello World")
let _ = (data as! NSDictionary).object(forKey: "")

// 模拟信号异常
abort()

// 模拟 C++ 异常
// throw "Something went wrong"
// 模拟 OC 异常
id data = [NSArray arrayWithObject:@"Hello World"];
[(NSDictionary *)data objectForKey:@""];

// 模拟信号异常
abort();

// 模拟 C++ 异常(需在 .mm 文件中)
// throw std::runtime_error("Something went wrong");
崩溃发生后,异常需在第二次启动 App 时才完成上报,且上报可能存在延时。建议触发异常后重启 App,然后在 Xcode 控制台搜索关键字 TDEM 进行查看。

卡顿监控

可通过在主线程执行异常耗时任务模拟卡顿:
// 模拟卡顿(主线程阻塞)
while true {
// 空循环阻塞主线程
}
卡顿上报后,在 Xcode。 控制台搜索关键字 TDEM 进行查看。
卡顿监控包含两类事件:
lag_detected:主线程卡顿,判定阈值由 stallThresholdMs 控制,默认 1000ms,取值需大于 0 且小于 5000ms,否则初始化会失败(stall_invalid_configuration)。
no_response:主线程无响应,阈值固定 5000ms,由 SDK 内部写死,接入方不可修改。
两类事件都会采集代表性堆栈与掉帧指标。上方示例的死循环会触发 no_response;若要触发 lag_detected,阻塞时长需超过 stallThresholdMs 且低于 5000ms:
Swift
Objective-C
// 模拟卡顿:在主线程阻塞 3 秒
Thread.sleep(forTimeInterval: 3)
// 模拟卡顿:在主线程阻塞 3 秒
[NSThread sleepForTimeInterval:3];
Android 侧的 ANR 监控在 iOS 上由主线程无响应检测覆盖,iOS 无独立的 ANR 事件类型。

启动监控

启动监控默认开启,时间戳由 TDEMLaunchBridge 在进程启动阶段记录,早于 SDK 初始化执行,不依赖 TDEM.start 的调用时机。
iOS 启动类型共3种:
first:首次安装后的第一次启动。
cold:进程被杀死后重新启动。
warm:从后台切回,且后台停留超过 180 秒。
说明:
慢启动阈值由 SDK 内部维护(冷启动 4000ms / 温启动 2000ms),接入方不可修改。
默认在首个页面绘制后自动封口并上报事件 app_launch。若配置 configuration.launch.manualEndEnabled = true,则改为等待业务调用 TDEM.endLaunch();若 10 秒内未调用,SDK 会回落到首次绘制时刻封口,避免启动数据丢失。
上报耗时由 process_to_sdk_ms、sdk_to_did_finish_launching_ms、did_finish_launching_to_first_draw_ms 三段组成,duration 为三者之和。
验证方式:冷启动 App 后观察 Xcode 控制台中的启动日志。
Swift
Objective-C
let configuration = TDEMConfiguration(
id: "<project-key>",
url: URL(string: "https://dem.rumt-zh.com")!
)
configuration.launch.manualEndEnabled = true // 置 true 后需在首个页面绘制后调用 TDEM.endLaunch()
TDEM.start(configuration: configuration)
TDEMConfiguration *configuration =
[[TDEMConfiguration alloc] initWithId:@"<project-key>"
url:[NSURL URLWithString:@"https://dem.rumt-zh.com"]];
configuration.launch.manualEndEnabled = YES; // 置 YES 后需在首个页面绘制后调用 [TDEM endLaunch]
[TDEM startWithConfiguration:configuration];

网络监控

开启网络监控(network.enabled = true)后,正常发起任意 HTTP 请求即可验证网络请求数据的采集与上报,慢请求(超过 slowThresholdMs 阈值)会单独标记。采集的事件类型分三类:
api_call:成功的 HTTP 请求。
api_error:失败的 HTTP 请求,error_type 细分为 dns / connect / tls / timeout / read_write / cancelled / other。
sse_call:SSE 长连接。
默认仅上报慢成功与错误 / 取消的请求,如需上报全部成功请求,可将 reportAllSuccessfulRequests 置为 true。
Swift
Objective-C
configuration.network.enabled = true
configuration.network.slowThresholdMs = 1000
configuration.network.reportAllSuccessfulRequests = false
configuration.network.allowedHosts = ["api.example.com"] // 非空时仅采集命中白名单的请求
configuration.network.deniedHosts = [] // 仅在 allowedHosts 为空时生效
configuration.network.additionalSensitiveHeaderNames = ["x-custom-token"]
configuration.network.enabled = YES;
configuration.network.slowThresholdMs = 1000;
configuration.network.reportAllSuccessfulRequests = NO;
configuration.network.allowedHosts = @[ @"api.example.com" ]; // 非空时仅采集命中白名单的请求
configuration.network.deniedHosts = @[]; // 仅在 allowedHosts 为空时生效
configuration.network.additionalSensitiveHeaderNames = @[ @"x-custom-token" ];

行为监控与会话回放

行为监控需显式开启 behavior.enabled = true,开启后在 App 内进行页面跳转、点击等操作即可验证埋点上报。
开启行为监控后,SDK 采集以下事件:
页面:page_view
触摸:click / long_press / scroll
输入:form_focus / form_blur / form_change / form_submit
手动逻辑页可通过 startPage / leavePage 声明,二者需成对、按 LIFO 顺序调用:
Swift
Objective-C
TDEM.startPage(pageID: "checkout")
// ... 页面逻辑 ...
TDEM.leavePage()
[TDEM startPageWithPageID:@"checkout"];
// ... 页面逻辑 ...
[TDEM leavePage];
会话回放需显式开启 replay.enabled = true,建议临时将 sessionSampleRate 调为1.0。
Swift
Objective-C
let configuration = TDEMConfiguration(
id: "<project-key>",
url: URL(string: "https://dem.rumt-zh.com")!
)
configuration.behavior.enabled = true
configuration.replay.enabled = true
configuration.replay.sessionSampleRate = 1.0 // 验证期间建议置 1.0
TDEM.start(configuration: configuration)
TDEMConfiguration *configuration =
[[TDEMConfiguration alloc] initWithId:@"<project-key>"
url:[NSURL URLWithString:@"https://dem.rumt-zh.com"]];
configuration.behavior.enabled = YES;
configuration.replay.enabled = YES;
configuration.replay.sessionSampleRate = 1.0; // 验证期间建议置 1.0
[TDEM startWithConfiguration:configuration];
采样是双通道:sessionSampleRate(默认0.10)决定常规会话是否被录制;未命中时若 errorSampleRate(默认 1.0)大于 0,SDK 会进入缓冲模式,在发生错误时冲刷并上报(缓冲窗口默认30秒)。
控制台下发的远程配置 replay_sample_rate(0 - 100)会覆盖本地 sessionSampleRate。因此「开启了回放却没看到数据」不一定是接入失败,需要依次确认:本地 enabled 已开启、控制台远程配置已启用回放、且会话被采样命中。
录制清晰度由 quality 控制,可选 low(默认)/ medium / high。
iOS 默认遮罩输入类控件(UITextField / UITextView)与显式标记为敏感的视图,maskAllText / maskAllImages 默认均为 false。
如需对自动识别覆盖不到的控件(如订单金额、收货地址这类字面无语义特征的文案)主动声明为敏感,可调用 TDEMPrivacyMetadata:
Swift
Objective-C
// 标记为敏感:行为监控不采集该控件文本,Session Replay 遮罩该控件及其子树
TDEMPrivacyMetadata.setSensitive(true, for: orderAmountLabel)

// 只调 Session Replay 遮罩,不影响文本采集
TDEMPrivacyMetadata.setReplayMasking(.masked, for: qrCodeView)
TDEMPrivacyMetadata.setReplayMasking(.inherit, for: qrCodeView) // 恢复默认判定
// 标记为敏感:行为监控不采集该控件文本,Session Replay 遮罩该控件及其子树
[TDEMPrivacyMetadata setSensitive:YES forView:orderAmountLabel];

// 只调 Session Replay 遮罩,不影响文本采集
[TDEMPrivacyMetadata setReplayMasking:TDEMReplayMaskingMasked forView:qrCodeView];
[TDEMPrivacyMetadata setReplayMasking:TDEMReplayMaskingInherit forView:qrCodeView]; // 恢复默认判定
标记父容器时,Session Replay 会把标记向下传递(等价于遮罩整棵子树);行为监控只判定被标记的控件本身,子控件文本仍会被采集,需逐个标记。
验证方式:开启 Session Replay 后操作 App,在控制台的回放列表查看会话录像,并确认被标记的控件在录像中已遮罩。

挣扎检测

挣扎检测默认开启,产出5类子事件:
rage_click:同一元素1秒内连续点击5次。
dead_click:点击后 3 秒内既无页面跳转也无接口调用,判定为无响应。
error_click:点击后 3 秒内出现接口错误或 JS / Promise 错误。
long_focus_time:输入控件持续聚焦超过20秒。
back_forward:10 秒内连续返回3次。
说明:
规则阈值由 SDK 内部维护,接入方不可修改。
需要注意的是,默认配置下通常只有 back_forward 能被触发。click / form_focus / form_blur 等事件由用户行为监控(behavior.enabled)产生,而行为监控默认关闭,因此依赖这些事件源的 rage_click / dead_click / error_click / long_focus_time 会静默失效。要完整验证挣扎检测,需要同时开启行为监控:
Swift
Objective-C
let configuration = TDEMConfiguration(
id: "<project-key>",
url: URL(string: "https://dem.rumt-zh.com")!
)
configuration.behavior.enabled = true // 必需:提供点击 / 表单事件源
TDEM.start(configuration: configuration)
TDEMConfiguration *configuration =
[[TDEMConfiguration alloc] initWithId:@"<project-key>"
url:[NSURL URLWithString:@"https://dem.rumt-zh.com"]];
configuration.behavior.enabled = YES; // 必需:提供点击 / 表单事件源
[TDEM startWithConfiguration:configuration];
说明:
back_forward 消费的是页面事件,而页面事件有不受行为监控开关影响的来源(startPage / setPage / leavePage),因此它单独可用。
如需精确忽略某个控件的 dead click 判定,可调用 TDEMBehaviorMetadata.setDeadClickIgnored(_:for:)。
验证方式:连点同一按钮5次以上触发 rage_click,或在10秒内连续返回3次触发 back_forward,随后在控制台的挣扎事件页查看。

设备信息

设备信息随每条事件的上下文一并上报,SDK 在事件批次中填充 session_id / app_version / environment / user_id / device_type / os / os_version / screen_resolution / device_id 字段。其中 SDK 版本号位于批次的 sdk 对象(sdk.name / sdk.version)中。
验证方式:在控制台打开任一事件的详情,确认事件上下文中的上述字段已填充。

步骤3:主动上报(可选)

除自动采集外,SDK 提供下列主动上报接口,均为 TDEM 的类方法,可直接调用。
Swift
Objective-C
// 自定义事件
TDEM.track("order_submit", tags: ["channel": "app"], properties: ["amount": 99])

// 自定义测速:可直接传耗时,也可 start / end 成对使用
TDEM.measure("api_latency", duration: 320, tags: ["api": "/user/info"], properties: [:])
TDEM.startMeasure("render")
TDEM.endMeasure("render", tags: ["step": "pay"], properties: [:]) // 未调用 startMeasure 时为 no-op

// 上报已捕获异常(未导致崩溃的业务异常)
TDEM.captureException(error, tags: ["module": "payment"], properties: [:])

// 自定义挣扎
TDEM.trackStruggle("custom_struggle", severity: .high, properties: ["element": "buy_btn"], tags: [:])
// 自定义事件
[TDEM trackWithName:@"order_submit" tags:@{ @"channel": @"app" } properties:@{ @"amount": @99 }];

// 自定义测速:可直接传耗时,也可 start / end 成对使用
[TDEM measureWithName:@"api_latency" duration:320 tags:@{ @"api": @"/user/info" }];
[TDEM startMeasureWithName:@"render"];
[TDEM endMeasureWithName:@"render" tags:@{ @"step": @"pay" }]; // 未调用 startMeasure 时为 no-op

// 上报已捕获异常(未导致崩溃的业务异常)
[TDEM captureExceptionWithError:error tags:@{ @"module": @"payment" }];

// 自定义挣扎
[TDEM trackStruggleWithName:@"custom_struggle" severity:TDEMStruggleSeverityHigh properties:@{ @"element": @"buy_btn" }];
用户标识、设备标识与全局标签:
Swift
Objective-C
TDEM.setUser("user-456") // 设置用户标识,用于用户维度聚合
TDEM.clearUser() // 清除用户标识
TDEM.setDeviceId("device-abc") // 设置设备标识,由宿主提供
TDEM.clearDeviceId() // 清除设备标识,回落 not_set
TDEM.setTags(["role": "admin", "team": "dev"]) // 设置 / 追加标签
TDEM.removeTags(["team"]) // 移除指定标签
TDEM.clearTags() // 清空所有标签
[TDEM setUser:@"user-456"]; // 设置用户标识,用于用户维度聚合
[TDEM clearUser]; // 清除用户标识
[TDEM setDeviceId:@"device-abc"]; // 设置设备标识,由宿主提供
[TDEM clearDeviceId]; // 清除设备标识,回落 not_set
[TDEM setTags:@{ @"role": @"admin", @"team": @"dev" }]; // 设置 / 追加标签
[TDEM removeTags:@[ @"team" ]]; // 移除指定标签
[TDEM clearTags]; // 清空所有标签
生命周期与缓冲控制:
Swift
Objective-C
TDEM.endLaunch() // 手动结束启动(需先设 launch.manualEndEnabled = true)
TDEM.flush() // 立即冲刷缓冲事件
TDEM.stop() // 停止 SDK
[TDEM endLaunch]; // 手动结束启动(需先设 launch.manualEndEnabled = YES),返回 BOOL
[TDEM flush]; // 立即冲刷缓冲事件
[TDEM stop]; // 停止 SDK
如需上报业务日志,可改用 TDEM.track 自定义事件承载。
验证方式:调用后在控制台对应的自定义事件、挣扎事件或用户页确认数据已入库。完整签名与参数说明见 API 说明。

步骤4:检查数据上报

iOS SDK 的日志通过 NSLog 输出,格式为 [TDEM][<category>] <code>。诊断日志默认关闭,需在初始化时设置 configuration.debug = true 才会输出。
在 Xcode 的 Console 中按 TDEM 过滤即可:
[TDEM][transport] acknowledged
[TDEM][behavior] page_view_persist_failed
[TDEM][lifecycle] launch_sealed
也可以打开 macOS 的控制台 App,选择对应的模拟器 / 真机设备后按 TDEM 过滤。