跳转至

RUM 配置

本文用于承载 HarmonyOS RUM 初始化配置与手动采集能力。

初始化配置

import { FTSDK } from '@guancecloud/ft_sdk/src/main/ets/components/FTSDK';
import { FTRUMConfig } from '@guancecloud/ft_sdk/src/main/ets/components/Configs';

const rumConfig = new FTRUMConfig()
  .setRumAppId('your-app-id')
  .setSamplingRate(1.0)
  .setSessionErrorSampleRate(1.0)
  .setEnableTraceUserAction(true)
  .setEnableTraceUserView(true)
  .setEnableTraceUserResource(true)
  .setEnableTrackAppANR(true)
  .setEnableTrackAppCrash(true)
  .setEnableTraceWebView(true);

await FTSDK.installRUMConfig(rumConfig);
方法 类型 必须 说明
setRumAppId string RUM 应用 ID,从[用户访问监测]应用中获取
setSamplingRate number RUM 采样率,范围 [0.0, 1.0],默认 1.0
setSessionErrorSampleRate number 错误采样率,范围 [0.0, 1.0],默认 0.0
setEnableTraceUserAction boolean 是否开启自动动作追踪,默认 false
setEnableTraceUserView boolean 是否开启页面追踪,默认 false
setEnableTraceUserResource boolean 是否开启资源追踪,默认 false
setEnableTrackAppANR boolean 是否开启 ANR 监控,默认 false
setEnableTrackAppCrash boolean 是否开启 APP 崩溃监控,默认 false。如需 Native Crash,需依赖 @guancecloud/ft_native
setEnableTraceWebView boolean 是否开启 WebView 数据采集,默认 false。如需完整接入,请参考 WebView 数据监测
setRumCacheLimitCount number RUM 数据缓存数量限制,默认 100000,最小值 10000

View 手动采集

startView(viewName: string, property?: Record<string, object>): void
stopView(property?: Record<string, object>): void
updateLoadTime(loadTime: number): void

自动追踪:

在 RUM 配置中开启 enableTraceUserView 后,SDK 会自动追踪页面跳转,包括:

  • 路由导航(router.pushUrlrouter.replaceUrl 等)
  • Navigation 组件切换
import { FTRUMGlobalManager } from '@guancecloud/ft_sdk/src/main/ets/components/rum/FTRUMGlobalManager';

// 场景 1
FTRUMGlobalManager.getInstance().startView('ProductPage');

// 场景 2: 动态参数
class PropertyWrapper {
  value: string | number | boolean;

  constructor(v: string | number | boolean) {
    this.value = v;
  }
}

class ViewProperty {
  private properties: Map<string, string | number | boolean> = new Map();

  set(key: string, value: string | number | boolean): void {
    this.properties.set(key, value);
  }

  toObject(): Record<string, object> {
    const result: Record<string, object> = {} as Record<string, object>;
    this.properties.forEach((value, key) => {
      result[key] = new PropertyWrapper(value) as object;
    });
    return result;
  }
}

const viewProperty = new ViewProperty();
viewProperty.set('page_category', 'product');
viewProperty.set('page_id', '12345');
FTRUMGlobalManager.getInstance().startView('ProductPage', viewProperty.toObject());

FTRUMGlobalManager.getInstance().updateLoadTime(100000000);

// 场景 1
FTRUMGlobalManager.getInstance().stopView();

// 场景 2: 动态参数
const stopViewProperty = new ViewProperty();
stopViewProperty.set('view_duration', 1000);
FTRUMGlobalManager.getInstance().stopView(stopViewProperty.toObject());

注意事项:

  • 自动追踪需要在 RUM 配置中开启 enableTraceUserView(true)
  • 自动追踪会在页面切换时自动调用 startViewstopView,无需手动调用
  • 如果使用条件渲染等场景,仍可手动调用 startViewstopView
  • 页面名称会自动从路由路径或 Navigation 组件名称中提取

