Skip to content

RUM Configuration

This document is used to carry the HarmonyOS RUM initialization configuration and manual collection capabilities.

RUM Initialization Configuration

import { FTSDK, FTRUMConfig } from '@guancecloud/ft_sdk/Index';

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

FTSDK.installRUMConfig(rumConfig);
Method Type Required Description
setRumAppId string Yes RUM application ID, obtained from the [RUM] application
setSamplingRate number No RUM sampling rate, range [0.0, 1.0], default 1.0
setSessionErrorSampleRate number No Error sampling rate, range [0.0, 1.0], default 0.0
setEnableTraceUserAction boolean No Whether to enable automatic action tracing, default false
setEnableTraceUserView boolean No Whether to enable page tracing, default false
setEnableTraceUserResource boolean No Whether to enable resource tracing, default false
setEnableTrackAppUIBlock boolean, number No Whether to enable UI freeze detection, default false. The second parameter blockDurationMs is used to control the detection time range [100,), in milliseconds, default 1000ms
setEnableTrackAppANR boolean No Whether to enable ANR monitoring, default false
setEnableTrackAppCrash boolean No Whether to enable APP crash monitoring, default false. For Native Crash, @guancecloud/ft_native is required
setEnableTraceWebView boolean No Whether to enable WebView data collection, default false. For full integration, refer to WebView Data Monitoring
setAllowWebViewHost Array<string> \| null No Set the allowed Host whitelist for WebView JavaScript Bridge. Pass null or empty array to not restrict Host; for restrictions, refer to WebView Data Monitoring
setRumCacheLimitCount number No RUM data cache limit count, default 100000, minimum 10000
setRumCacheDiscardStrategy RUMCacheDiscard No Set the RUM discard rule when data reaches the upper limit, default RUMCacheDiscard.DISCARD, DISCARD discards appended data, DISCARD_OLDEST discards old data

RUM Manual Collection

Configure setEnableTraceUserAction, setEnableTraceUserView, setEnableTraceUserResource, setEnableTrackAppUIBlock, setEnableTrackAppCrash, and setEnableTrackAppANR in FTRUMConfig to achieve automatic collection of Action, View, Resource, LongTask, and Error. If custom collection is needed, use FTRUMGlobalManager for manual reporting.

View

Usage

/**
 * Start the View lifecycle.
 *
 * @param viewName View name.
 * @param property Optional extended properties.
 */
startView(viewName: string, property?: Record<string, object>): Promise<void>

/**
 * End the current View lifecycle.
 *
 * @param property Optional extended properties.
 */
stopView(property?: Record<string, object>): Promise<void>

/**
 * Update the load time of the current View.
 *
 * @param loadTime Load time, in nanoseconds.
 */
updateLoadTime(loadTime: number): void

Code Example

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

@Entry
@Component
struct ProductPage {
  async aboutToAppear() {
    // Scenario 1:
    await FTRUMGlobalManager.getInstance().startView('ProductPage');

    // Scenario 2: With extended properties
    const viewProperty: Record<string, object> = { page_category: new String('product'), page_id: new String('12345') };
    await FTRUMGlobalManager.getInstance().startView('ProductPage', viewProperty);

  }

  async aboutToDisappear() {
    // Scenario 1:
    await FTRUMGlobalManager.getInstance().stopView();

    // Scenario 2:
    const stopViewProperty: Record<string, object> = { view_duration: new Number(1000) };
    await FTRUMGlobalManager.getInstance().stopView(stopViewProperty);
  }

  build() {
    Column() {
      Text('Product Page');
    }
  }
}

Action

Usage

/**
 * Add a completed Action; this data will not be associated with Error, Resource, or LongTask.
 *
 * @param actionName Action name.
 * @param actionType Action type, e.g., `click`.
 * @param durationOrProperty Optional. When a number, indicates duration (nanoseconds); when a Record, indicates extended properties.
 * @param property Optional. Only passed when the third parameter is a duration.
 */
addAction(
  actionName: string,
  actionType: string,
  durationOrProperty?: number | Record<string, object>,
  property?: Record<string, object>
): void

