HarmonyOS —— 基于 TracingConfiguration 做 HTTP 性能维测实战笔记
HarmonyOS —— 基于 TracingConfiguration 做 HTTP 性能维测实战笔记
前面折腾了 DNS / 传输 / 代理 / 安全 / 拦截器 / 流式传输,这一篇换个视角:
不改行为,只“看清楚”HTTP 每一步花了多少时间、数据是怎么流的。
也就是:基于TracingConfiguration做性能埋点 & 调试。
一、能力概览 & 设备支持
TracingConfiguration 的作用:
- 捕获一次 HTTP 请求 / 响应链路上的 详细事件 & 时间信息;
- 可按需打开不同级别的跟踪:
- 是否输出详细日志(
verbose) - 收集哪些类型的信息事件(
infoToCollect) - 要不要采集时间信息(
collectTimeInfo) - HTTP 关键节点的回调处理(
httpEventsHandler)
- 是否输出详细日志(
设备支持:
- 支持:Phone / 2in1 / Tablet / Wearable
- 自 5.1.1(19) 起:新增 TV 支持
一句记:性能维测能力支持 Phone / 2in1 / Tablet / Wearable,5.1.1(19) 起支持 TV。
二、用 TracingConfiguration 捕获请求 / 响应详细过程
1. HttpEventsHandler:拿到“数据 + 头 + 结束”的时刻
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 自定义 HTTP 事件处理器
const customHttpEventsHandler: rcp.HttpEventsHandler = {
onDataReceive: (incomingData: ArrayBuffer) => {
// 每收到一块响应 body 数据都会回调这里
console.info('Received data:', JSON.stringify(incomingData));
return incomingData.byteLength; // 返回处理的数据长度
},
onHeaderReceive: (headers: rcp.RequestHeaders) => {
// 收到响应头时调用
console.info('Received headers:', JSON.stringify(headers));
},
onDataEnd: () => {
// 整个响应数据传输完成时
console.info('Data transfer complete');
}
};
可以用来做什么?
onHeaderReceive:- 做响应头检查、埋点、根据 header 动态调整 UI;
onDataReceive:- 边下边解码(比如流式 JSON、日志、视频分片等);
onDataEnd:- 做「加载完成」打点,或者触发下一阶段逻辑。
2. 配置 TracingConfiguration
const tracingConfig: rcp.TracingConfiguration = {
verbose: true, // 打开详细跟踪
infoToCollect: {
incomingHeader: true, // 收集传入 header 事件
outgoingHeader: true, // 收集传出 header 事件
incomingData: true, // 收集传入数据事件
outgoingData: true // 收集传出数据事件
},
collectTimeInfo: true, // 采集时间信息(TimeInfo)
httpEventsHandler: customHttpEventsHandler
};
const securityConfig: rcp.SecurityConfiguration = {
tlsOptions: {
tlsVersion: 'TlsV1.3'
}
};
// 创建会话时挂上 tracing 配置
const session = rcp.createSession({
requestConfiguration: {
tracing: tracingConfig,
security: securityConfig
}
});
// 发起请求
session.get('http://developer.huawei.com').then((response) => {
console.info(`Request succeeded, message is ${JSON.stringify(response)}`);
}).catch((err: BusinessError) => {
console.error(`err: err code is ${err.code}, err message is ${JSON.stringify(err)}`);
});
几个关键开关:
verbose: true
→ 输出更详细的调试信息(配合debugInfo使用时尤其有用)。infoToCollectincomingHeader / outgoingHeader:谁在什么时候发/收了哪些 header;incomingData / outgoingData:数据块的流动情况;
collectTimeInfo: true
→ 这一步是后面拿 精确时间点 的前提,response.timeInfo才会有值。
三、TimeInfo:HTTP 请求全过程的“时间轴”
官方给的时间线可以简单理解为:
0 ms (请求开始)
↓ nameLookupTimeMs // DNS 解析完成
↓ connectTimeMs // 建连完成(TCP 完成)
↓ tlsHandshakeTimeMs // TLS 握手完成
↓ preTransferTimeMs // 业务请求数据发完
↓ startTransferTimeMs // 收到首包响应数据
...
↓ totalTimeMs // 整个请求结束
所有这些字段,都是“相对于 0 时刻”的耗时(单位一般是 ms)。
常见关注三大时间段
- 首包耗时:从请求发完到收到首包的时间
首包耗时 = startTransferTimeMs - preTransferTimeMs
- TLS 握手耗时(不包含建连)
TLS 耗时 = tlsHandshakeTimeMs - connectTimeMs
- 接收剩余数据的耗时
接收剩余数据耗时 = totalTimeMs - startTransferTimeMs
- 对应问题:
- DNS 慢?TLS 慢?服务端处理慢?还是下行带宽 / RTT 问题?
- TimeInfo 就是拆开这些阶段的关键。
四、实战:打印首包 / TLS / 剩余数据耗时
这段示例就是专门帮你“算并打印三个关键指标”的:
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 1. 创建 session & URL
const session = rcp.createSession();
const requestURL = "https://www.example.com";
// 2. 配置:只关心时间信息的话,至少要打开 collectTimeInfo
const configuration: rcp.Configuration = {
tracing: {
collectTimeInfo: true
}
};
// 3. 创建请求并挂上配置
const request = new rcp.Request(requestURL, "GET");
request.configuration = configuration;
// 4. 发起请求
session.fetch(request).then((response: rcp.Response) => {
if (!response.timeInfo) {
console.error(`timeInfo is undefined ${response.timeInfo}`);
return;
}
const timeInfo = response.timeInfo;
// 注意:字段可能为 undefined,做运算时要小心判空
const remainderDataTime =
(timeInfo.totalTimeMs ?? 0) - (timeInfo.startTransferTimeMs ?? 0);
const firstPackageTime =
(timeInfo.startTransferTimeMs ?? 0) - (timeInfo.preTransferTimeMs ?? 0);
const TLSTime =
(timeInfo.tlsHandshakeTimeMs ?? 0) - (timeInfo.connectTimeMs ?? 0);
console.info(`首包耗时: ${firstPackageTime} ms`);
console.info(`TLS 握手(不含建连)耗时: ${TLSTime} ms`);
console.info(`接收剩余数据的耗时: ${remainderDataTime} ms`);
}).catch((err: BusinessError) => {
console.error(`Response err, the err is ${JSON.stringify(err)}`);
});
你可以在此基础上做更多事情,比如:
- 首包耗时 > 某个阈值 → 上报埋点,标记网络慢;
- TLS 耗时过长 → 提示用户检查代理 / 中间网关;
- 接收剩余耗时过长 → 有可能是服务端处理慢或下行带宽问题。
五、结合前面章节:TracingConfiguration 能怎么用?
给你几个后续可以串起来写博客 / 出考点的思路:
- 和 TransferConfiguration / PausePolicy 联动
- 监控请求耗时,如果超过某阈值自动触发暂停 / 重试;
- 通过 TimeInfo 定位到底是建连慢、TLS 慢、首包慢还是 body 很大。
- 和 Interceptor 拦截器联动
- 在拦截器里统一打日志 + 打上 traceId;
- TracingConfiguration 收集底层时间,拦截器收集“业务维度”信息,两者组合做完整链路追踪。
- 和 流式传输 配合
- 使用
httpEventsHandler.onDataReceive+ NetworkOutputQueue / downloadToStream:- 实时统计每块数据到达时间,做简单吞吐监控;
- 或者对关键接口做实时“下载速度曲线”。
- 使用
- 和 SecurityConfiguration 联动
- 利用 TLS 时长(
tlsHandshakeTimeMs)分析不同 TLS 版本、不同 CA 的握手影响; - 可以在测试环境切换配置,比较性能数据。
- 利用 TLS 时长(
六、结尾小抄:TracingConfiguration 核心记忆点
- TracingConfiguration 能配什么?
verbose:是否启用详细跟踪infoToCollect:选择收集哪些事件(header / data 的 incoming / outgoing)collectTimeInfo:是否采集 TimeInfohttpEventsHandler:三大回调:onHeaderReceiveonDataReceiveonDataEnd
- TimeInfo 常用字段 & 计算公式:
firstPackageTime = startTransferTimeMs - preTransferTimeMsTLSTime = tlsHandshakeTimeMs - connectTimeMsremainderDataTime = totalTimeMs - startTransferTimeMs
- 设备支持:
- Phone / 2in1 / Tablet / Wearable
- 5.1.1(19) 起:新增 TV

浙公网安备 33010602011771号