Action 手动采集

addAction(actionName: string, actionType: string, duration: number, startTime: number, property?: Record<string, object>): void
import { FTRUMGlobalManager } from '@guancecloud/ft_sdk/src/main/ets/components/rum/FTRUMGlobalManager';

// 场景 1: 直接完成
FTRUMGlobalManager.getInstance().addAction('buy_button_click', 'click');

// 场景 2: 动态参数
class PropertyWrapper {
  value: string | number | boolean;

  constructor(v: string | number | boolean) {
    this.value = v;
  }
}

class ActionProperty {
  private properties: Map<string, string | number | boolean> = new Map();

  set(key: string, value: string | number | boolean): void {
    this.properties.set(key, value);
  }

  toObject(): Record<string, object> {
    const result: Record<string, object> = {} as Record<string, object>;
    this.properties.forEach((value, key) => {
      result[key] = new PropertyWrapper(value) as object;
    });
    return result;
  }
}

const actionProperty = new ActionProperty();
actionProperty.set('product_id', '12345');
actionProperty.set('product_name', 'iPhone 15');
FTRUMGlobalManager.getInstance().addActionWithProperty('buy_button_click', 'click', actionProperty.toObject());

// 场景 3: 开始 Action(包含时长计算机制)
FTRUMGlobalManager.getInstance().startAction('buy_button_click', 'click');
FTRUMGlobalManager.getInstance().stopAction();

自动追踪:

在 RUM 配置中开启 enableTraceUserAction 后,SDK 会自动追踪 UI 组件的点击事件。为 Button 组件添加 customProperty 可获取按钮文本:

Button('Buy Now')
  .id('buy-btn')
  .customProperty('buy-btn', 'Buy Now')
  .onClick(() => {
    // 点击事件会自动被追踪
  })

Resource 手动采集

startResource(resourceId: string, property?: Record<string, object>): void
stopResource(resourceId: string): void
addResource(resourceId: string, resourceParams: ResourceParams, netStatusBean?: NetStatusBean): void

自动追踪:

在 RUM 配置中开启 enableTraceUserResource 后,SDK 可自动追踪以下请求:

  • @guancecloud/ft_sdk:RCP 与 Axios 兼容模式
  • @guancecloud/ft_sdk_ext:基于 @kit.NetworkKit HttpInterceptorChain 的增强模式,自 0.1.14-alpha03 起支持,且要求 HarmonyOS API 22+
import { FTRUMGlobalManager } from '@guancecloud/ft_sdk/src/main/ets/components/rum/FTRUMGlobalManager';
import { ResourceParams } from '@guancecloud/ft_sdk/src/main/ets/components/rum/bean/ResourceParams';
import { NetStatusBean } from '@guancecloud/ft_sdk/src/main/ets/components/rum/bean/NetStatusBean';

const resourceId = 'https://api.example.com/data';

FTRUMGlobalManager.getInstance().startResource(resourceId);

const resourceParams = new ResourceParams();
resourceParams.setUrl(resourceId);
resourceParams.setResourceStatus(200);
resourceParams.setResponseContentLength(1024);
resourceParams.resourceType = 'xhr';

const netStatusBean = new NetStatusBean();
netStatusBean.setResourceHostIP('192.168.1.1');
netStatusBean.setDNSTime(10000000);
netStatusBean.setTcpTime(20000000);
netStatusBean.setTTFB(50000000);
netStatusBean.setResponseTime(100000000);

FTRUMGlobalManager.getInstance().stopResource(resourceId);
FTRUMGlobalManager.getInstance().addResource(resourceId, resourceParams, netStatusBean);

Resource 自动追踪

开启 enableTraceUserResource(true) 后,SDK 会自动追踪通过 RCP、Axios 兼容模式或 @kit.NetworkKit HTTP 拦截器发送的请求。

RCP 自动追踪接入

在 RUM 配置中开启 enableTraceUserResource 后,SDK 会为通过 RCP 发送的 HTTP 请求自动采集 Resource 数据。

