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 HeadersRCPResourceInterceptor: Automatically collectsResourcedata and performance metricscreateFTRCPInterceptors(): Returns a default list of RCP interceptors, convenient for merging with customSessionConfigurationcreateFTRCPTrackConfig(): Quickly generates aSessionConfigurationwith default interceptors andTracingConfiguration
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:
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 onresponse.timeInfoto calculate performance metrics such as DNS, TCP, SSL, TTFB, and download timeincomingHeader/outgoingHeader: Optional, enabled by defaultincomingData/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_sdkinoh-package.json5ft_sdk_ext.har, and declared as@guancecloud/ft_sdk_extinoh-package.json5- If
ft_sdk_ext.haris installed via a local HAR, addoverrides["@guancecloud/ft_sdk"] = "file:./libs/ft_sdk.har"in the rootoh-package.json5to 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 startsResourceHttpFinalResponseInterceptor: SupplementsResourcedata at the end of the response and ends collectioncreateFTHttpInterceptorChain(): Creates a reusablehttp.HttpInterceptorChainapplyFTHttpTrack(): Mounts the default interceptor chain directly to a singlehttp.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.NetworkKitin API 22+. For lower API versions, use RCP or Axios compatibility mode instead - In the HTTP interceptor mode using
http.createHttp()directly,HttpRequestContextcurrently cannot stably obtain the actual request method, so themethodinResourcemay be recorded asUNKNOWN - If the business uses
@ohos/axiosininterceptorChainmode, it is recommended to additionally mountapplyFTAxiosChainMethodBridge()to bridge the actual method, url, and headers from axios - The interceptor callback of
@kit.NetworkKitdoes not currently expose detailed timing at the RCPtimeInfolevel, so onlyresourceLoadwill be supplemented
Axios Integration¶
If the business uses @ohos/axios, automatic tracing can be integrated as follows:
@guancecloud/ft_sdk: Based on Axiosrequest/response interceptorscompatibility mode@guancecloud/ft_sdk_ext: Since0.1.14-alpha03, provides an enhanced mode based oninterceptorChain
@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/axioscompat mode,requestinterceptors behave as: later registered, executed first - This means multiple
request interceptorscan 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 businessrequest interceptor - With the above order, the business
request interceptorwill execute first, and FT will then execute and read the finalheaders - 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
interceptorChainuniformly when creating the Axios instance and callapplyFTAxiosChainMethodBridge(client)to avoid missing the bridge, which could cause inaccurateResourcemethod recording. - The
interceptorChainmode depends on@guancecloud/ft_sdk_ext(the local HAR file is still namedft_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 enablesetEnableTraceUserResource(true)in the RUM configuration - If the caller already has custom HTTP/Axios interceptors, it is recommended to directly use
HttpInitialRequestInterceptor,HttpFinalResponseInterceptorto manually assemble the order, avoiding rewritingurl,method, orheadersafter 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 mountapplyFTHttpTrack(),applyFTAxiosTrack(),createFTHttpInterceptorChain(); AxiosinterceptorChainmode also needs to callapplyFTAxiosChainMethodBridge(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.