/**
 * Start an Action; the SDK will manage the end timing and associate nearby Resource, LongTask, and Error data.
 *
 * @param actionName Action name.
 * @param actionType Action type, e.g., `click`.
 * @param property Optional extended properties.
 */
startAction(
  actionName: string,
  actionType: string,
  property?: Record<string, object>
): void

addAction(...) is used for actions completed directly, cannot associate data such as Error, Resource, or LongTask. The duration unit is nanoseconds: the third parameter can directly pass extended properties; if both duration and extended properties need to be passed, they are passed as the third and fourth parameters respectively.

startAction(...) will have the SDK manage the end timing and associated data; manual control interfaces such as stopAction(...) or waiting state are not provided.

Code Example

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

// Scenario 1:
FTRUMGlobalManager.getInstance().addAction('buy_button_click', 'click');

// Scenario 2: With extended properties
const actionProperty: Record<string, object> = {
  product_id: new String('product_id'),
  product_name: new String('product_name')
};
FTRUMGlobalManager.getInstance().addAction('buy_button_click', 'click', actionProperty);

// Scenario 1:
FTRUMGlobalManager.getInstance().startAction('buy_button_click', 'click');

// Scenario 2: With extended properties
const startActionProperty: Record<string, object> = {
  product_id: new String('product_id'),
  product_name: new String('product_name')
};
FTRUMGlobalManager.getInstance().startAction('buy_button_click', 'click', startActionProperty);

Error

Usage

/**
 * Report an Error.
 *
 * @param log Error log or stack trace.
 * @param message Message.
 * @param errorType Error type, can be `ErrorType` enum or string.
 * @param state Application running state when the error occurred.
 * @param property Optional extended properties.
 */
addError(
  log: string,
  message: string,
  errorType: string | ErrorType,
  state: AppState,
  property?: Record<string, object> | null
): void

/**
 * Report an Error with a specified occurrence time.
 *
 * @param log Error log or stack trace.
 * @param message Message.
 * @param dateline Error occurrence time, in nanoseconds.
 * @param errorType Error type, can be `ErrorType` enum or string.
 * @param state Application running state when the error occurred.
 * @param property Optional extended properties.
 */
addError(
  log: string,
  message: string,
  dateline: number,
  errorType: string | ErrorType,
  state: AppState,
  property?: Record<string, object> | null
): void

Use ErrorType.CUSTOM for custom errors. dateline is an optional occurrence time, in nanoseconds.

Code Example

import { FTRUMGlobalManager, ErrorType, AppState } from '@guancecloud/ft_sdk/Index';
import { systemDateTime } from '@kit.BasicServicesKit';

// Scenario 1:
FTRUMGlobalManager.getInstance().addError('error log', 'error message', ErrorType.CUSTOM, AppState.RUN);

// Scenario 2: When reporting delayed, pass the actual error occurrence time (in nanoseconds).
const errorTimeNs = systemDateTime.getTime(true);
FTRUMGlobalManager.getInstance().addError('error log', 'error message', errorTimeNs, ErrorType.CUSTOM, AppState.RUN);

// Scenario 3: With extended properties.
const errorProperty: Record<string, object> = {
  module: new String('checkout'),
  action: new String('submit_order')
};
FTRUMGlobalManager.getInstance().addError('error log', 'error message', ErrorType.CUSTOM, AppState.RUN, errorProperty);

LongTask

Usage

/**
 * Report a LongTask.
 *
 * @param log Log or stack trace when the freeze occurred.
 * @param duration Freeze duration, in nanoseconds.
 * @param property Optional extended properties.
 */
addLongTask(log: string, duration: number, property?: Record<string, string | number | boolean>): void

duration is in nanoseconds.

Code Example

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

const durationMs = 350;
const durationNs = durationMs * 1000000;
const stack = new Error('checkout render long task').stack ?? 'Stack trace not available';

// Scenario 1:
FTRUMGlobalManager.getInstance().addLongTask(stack, durationNs);

// Scenario 2: With extended properties.
const longTaskProperty: Record<string, string | number | boolean> = {
  module: 'checkout',
  operation: 'render_order_list',
  threshold_ms: 200
};
FTRUMGlobalManager.getInstance().addLongTask(stack, durationNs, longTaskProperty);

Resource