从当前版本开始,SDK 不再自动创建或持有全局 RCP Session,而是提供以下能力供业务自行装配:

  • RCPTraceInterceptor:自动注入 Trace Headers
  • RCPResourceInterceptor:自动采集 Resource 数据与性能指标
  • createFTRCPInterceptors():返回默认 RCP 拦截器列表,便于与自定义 SessionConfiguration 合并
  • createFTRCPTrackConfig():快速生成带默认拦截器和 TracingConfigurationSessionConfiguration

推荐接入方式:使用默认 SessionConfiguration 工厂函数

import { rcp } from '@kit.RemoteCommunicationKit';
import { createFTRCPTrackConfig } from '@guancecloud/ft_sdk/src/main/ets/components/network/FTHttpAutoTrack';

const session = rcp.createSession(
  createFTRCPTrackConfig({
    baseAddress: 'https://api.example.com'
  })
);

// GET 请求
const request = new rcp.Request('/data', 'GET');
const response = await session.fetch(request);

// POST 请求
const headers: rcp.RequestHeaders = { 'Content-Type': 'application/json' };
const postRequest = new rcp.Request('/data', 'POST', headers, { name: 'test' });
const postResponse = await session.fetch(postRequest);

如果项目通过 SDK 根入口导入,也可以使用:

import { createFTRCPTrackConfig } from '@guancecloud/ft_sdk/Index';

手动装配拦截器

如果需要完全控制 Session 配置,也可以直接使用 SDK 提供的拦截器:

import { rcp } from '@kit.RemoteCommunicationKit';
import { RCPTraceInterceptor, RCPResourceInterceptor } from '@guancecloud/ft_sdk/src/main/ets/components/network/FTHttpAutoTrack';

const session = rcp.createSession({
  baseAddress: 'https://api.example.com',
  interceptors: [
    new RCPTraceInterceptor(),
    new RCPResourceInterceptor()
  ],
  requestConfiguration: {
    tracing: {
      collectTimeInfo: true
    }
  }
});

TracingConfiguration 说明:

  • collectTimeInfo: true:建议开启。SDK 依赖 response.timeInfo 计算 DNS、TCP、SSL、TTFB、下载时间等性能指标
  • incomingHeader / outgoingHeader:可选,默认开启
  • incomingData / outgoingData:默认关闭,以减少额外开销

HTTP 拦截器接入

如果业务使用 @kit.NetworkKithttp.createHttp() 发起请求,可以通过 @guancecloud/ft_sdk_ext 提供的 HTTP 拦截器完成自动 Trace Header 注入和 Resource 采集。该接入方式自 0.1.14-alpha03 起支持,并要求 HarmonyOS API 22 及以上版本。

请先确保项目已安装:

  • ft_sdk.har,并在 oh-package.json5 中声明为 @guancecloud/ft_sdk
  • ft_sdk_ext.har,并在 oh-package.json5 中声明为 @guancecloud/ft_sdk_ext
  • 如果通过本地 HAR 安装 ft_sdk_ext.har,还需要在工程根目录的 oh-package.json5 中增加 overrides["@guancecloud/ft_sdk"] = "file:./libs/ft_sdk.har",将其内部依赖改写到本地 HAR

  • HttpInitialRequestInterceptor:在请求开始阶段注入 Trace Header,并启动 Resource

  • HttpFinalResponseInterceptor:在响应结束阶段补充 Resource 数据并结束采集
  • createFTHttpInterceptorChain():创建可复用的 http.HttpInterceptorChain
  • applyFTHttpTrack():将默认拦截器链直接挂载到单个 http.HttpRequest

提供两种接入方式。

方式一:使用 SDK 提供的默认工厂

import { http } from '@kit.NetworkKit';
import { createFTHttpInterceptorChain } from '@guancecloud/ft_sdk_ext/src/main/ets/components/network/FTHttpAutoTrackExt';