Usage

/**
 * Start the Resource lifecycle.
 *
 * @param resourceId Unique resource identifier; must use the same value with `stopResource`, `addResource`.
 * @param property Optional extended properties.
 */
startResource(resourceId: string, property?: Record<string, object>): void

/**
 * End the Resource lifecycle.
 *
 * @param resourceId Unique resource identifier; should use the same value as `startResource`.
 * @param property Optional extended properties.
 */
stopResource(resourceId: string, property?: Record<string, object>): void

/**
 * Supplement the request, response, and network performance data of the Resource.
 *
 * @param resourceId Unique resource identifier; should use the same value as `startResource`, `stopResource`.
 * @param resourceParams Resource details, such as URL, request method, response status, response length, and extended properties.
 * @param netStatusBean Network performance data, such as DNS, TCP, TTFB, and response time.
 */
addResource(resourceId: string, resourceParams: ResourceParams, netStatusBean: NetStatusBean): void

Extended properties passed in startResource(...) and stopResource(...) will be merged with properties in ResourceParams in the order of invocation. Resource status code and response length should be set via ResourceParams, and are no longer passed as parameters of stopResource(...).

Code Example

import {
  FTRUMGlobalManager,
  ResourceParams,
  NetStatusBean
} from '@guancecloud/ft_sdk/Index';

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

// Scenario 1:
// Request start
FTRUMGlobalManager.getInstance().startResource(resourceId);

// After request ends, supplement request, response, and network performance data.
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);

// Scenario 2: With extended properties. The following is a separate request; replace the startResource and stopResource calls in Scenario 1 when using.
const startResourceProperty: Record<string, object> = {
  request_source: new String('checkout')
};
FTRUMGlobalManager.getInstance().startResource(resourceId, startResourceProperty);

const stopResourceProperty: Record<string, object> = {
  response_cache: new Boolean(false)
};
FTRUMGlobalManager.getInstance().stopResource(resourceId, stopResourceProperty);

NetStatusBean Property Description

NetStatusBean is used to supplement network performance data for manual Resource collection. All time parameter units are nanoseconds, *StartTime indicates the offset relative to the Resource start time; unset time values default to -1 and will not be written to the corresponding metrics.

Method Description
setDNSTime DNS resolution time
setDNSStartTime DNS resolution start offset
setTcpTime TCP connection time
setConnectStartTime TCP connection start offset
setSSLTime SSL/TLS handshake time
setSslStartTime SSL/TLS handshake start offset
setTTFB Time to first byte wait (TTFB)
setResponseTime Response transfer time
setFirstByteTime First byte stage time
setFirstByteStartTime First byte stage start offset
setDownloadTime Response download time
setDownloadTimeStart Response download start offset
setHoleRequestTime Total request time (API name retains Hole spelling per SDK definition)
setResourceHostIP Resource server IP address

Resource Automatic Tracing

When setEnableTraceUserResource(true) is enabled, the SDK will automatically trace requests sent via RCP, Axios compatibility mode, or @kit.NetworkKit HTTP interceptors.

When integrating with @guancecloud/ft_sdk_ext, it is recommended to import public APIs from @guancecloud/ft_sdk_ext/Index to avoid deep paths like src/main/....

RCP Automatic Tracing Integration

After enabling setEnableTraceUserResource in the RUM configuration, the SDK will automatically collect Resource data for HTTP requests sent via RCP.

Starting from this version, the SDK no longer automatically creates or holds a global RCP Session, but provides the following capabilities for the business to assemble:

  • RCPTraceInterceptor: Automatically injects Trace Headers
  • RCPResourceInterceptor: Automatically collects Resource data and performance metrics
  • createFTRCPInterceptors(): Returns a default list of RCP interceptors, convenient for merging with custom SessionConfiguration
  • createFTRCPTrackConfig(): Quickly generates a SessionConfiguration with default interceptors and TracingConfiguration

Recommended Integration: Use the default SessionConfiguration factory function

import { rcp } from '@kit.RemoteCommunicationKit';
import { createFTRCPTrackConfig } from '@guancecloud/ft_sdk/Index';

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

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

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

If the project imports through the SDK root entry, the following can also be used:

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