const request = http.createHttp();
const interceptorChain = createFTHttpInterceptorChain();
interceptorChain.apply(request);

try {
  const response = await request.request('https://httpbin.org/get', {
    method: http.RequestMethod.GET,
    header: {
      'Accept': 'application/json'
    }
  });
} finally {
  request.destroy();
}

如果希望继续追加业务自己的拦截器,也可以这样写:

import { http } from '@kit.NetworkKit';
import { createFTHttpInterceptorChain } from '@guancecloud/ft_sdk_ext/src/main/ets/components/network/FTHttpAutoTrackExt';

const request = http.createHttp();
const interceptorChain = createFTHttpInterceptorChain({
  interceptors: [
    new CustomAfterInterceptor()//追加自定义
  ]
});
interceptorChain.apply(request);

此时执行顺序为:

[
  new HttpInitialRequestInterceptor(),
  new HttpFinalResponseInterceptor(),
  new CustomAfterInterceptor()
]

方式二:手动装配 HttpInterceptorChain

如果业务本身已经有自定义拦截器,或者需要自由决定拦截器顺序,推荐直接手动创建 http.HttpInterceptorChain

import { http } from '@kit.NetworkKit';
import {
  HttpInitialRequestInterceptor,
  HttpFinalResponseInterceptor
} from '@guancecloud/ft_sdk_ext/src/main/ets/components/network/FTHttpAutoTrackExt';

const request = http.createHttp();
const interceptorChain = new http.HttpInterceptorChain();
interceptorChain.addChain([
  new CustomBeforeInterceptor(),
  new HttpInitialRequestInterceptor(),
  new HttpFinalResponseInterceptor()
]);
interceptorChain.apply(request);

注意事项:

  • HTTP 拦截器依赖 @kit.NetworkKit 在 API 22+ 提供的拦截器能力,低于 API 22 时请改用 RCP 或 Axios 兼容模式
  • HttpRequestContext 当前无法稳定拿到真实请求方法,因此 Resource 中的 method 会记录为 UNKNOWN
  • @kit.NetworkKit 的拦截器回调暂不暴露 RCP timeInfo 级别的明细耗时,因此当前只会补充 resourceLoad

Axios 接入

如果业务使用 @ohos/axios,可按以下方式接入自动追踪:

  • @guancecloud/ft_sdk:基于 Axios request/response interceptors 的兼容模式
  • @guancecloud/ft_sdk_ext:自 0.1.14-alpha03 起提供基于 interceptorChain 的增强模式

@ohos/axios 2.2.4 及以上版本

import axios from '@ohos/axios';
import { applyFTAxiosTrack } from '@guancecloud/ft_sdk/src/main/ets/components/network/FTHttpAutoTrack';

const client = axios.create({
  timeout: 10000
});

applyFTAxiosTrack(client);

该接入方式基于 Axios 的 request/response interceptors,可以与业务自己的拦截器共存使用:

import axios from '@ohos/axios';
import { applyFTAxiosTrack } from '@guancecloud/ft_sdk/src/main/ets/components/network/FTHttpAutoTrack';

const client = axios.create({
  timeout: 10000
});

applyFTAxiosTrack(client);

client.interceptors.request.use((config) => {
  config.headers = {
    ...(config.headers || {}),
    Authorization: 'Bearer <token>',
    'X-Signature': 'signed-value'
  };
  return config;
});

client.interceptors.response.use((response) => {
  return response;
});

执行次序说明:

  • @ohos/axios compat 模式下,request 拦截器表现为:后注册先执行
  • 这意味着多个 request interceptors 可以共存,但注册顺序会影响 FT 看到的是“修改前”还是“修改后”的请求头
  • 如果希望 FT 采集到业务补齐鉴权、签名等字段之后的最终请求头,推荐顺序是:applyFTAxiosTrack(client),再注册业务 request interceptor
  • 按上述顺序时,业务 request interceptor 会先执行,FT 随后执行并读取到最终的 headers
  • 如果希望调整次序,只需调整注册顺序;例如先注册业务、再调用 applyFTAxiosTrack(client) 时,FT 会先执行,业务拦截器后执行

@ohos/axios 2.2.8 及以上

对于 @ohos/axios 2.2.8 及以上版本,推荐优先通过 @guancecloud/ft_sdk_extinterceptorChain 接入 FT 自动追踪:

import axios from '@ohos/axios';
import { createFTHttpInterceptorChain } from '@guancecloud/ft_sdk_ext/src/main/ets/components/network/FTHttpAutoTrackExt';

const client = axios.create({
  timeout: 10000,
  interceptorChain: createFTHttpInterceptorChain()
});

如果存在多个 interceptor 共存、需要手动调整执行次序,或者需要与业务自定义拦截器统一装配的场景,可以参考 HTTP 拦截器接入 中的内容,按需自行组合 HttpInitialRequestInterceptorHttpFinalResponseInterceptor

如果按单次请求传入,也可以这样写:

import axios from '@ohos/axios';
import { createFTHttpInterceptorChain } from '@guancecloud/ft_sdk_ext/src/main/ets/components/network/FTHttpAutoTrackExt';

const response = await axios.request({
  url: 'https://httpbin.org/post',
  method: 'post',
  data: {
    source: 'axios',
    message: 'ft auto track'
  },
  responseType: 'string',
  interceptorChain: createFTHttpInterceptorChain()
});

注意事项:

  • 推荐在创建 Axios 实例时统一注入 interceptorChain,避免遗漏单次请求
  • interceptorChain 模式依赖 @guancecloud/ft_sdk_ext(本地 HAR 文件名仍为 ft_sdk_ext.har),并要求 HarmonyOS API 22+
  • 如需自动注入 Trace Headers,除了创建拦截器链外,还需要在 Trace 配置中开启 setEnableAutoTrace(true)
  • 如需自动采集 Resource,仍需在 RUM 配置中开启 setEnableTraceUserResource(true)
  • 如果调用方已有自定义 HTTP/Axios 拦截器,推荐直接使用 HttpInitialRequestInterceptorHttpFinalResponseInterceptor 手动装配顺序,避免在 FT 自动追踪之后再次改写 urlmethodheaders
  • SDK 只提供拦截器和默认配置工厂函数,RCP Session 的创建和生命周期由业务自己管理
  • 如果业务直接使用 rcp.createSession() 创建 Session,需要自行添加 SDK 提供的拦截器,否则请求不会被自动追踪
  • 如果业务直接使用 http.createHttp()@ohos/axios,需要显式挂载 applyFTHttpTrack()applyFTAxiosTrack()createFTHttpInterceptorChain()

Resource 性能指标说明

HarmonyOS SDK 通过 RCP(Remote Call Protocol)的 TimeInfo 接口获取网络请求的性能指标,包括 DNS、TCP、SSL、TTFB(Time To First Byte)等。

TTFB 计算说明:

  • HarmonyOS TTFB:使用 startTransferTimeMs - preTransferTimeMs 计算,包含服务器处理时间、网络传输时间和响应头接收时间
  • Android TTFB:仅表示响应头接收时间,通常很短

  • DNS 时间:nameLookupTimeMs

  • TCP 时间:connectTimeMs - nameLookupTimeMs
  • SSL 时间:tlsHandshakeTimeMs - connectTimeMs
  • TTFB:startTransferTimeMs - preTransferTimeMs
  • 下载时间:totalTimeMs - startTransferTimeMs

由于 HarmonyOS RCP API 的限制,preTransferTimeMs 几乎等于 SSL 完成时间,因此 HarmonyOS 的 TTFB 会包含服务器处理时间,导致其值通常比 Android 更大。这是预期的平台行为差异,并非 SDK 实现问题。

文档评价

文档内容是否对您有帮助? ×