Manual Interceptor Assembly

If full control over Session configuration is needed, the interceptors provided by the SDK can be used directly:

import { rcp } from '@kit.RemoteCommunicationKit';
import { RCPTraceInterceptor, RCPResourceInterceptor } from '@guancecloud/ft_sdk/Index';

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

TracingConfiguration Description:

  • collectTimeInfo: true: Recommended to enable. The SDK depends on response.timeInfo to calculate performance metrics such as DNS, TCP, SSL, TTFB, and download time
  • incomingHeader / outgoingHeader: Optional, enabled by default
  • incomingData / outgoingData: Disabled by default to reduce overhead

HTTP Interceptor Integration

If the business uses @kit.NetworkKit's http.createHttp() to make requests, automatic Trace Header injection and Resource collection can be achieved through the HTTP interceptor provided by @guancecloud/ft_sdk_ext. This integration method is supported since 0.1.14-alpha03 and requires HarmonyOS API 22 or above.

First, ensure the project has installed:

  • ft_sdk.har, and declared as @guancecloud/ft_sdk in oh-package.json5
  • ft_sdk_ext.har, and declared as @guancecloud/ft_sdk_ext in oh-package.json5
  • If ft_sdk_ext.har is installed via a local HAR, add overrides["@guancecloud/ft_sdk"] = "file:./libs/ft_sdk.har" in the root oh-package.json5 to rewrite its internal dependency to the local HAR

The SDK provides the following capabilities:

  • HttpInitialRequestInterceptor: Injects Trace Headers at the start of the request and starts Resource
  • HttpFinalResponseInterceptor: Supplements Resource data at the end of the response and ends collection
  • createFTHttpInterceptorChain(): Creates a reusable http.HttpInterceptorChain
  • applyFTHttpTrack(): Mounts the default interceptor chain directly to a single http.HttpRequest

Two integration methods are provided.

Method 1: Use the SDK's default factory

import { http } from '@kit.NetworkKit';
import { createFTHttpInterceptorChain } from '@guancecloud/ft_sdk_ext/Index';

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();
}

If you want to append your own business interceptors, you can also write like this:

import { http } from '@kit.NetworkKit';
import { createFTHttpInterceptorChain } from '@guancecloud/ft_sdk_ext/Index';

const request = http.createHttp();
const interceptorChain = createFTHttpInterceptorChain({
  interceptors: [
    new CustomAfterInterceptor()// Append custom
  ]
});
interceptorChain.apply(request);

The execution order will be:

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

Method 2: Manually assemble HttpInterceptorChain

If the business already has custom interceptors, or needs to freely determine the order of interceptors, it is recommended to manually create http.HttpInterceptorChain:

import { http } from '@kit.NetworkKit';
import {
  HttpInitialRequestInterceptor,
  HttpFinalResponseInterceptor
} from '@guancecloud/ft_sdk_ext/Index';

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

Notes:

  • HTTP interceptors rely on the interceptor capability provided by @kit.NetworkKit in API 22+. For lower API versions, use RCP or Axios compatibility mode instead
  • In the HTTP interceptor mode using http.createHttp() directly, HttpRequestContext currently cannot stably obtain the actual request method, so the method in Resource may be recorded as UNKNOWN
  • If the business uses @ohos/axios in interceptorChain mode, it is recommended to additionally mount applyFTAxiosChainMethodBridge() to bridge the actual method, url, and headers from axios
  • The interceptor callback of @kit.NetworkKit does not currently expose detailed timing at the RCP timeInfo level, so only resourceLoad will be supplemented

Axios Integration

If the business uses @ohos/axios, automatic tracing can be integrated as follows:

  • @guancecloud/ft_sdk: Based on Axios request/response interceptors compatibility mode
  • @guancecloud/ft_sdk_ext: Since 0.1.14-alpha03, provides an enhanced mode based on interceptorChain

@ohos/axios 2.2.4 and above

This integration method is based on Axios request/response interceptors.

import axios from '@ohos/axios';
import { applyFTAxiosTrack } from '@guancecloud/ft_sdk/Index';

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

applyFTAxiosTrack(client);

This integration method can coexist with the business's own interceptors:

import axios from '@ohos/axios';
import { applyFTAxiosTrack } from '@guancecloud/ft_sdk/Index';

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;
});

Execution Order Description:

  • In @ohos/axios compat mode, request interceptors behave as: later registered, executed first
  • This means multiple request interceptors can coexist, but the registration order affects whether FT sees the request headers "before modification" or "after modification"
  • If you want FT to capture the final request headers after the business has added authentication, signatures, etc., the recommended order is: first applyFTAxiosTrack(client), then register the business request interceptor
  • With the above order, the business request interceptor will execute first, and FT will then execute and read the final headers
  • If you want to adjust the order, simply change the registration order; for example, if you register the business interceptor first and then call applyFTAxiosTrack(client), FT will execute first and the business interceptor will execute later

@ohos/axios 2.2.8 and above

For @ohos/axios 2.2.8 and above, it is recommended to use the interceptorChain from @guancecloud/ft_sdk_ext for FT automatic tracing:

import axios from '@ohos/axios';
import {
  createFTHttpInterceptorChain,
  applyFTAxiosChainMethodBridge
} from '@guancecloud/ft_sdk_ext/Index';

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

applyFTAxiosChainMethodBridge(client);

const response = await client.post('https://api.example.com/data', {
  source: 'axios',
  message: 'ft auto track'
});

If there are multiple interceptors coexisting, manual adjustment of execution order is needed, or if you need to integrate with business custom interceptors, refer to the content in HTTP Interceptor Integration and combine HttpInitialRequestInterceptor and HttpFinalResponseInterceptor as needed.

If passing per request, you can also write like this:

import axios from '@ohos/axios';
import { createFTHttpInterceptorChain } from '@guancecloud/ft_sdk_ext/Index';

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

Notes:

  • It is recommended to inject interceptorChain uniformly when creating the Axios instance and call applyFTAxiosChainMethodBridge(client) to avoid missing the bridge, which could cause inaccurate Resource method recording.
  • The interceptorChain mode depends on @guancecloud/ft_sdk_ext (the local HAR file is still named ft_sdk_ext.har), and requires HarmonyOS API 22+
  • To automatically inject Trace Headers, in addition to creating the interceptor chain, enable setEnableAutoTrace(true) in the Trace configuration
  • To automatically collect Resource, still enable setEnableTraceUserResource(true) in the RUM configuration
  • If the caller already has custom HTTP/Axios interceptors, it is recommended to directly use HttpInitialRequestInterceptor, HttpFinalResponseInterceptor to manually assemble the order, avoiding rewriting url, method, or headers after FT automatic tracing
  • The SDK only provides interceptors and default configuration factory functions; the creation and lifecycle of RCP Session are managed by the business itself
  • If the business directly uses rcp.createSession() to create a Session, it needs to add the SDK's interceptors manually, otherwise requests will not be automatically traced
  • If the business directly uses http.createHttp() or @ohos/axios, it needs to explicitly mount applyFTHttpTrack(), applyFTAxiosTrack(), createFTHttpInterceptorChain(); Axios interceptorChain mode also needs to call applyFTAxiosChainMethodBridge(client)

Resource Performance Metrics Description

The HarmonyOS SDK obtains network request performance metrics through the RCP (Remote Call Protocol) TimeInfo interface, including DNS, TCP, SSL, TTFB (Time To First Byte), etc.

TTFB Calculation Description:

  • HarmonyOS TTFB: Calculated using startTransferTimeMs - preTransferTimeMs, includes server processing time, network transmission time, and response header reception time
  • Android TTFB: Only represents response header reception time, usually very short

  • DNS Time: nameLookupTimeMs

  • TCP Time: connectTimeMs - nameLookupTimeMs
  • SSL Time: tlsHandshakeTimeMs - connectTimeMs
  • TTFB: startTransferTimeMs - preTransferTimeMs
  • Download Time: totalTimeMs - startTransferTimeMs

Due to the limitations of the HarmonyOS RCP API, preTransferTimeMs is almost equal to the SSL completion time, so HarmonyOS's TTFB will include server processing time, which typically makes it larger than Android's. This is an expected platform behavior difference and not a SDK implementation issue.

Feedback

Is this page helpful? ×