HarmonyOS Application Integration¶
Collect metrics data from HarmonyOS applications and analyze application performance through visualization.
Prerequisites¶
Note: If you have activated the RUM Headless service, the prerequisites have been automatically configured for you. You can directly integrate the application.
- Install DataKit;
- Configure the RUM Collector;
- Configure DataKit to be accessible via the public network and install the IP geolocation database.
Application Integration¶
- Navigate to RUM > Create Application > HarmonyOS;
- Enter the Application Name and Application ID;
- Choose the application integration method:
- Public DataWay: Directly receives RUM data, no need to install the DataKit collector.
- Local Environment Deployment: Receives RUM data after meeting the prerequisites.
Installation¶
- Download the latest
ft_sdk.harfile: Download Link
HAR Package Dependency Configuration:
According to the HarmonyOS official documentation (HAR Package Import Guide), the HAR file should be placed in the libs directory of the project.
Add the dependency in the project's oh-package.json5:
Note:
- Ensure the
ft_sdk.harfile is in thelibs/directory (create the directory if it doesn't exist) - If the HAR file is in the root directory, move it to the
libs/directory
Then run:
After installation, the HAR package will be installed in the oh_modules/ft_sdk/ directory.
Import Instructions:
Import using the following method based on the actual structure of the HAR package:
import { FTSDK } from 'ft_sdk/src/main/ets/components/FTSDK';
import { FTSDKConfig, FTRUMConfig, FTLoggerConfig } from 'ft_sdk/src/main/ets/components/Configs';
Permission Description:
The SDK module automatically includes the following permission declarations. Users do not need to configure them manually. These permissions take effect automatically when the application integrates the SDK:
| Permission Name | Purpose Description |
|---|---|
ohos.permission.INTERNET |
Network access permission, used for data reporting and network request tracing |
ohos.permission.GET_WIFI_INFO |
Get WiFi information, used for network type detection and signal strength collection |
ohos.permission.GET_NETWORK_INFO |
Get network information, used for network status monitoring and type identification |
Initialization¶
Initialize the SDK in EntryAbility.ets:
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { FTSDK } from 'ft_sdk/src/main/ets/components/FTSDK';
import { FTSDKConfig, FTRUMConfig, FTLoggerConfig } from 'ft_sdk/src/main/ets/components/Configs';
import { EnvType } from 'ft_sdk/src/main/ets/components/enum/Enums';
import { TraceType } from 'ft_sdk/src/main/ets/components/trace/TraceType';
const DOMAIN = 0x0000;
export default class EntryAbility extends UIAbility {
async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
await this.initFTSDK();
}
private async initFTSDK(): Promise<void> {
try {
// Local environment deployment (Datakit)
// const sdkConfig = FTSDKConfig.builder(datakitUrl);
// Public DataWay
const sdkConfig = FTSDKConfig.builder(datawayUrl, clientToken)
.setDebug(true)
.setServiceName('Your-App-Name')
.setEnv(EnvType.PROD); // Or use string: .setEnv('prod');
// dbCacheLimit defaults to 100MB, call .setDbCacheLimit(sizeInBytes) to customize
// rumCacheLimitCount defaults to 100000, call .setRumCacheLimitCount(count) to customize
// logCacheLimitCount defaults to 5000, call .setLogCacheLimitCount(count) to customize
await FTSDK.install(sdkConfig, this.context);
const rumConfig = new FTRUMConfig()
.setSamplingRate(1.0)
.setRumAppId('your-app-id')
.setEnableTraceUserAction(true)
.setEnableTraceUserView(true)
.setEnableTraceUserResource(true)
.setEnableTrackAppANR(true);
await FTSDK.installRUMConfig(rumConfig);
const logConfig = new FTLoggerConfig()
.setSamplingRate(1.0)
.setEnableCustomLog(true)
.setLogCacheLimitCount(10000)
.setEnableLinkRumData(true);
FTSDK.installLogConfig(logConfig);
hilog.info(DOMAIN, 'FTSDK', 'FT SDK initialized successfully');
} catch (error) {
const errorObj: object = error as object;
hilog.error(DOMAIN, 'FTSDK', `Failed to initialize FT SDK: ${JSON.stringify(errorObj)}`);
}
}
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'FTSDK', `loadContent failed: ${err.code}`);
return;
}
hilog.info(DOMAIN, 'FTSDK', 'Succeeded in loading the content.');
});
}
}
| Field | Type | Required | Description |
|---|---|---|---|
| datakitUrl | string | Yes | Local environment deployment (Datakit) reporting URL address, example: http://10.0.0.1:9529, default port 9529, the device installing the SDK must be able to access this address. Note: Choose either datakitUrl or datawayUrl configuration |
| datawayUrl | string | Yes | Public Dataway reporting URL address, obtained from the [RUM] application, example: https://open.dataway.url, the device installing the SDK must be able to access this address. Note: Choose either datakitUrl or datawayUrl configuration |
| clientToken | string | Yes | Authentication token, needs to be configured together with datawayUrl |
| debug | boolean | No | Sets whether to allow printing Debug logs, default false |
| env | string | EnvType | No | Environment, default prod. Can use EnvType enum (EnvType.PROD, EnvType.PRE, EnvType.GRAY, EnvType.COMMON, EnvType.LOCAL) or strings (e.g., "prod", "pre", etc.) |
| serviceName | string | No | Sets the name of the business or service it belongs to. Default: df_rum_harmonyos |
| autoSync | boolean | No | Whether to automatically sync data to the server after collection. Default true. When false, use the flushSyncData method to manage data synchronization manually. |
| syncPageSize | number | No | Sets the number of entries for sync requests. Range [5, ). Note: A larger number of request entries means data synchronization consumes more computing resources. Default is 10. |
| dbCacheLimit | number | No | DB cache limit size. Range [30MB,), default 100MB, unit byte. |
| rumCacheLimitCount | number | No | RUM data cache count limit, default 100000, minimum 10000. |
| logCacheLimitCount | number | No | Log data cache count limit, default 5000, minimum 1000. |
| dbCacheDiscard | string | No | Sets the data discard rule in the database. Discard policy: discard discard new data (default), discardOldest discard old data. |
RUM Configuration¶
const rumConfig = new FTRUMConfig()
.setRumAppId('your-app-id')
.setSamplingRate(1.0)
.setSessionErrorSampleRate(1.0) // Set error sampling rate
.setEnableTraceUserAction(true)
.setEnableTraceUserView(true)
.setEnableTraceUserResource(true)
.setEnableTrackAppANR(true)
.setEnableTraceWebView(true); // Enable WebView data collection
await 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 (100% collection). |
| setSessionErrorSampleRate | number | No | Error sampling rate, range [0.0, 1.0], default 0.0. When a session is not sampled by setSamplingRate, if an error occurs in the session, data from 1 minute before the error can be collected. 0 means no collection, 1 means full collection. |
| setEnableTraceUserAction | boolean | No | Whether to enable automatic action tracking (UI click events), default false. |
| setEnableTraceUserView | boolean | No | Whether to enable page tracking, default false. |
| setEnableTraceUserResource | boolean | No | Whether to enable resource tracking (HTTP requests), default false. |
| setEnableTrackAppANR | boolean | No | Whether to enable ANR monitoring, default false. |
| setEnableTraceWebView | boolean | No | Whether to enable WebView data collection, default false. |
| setRumCacheLimitCount | number | No | RUM data cache count limit, default 100000, minimum 10000. |
Log Configuration¶
import { Status } from 'ft_sdk/src/main/ets/components/bean/Status';
const logConfig = new FTLoggerConfig()
.setSamplingRate(1.0)
.setEnableCustomLog(true)
.setLogCacheLimitCount(10000)
.setLogLevelFiltersString([
Status.ERROR.name,
Status.WARNING.name,
Status.INFO.name,
Status.DEBUG.name
])
.setEnableLinkRumData(true);
FTSDK.installLogConfig(logConfig);
| Method | Type | Required | Description |
|---|---|---|---|
| setSamplingRate | number | No | Log sampling rate, range [0.0, 1.0], default 1.0 (100% collection). |
| setEnableCustomLog | boolean | No | Whether to enable custom logs, default false. |
| setLogCacheLimitCount | number | No | Log data cache count limit, default 5000, minimum 1000. |
| setLogLevelFiltersString | string[] | No | Log level filter, options: ERROR, WARNING, INFO, DEBUG. |
| setEnableLinkRumData | boolean | No | Whether to associate RUM data, default false. |
Trace Configuration¶
import { TraceType } from 'ft_sdk/src/main/ets/components/trace/TraceType';
const traceConfig = new FTTraceConfig()
.setSamplingRate(0.8)
.setTraceType(TraceType.DDTRACE)
.setEnableAutoTrace(true)
.setEnableLinkRUMData(true);
FTSDK.installTraceConfig(traceConfig);
| Method | Type | Required | Description |
|---|---|---|---|
| setSamplingRate | number | No | Set collection rate, value range [0,1], 0 means no collection, 1 means full collection, default value 1. |
| setTraceType | TraceType | No | Set the type of trace, default is DDTRACE. Currently supports ZIPKIN_MULTI_HEADER, ZIPKIN_SINGLE_HEADER, JAEGER, DDTRACE, SKYWALKING, TRACEPARENT (W3C). If integrating OpenTelemetry, please check the supported types and agent related configurations when selecting the corresponding trace type. |
| setEnableLinkRUMData | boolean | No | Whether to associate with RUM data, default false. |
| setEnableAutoTrace | boolean | No | Set whether to enable automatic http trace, currently supports automatic tracing of RCP, default false. |
| setHeaderHandler | HeaderHandler | No | Set global FTTraceHeaderHandler, not set by default, used for custom Trace Header. |
RUM User Data Tracking¶
View¶
Usage¶
startView(viewName: string, property?: Record<string, object>): void
stopView(property?: Record<string, object>): void
updateLoadTime(loadTime: number): void
Automatic Tracking:
After enabling enableTraceUserView in the RUM configuration, the SDK will automatically track page navigation, including:
- Route navigation (router.pushUrl, router.replaceUrl, etc.)
- Navigation component switching.
Code Example¶
import { FTRUMGlobalManager } from 'ft_sdk/src/main/ets/components/rum/FTRUMGlobalManager';
// Scenario 1
FTRUMGlobalManager.getInstance().startView('ProductPage');
// Scenario 2: Dynamic parameters
// PropertyWrapper class must be defined (ArkTS requirement)
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);
// Scenario 1
FTRUMGlobalManager.getInstance().stopView();
// Scenario 2: Dynamic parameters
const stopViewProperty = new ViewProperty();
stopViewProperty.set('view_duration', 1000);
FTRUMGlobalManager.getInstance().stopView(stopViewProperty.toObject());
Notes:
- Automatic tracking requires enabling
enableTraceUserView(true)in the RUM configuration. - Automatic tracking will automatically call
startViewandstopViewduring page transitions; manual calls are not needed. - Manual calls to
startViewandstopViewcan still be used in scenarios like conditional rendering. - Page names are automatically extracted from route paths or Navigation component names.
Action¶
Usage¶
addAction(actionName: string, actionType: string, duration: number, startTime: number, property?: Record<string, object>): void
Code Example¶
import { FTRUMGlobalManager } from 'ft_sdk/src/main/ets/components/rum/FTRUMGlobalManager';
// Scenario 1: Direct completion
FTRUMGlobalManager.getInstance().addAction('buy_button_click', 'click');
// Scenario 2: Dynamic parameters
// PropertyWrapper class must be defined (ArkTS requirement)
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());
// Scenario 3: Start Action (includes duration calculation mechanism)
FTRUMGlobalManager.getInstance().startAction('buy_button_click', 'click');
// ... Perform operation ...
FTRUMGlobalManager.getInstance().stopAction();
Automatic Tracking:
After enabling enableTraceUserAction in the RUM configuration, the SDK will automatically track click events on UI components. Add customProperty to Button components to get the button text:
Button('Buy Now')
.id('buy-btn')
.customProperty('buy-btn', 'Buy Now')
.onClick(() => {
// Click event will be tracked automatically
})
Resource¶
Usage¶
startResource(resourceId: string, property?: Record<string, object>): void
stopResource(resourceId: string): void
addResource(resourceId: string, resourceParams: ResourceParams, netStatusBean?: NetStatusBean): void
Automatic Tracking:
After enabling enableTraceUserResource in the RUM configuration, the SDK will automatically track HTTP requests sent via RCP.
Code Example¶
import { FTRUMGlobalManager } from 'ft_sdk/src/main/ets/components/rum/FTRUMGlobalManager';
import { ResourceParams } from 'ft_sdk/src/main/ets/components/rum/bean/ResourceParams';
import { NetStatusBean } from 'ft_sdk/src/main/ets/components/rum/bean/NetStatusBean';
const resourceId = 'https://api.example.com/data';
// Start resource tracking
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);
// End resource tracking and add resource data
FTRUMGlobalManager.getInstance().stopResource(resourceId);
FTRUMGlobalManager.getInstance().addResource(resourceId, resourceParams, netStatusBean);
RCP Automatic Tracking Integration¶
After enabling enableTraceUserResource in the RUM configuration, the SDK will automatically create an RCP Session with interceptors. HTTP requests sent using this Session will be automatically tracked, and performance metrics (DNS, TCP, SSL, TTFB, etc.) will be collected.
Usage:
import { FTHttpAutoTrack } from 'ft_sdk/src/main/ets/components/network/FTHttpAutoTrack';
import { rcp } from '@kit.RemoteCommunicationKit';
// Get the default Session (already configured with interceptors)
const session = FTHttpAutoTrack.getInstance().getDefaultSession();
if (session) {
// GET request
const request = new rcp.Request('https://api.example.com/data', 'GET');
const response = await session.fetch(request);
// POST request
const headers: rcp.RequestHeaders = { 'Content-Type': 'application/json' };
const postRequest = new rcp.Request('https://api.example.com/data', 'POST', headers, { name: 'test' });
const postResponse = await session.fetch(postRequest);
}
Notes:
- Only requests sent through the Session obtained via
getDefaultSession()will be automatically tracked. - If using a Session created directly with
rcp.createSession(), interceptors need to be added manually; use thecreateSessionWithInterceptors(config)method. - Ensure
enableTraceUserResourceis enabled in the RUM configuration, otherwisegetDefaultSession()will returnnull.
Resource Performance Metrics Explanation¶
The HarmonyOS SDK obtains network request performance metrics (including DNS, TCP, SSL, TTFB (Time To First Byte), etc.) through the RCP (Remote Call Protocol) TimeInfo interface.
TTFB Calculation Explanation:
- 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, a few milliseconds).
Due to limitations of the HarmonyOS RCP API, preTransferTimeMs is almost equal to the SSL completion time. Therefore, HarmonyOS's TTFB includes server processing time, causing its value to typically be larger than Android's TTFB (tens to hundreds of milliseconds). This is an expected behavioral difference, not an SDK implementation issue.
Other Performance Metrics:
- DNS Time:
nameLookupTimeMs(DNS resolution time) - TCP Time:
connectTimeMs - nameLookupTimeMs(TCP connection establishment time) - SSL Time:
tlsHandshakeTimeMs - connectTimeMs(SSL/TLS handshake time) - Transfer Time:
totalTimeMs - tlsHandshakeTimeMs(TTFB + download time) - Download Time:
totalTimeMs - startTransferTimeMs(response body download time)
Image Resource Loading¶
Important Note: If using the system's Image component to load network URLs directly (e.g., Image('https://example.com/image.jpg')), the image loading process cannot be monitored by RUM because the internal network requests used by the system Image component are not intercepted by the SDK.
When loading network images, to ensure the image loading can be tracked as a Resource event by RUM, you need to download the image manually using RCP:
Download Image Using RCP
Use the Session obtained from FTHttpAutoTrack.getDefaultSession() to download the image. The SDK will automatically track the image loading process:
import { FTHttpAutoTrack } from 'ft_sdk/src/main/ets/components/network/FTHttpAutoTrack';
import { rcp } from '@kit.RemoteCommunicationKit';
import { image } from '@kit.ImageKit';
async function loadImageFromNetwork(imageUrl: string): Promise<image.PixelMap | null> {
const httpAutoTrack = FTHttpAutoTrack.getInstance();
const session = httpAutoTrack.getDefaultSession();
if (!session) {
console.error('RCP session is not available. Make sure HTTP Auto Track is enabled.');
return null;
}
try {
const request = new rcp.Request(imageUrl, 'GET');
const response = await session.fetch(request);
if (response.statusCode < 200 || response.statusCode >= 300) {
console.error(`Failed to load image: HTTP ${response.statusCode}`);
return null;
}
const arrayBuffer = response.body as ArrayBuffer;
if (!arrayBuffer) {
console.error('Response body is not ArrayBuffer');
return null;
}
// Convert ArrayBuffer to PixelMap
const imageSource = image.createImageSource(arrayBuffer);
const pixelMap = await imageSource.createPixelMap();
return pixelMap;
} catch (error) {
console.error(`Error loading image: ${error}`);
return null;
}
}
// Use in component
@Component
export struct MyImageComponent {
@State imageData: image.PixelMap | null = null;
aboutToAppear() {
loadImageFromNetwork('https://example.com/image.jpg').then((pixelMap) => {
if (pixelMap) {
this.imageData = pixelMap;
}
});
}
build() {
if (this.imageData) {
Image(this.imageData)
} else {
Image($r('app.media.placeholder'))
}
}
}
Notes:
- ⚠️ Do not use the system
Imagecomponent to load network URLs directly (e.g.,Image('https://example.com/image.jpg')), as this method cannot be monitored by RUM. - Ensure
enableTraceUserResourceis enabled in the RUM configuration, otherwisegetDefaultSession()will returnnull. - To correctly identify the image type in Action tracking, add
.customProperty('__component_type__', 'Image').
Tip: For a more complete image loading solution (including caching, loading status, etc.), refer to the NetworkImage component implementation in the Demo project.
Error¶
Usage¶
addError(log: string, message: string, errorType: ErrorType, appState: AppState, property?: Record<string, object>): void
Code Example¶
import { FTRUMGlobalManager } from 'ft_sdk/src/main/ets/components/rum';
import { ErrorType, AppState } from 'ft_sdk/src/main/ets/components/rum';
const rumManager = FTRUMGlobalManager.getInstance();
// Option 1: Use ErrorProperty class (recommended for ArkTS)
// Note: ErrorProperty is a helper class, you can create your own or use Map
// PropertyWrapper class must be defined outside the method (ArkTS requirement)
class PropertyWrapper {
value: string | number | boolean;
constructor(v: string | number | boolean) {
this.value = v;
}
}
class ErrorProperty {
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) => {
// Create wrapper object using class (ArkTS requirement)
result[key] = new PropertyWrapper(value) as object;
});
return result;
}
}
const property = new ErrorProperty();
property.set('error_code', 'ERR_001');
property.set('user_id', 'test_user');
rumManager.addError(
'Error stack trace:\n at ProductPage.onClick\n at Button.onClick',
'Failed to load product data',
ErrorType.CUSTOM,
AppState.RUN,
property.toObject()
);
// Option 2: Pass null if no properties needed
rumManager.addError(
'Error stack trace:\n at ProductPage.onClick\n at Button.onClick',
'Failed to load product data',
ErrorType.CUSTOM,
AppState.RUN
);
Automatic Tracking:
After enabling enableTrackAppCrash and enableTrackAppANR in the RUM configuration, the SDK will automatically capture application crash and ANR events.
LongTask¶
Usage¶
addLongTask(taskName: string, duration: number, property?: Record<string, string | number | boolean>): void
Code Example¶
import { FTRUMGlobalManager } from 'ft_sdk/src/main/ets/components/rum';
const rumManager = FTRUMGlobalManager.getInstance();
// Option 1: Use Map for properties (recommended for ArkTS)
const property = new Map<string, string | number | boolean>();
property.set('task_type', 'data_processing');
property.set('data_size', 10000);
// Convert Map to Record (ArkTS compatible)
const propertyRecord: Record<string, string | number | boolean> = {} as Record<string, string | number | boolean>;
property.forEach((value, key) => {
propertyRecord[key] = value;
});
const duration = 500000000;
rumManager.addLongTask('Data Processing', duration, propertyRecord);
// Option 2: Pass empty object or omit property parameter
rumManager.addLongTask('Data Processing', duration);
Logging Functionality¶
Custom Logs¶
Usage¶
FTLogger.getInstance().logBackground(content: string, status: Status): void
FTLogger.getInstance().logBackground(content: string, status: Status, property?: Map<string, object>): void
FTLogger.getInstance().logBackground(content: string, status: string, property?: Map<string, object>): void
Code Example¶
import { FTLogger } from 'ft_sdk/src/main/ets/components/log/FTLogger';
import { Status } from 'ft_sdk/src/main/ets/components/bean/Status';
// Upload single log
FTLogger.getInstance().logBackground('Failed to load product data', Status.ERROR);
// Pass parameters
const property = new Map<string, object>();
property.set('error_code', 'ERR_001');
property.set('user_id', 'test_user');
FTLogger.getInstance().logBackground('Network request timeout', Status.WARN, property);
// Use string status
FTLogger.getInstance().logBackground('User logged in successfully', 'info');
Note:
- FTLogger is the public logging API provided to external users.
- To enable SDK internal debug logs, use the FTSDKConfig.setDebug(true) configuration.
Tracer Network Tracing¶
After enabling enableAutoTrace in the Trace Configuration, the SDK will automatically inject trace headers into HTTP requests. You can also manually use FTTraceManager to add Propagation Header to HTTP requests.
Automatic Tracing¶
After enabling enableAutoTrace in the Trace configuration, the SDK will automatically inject Trace Headers into HTTP requests sent via RCP:
import http from '@ohos.net.http';
const httpRequest = http.createHttp();
const response = await httpRequest.request('https://api.example.com/data', {
method: http.RequestMethod.GET
});
// Trace Headers are automatically injected into the request
Manually Get Trace Header¶
If using other network frameworks, you can manually get the Trace Header and add it to the request:
import { FTTraceManager } from 'ft_sdk/src/main/ets/components/trace/FTTraceManager';
import http from '@ohos.net.http';
const url = 'https://api.example.com/data';
const resourceId = 'unique-resource-id'; // Unique ID to identify the resource
// Get trace header parameters
const traceHeaders: Record<string, string> = FTTraceManager.getInstance().getTraceHeader(resourceId, url);
// Add Trace Headers to the request
const httpRequest = http.createHttp();
const response = await httpRequest.request(url, {
method: http.RequestMethod.GET,
header: traceHeaders
});
Trace Types¶
| Trace Type | Protocol | Main Headers |
|---|---|---|
DDTRACE |
DataDog Trace | x-datadog-trace-id, x-datadog-parent-id, x-datadog-origin, x-datadog-sampling-priority |
ZIPKIN_MULTI_HEADER |
Zipkin Multi-Header | X-B3-TraceId, X-B3-SpanId, X-B3-ParentSpanId, X-B3-Sampled |
ZIPKIN_SINGLE_HEADER |
Zipkin Single-Header (b3) | b3 |
JAEGER |
Jaeger | uber-trace-id |
TRACEPARENT |
W3C Trace Context | traceparent, tracestate |
SKYWALKING |
SkyWalking | sw8 |
User Data Binding¶
Usage¶
/**
* Bind user information (only user ID)
* @param id User ID
*/
static bindRumUserDataById(id: string): void
/**
* Bind user information (complete user data)
* @param userData User data object
*/
static async bindRumUserData(userData: UserData): Promise<void>
/**
* Unbind user information
*/
static async unbindRumUserData(): Promise<void>
UserData¶
| Method Name | Meaning | Required | Note |
|---|---|---|---|
| setId | Set user ID | No | |
| setName | Set username | No | |
| setEmail | Set email | No | |
| setExts | Set user extensions | No | Add rules please refer to here |
Code Example¶
import { FTSDK } from 'ft_sdk/src/main/ets/components/FTSDK';
import { UserData } from 'ft_sdk/src/main/ets/components/rum/bean/UserData';
// Method 1: Only bind user ID (recommended for quick binding)
FTSDK.bindRumUserDataById('user_001');
// Method 2: Bind complete user information (recommended for scenarios requiring more user information)
const userData = new UserData();
userData.setId('user_001');
userData.setName('test.user');
userData.setEmail('test@mail.com');
const exts: Record<string, string> = {
'ft_key': 'ft_value',
'user_type': 'vip'
};
userData.setExts(exts);
await FTSDK.bindRumUserData(userData);
// Unbind user information (call when user logs out)
await FTSDK.unbindRumUserData();
Add Custom Tags¶
import { FTSDK } from 'ft_sdk/src/main/ets/components/FTSDK';
const globalContext = new Map<string, string>();
globalContext.set('platform', 'harmonyos');
globalContext.set('version', '1.0.0');
FTSDK.appendGlobalContext(globalContext);
const rumGlobalContext = new Map<string, string>();
rumGlobalContext.set('user_type', 'vip');
rumGlobalContext.set('channel', 'official');
FTSDK.appendRUMGlobalContext(rumGlobalContext);
Manually Sync Data¶
When configuring autoSync to false, you need to manually trigger data synchronization:
Clear SDK Cache Data¶
Note: clearAllData() will delete all unsynced cached data, including:
- All data in the sync data table (sync_data_flat)
- All data in the RUM view data table (rum_view)
- All data in the RUM action data table (rum_action)
WebView Integration¶
After enabling enableTraceWebView in the RUM configuration, the SDK will automatically collect RUM data from within the WebView.
Usage in WebView Page
import { FTWebViewHandler } from 'ft_sdk/src/main/ets/components/web/FTWebViewHandler';
import { webview } from '@kit.ArkWeb';
@Component
export struct MyWebViewPage {
@State webController: webview.WebviewController = new webview.WebviewController();
private webViewHandler: FTWebViewHandler = new FTWebViewHandler();
aboutToAppear() {
// Only need to pass webController, configuration will be read from the RUM configuration at the application entry
this.webViewHandler.setWebView(this.webController);
}
aboutToDisappear() {
this.webViewHandler.clearWebController();
}
build() {
Web({
src: 'https://example.com',
controller: this.webController
})
.javaScriptAccess(true)
.javaScriptProxy(this.webViewHandler.getJavaScriptProxy(this.webController))
}
}
```## Advanced Configuration
### Custom HTTP Headers
To add custom headers to all outgoing HTTP requests (including those intercepted by the SDK), use the `appendGlobalContext` method:
```typescript
import { FTSDK } from 'ft_sdk/src/main/ets/components/FTSDK';
const customHeaders = new Map<string, string>();
customHeaders.set('X-Custom-Header', 'custom-value');
customHeaders.set('Authorization', 'Bearer your-token');
FTSDK.appendGlobalContext(customHeaders);
Custom Resource Tracking¶
For non-HTTP resources or custom resource tracking, use the manual resource tracking methods:
import { FTRUMGlobalManager } from 'ft_sdk/src/main/ets/components/rum/FTRUMGlobalManager';
import { ResourceParams } from 'ft_sdk/src/main/ets/components/rum/bean/ResourceParams';
const resourceId = 'custom-resource-001';
// Start tracking custom resource
FTRUMGlobalManager.getInstance().startResource(resourceId);
// ... Perform custom operation ...
// Create resource parameters
const resourceParams = new ResourceParams();
resourceParams.setUrl('custom://operation');
resourceParams.setResourceStatus(200); // Success status
resourceParams.setResponseContentLength(1024);
resourceParams.resourceType = 'custom';
// End tracking and add resource data
FTRUMGlobalManager.getInstance().stopResource(resourceId);
FTRUMGlobalManager.getInstance().addResource(resourceId, resourceParams);
Performance Monitoring¶
The SDK automatically collects performance metrics including:
- App Start Time: Cold start, warm start durations
- FPS (Frames Per Second): UI rendering performance
- Memory Usage: Application memory consumption
- CPU Usage: Application CPU utilization
- Battery Impact: Battery consumption metrics
These metrics are automatically collected and don't require additional configuration.
Network Quality Monitoring¶
The SDK monitors network quality including:
- Network Type: WiFi, 4G, 5G, etc.
- Signal Strength: Network signal quality
- Connection Stability: Network connection stability
- Latency: Network response times
Error Tracking Enhancements¶
For enhanced error tracking, you can add custom error contexts:
import { FTRUMGlobalManager } from 'ft_sdk/src/main/ets/components/rum';
import { ErrorType, AppState } from 'ft_sdk/src/main/ets/components/rum';
const errorContext = new Map<string, string>();
errorContext.set('screen_state', 'active');
errorContext.set('network_status', 'wifi');
errorContext.set('battery_level', '80%');
FTRUMGlobalManager.getInstance().addError(
'Detailed error stack trace',
'Custom error message',
ErrorType.CUSTOM,
AppState.RUN,
errorContext
);
Best Practices¶
1. Optimal Initialization Timing¶
Initialize the SDK as early as possible in your application lifecycle:
// In EntryAbility.ets
async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
// Initialize SDK before any other operations
await this.initFTSDK();
// Continue with other initialization
await this.initOtherServices();
}
2. Proper Error Handling¶
Always wrap SDK operations in try-catch blocks:
try {
await FTSDK.install(sdkConfig, this.context);
} catch (error) {
hilog.error(DOMAIN, 'FTSDK', `SDK installation failed: ${error.message}`);
// Continue with app initialization even if SDK fails
}
3. Memory Management¶
For long-running applications, periodically clear old data:
// Clear data older than 7 days
const sevenDaysAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);
FTSDK.clearDataOlderThan(sevenDaysAgo);
4. Battery Optimization¶
The SDK is optimized for battery efficiency, but you can further optimize:
// Reduce sampling rate for battery-sensitive applications
const rumConfig = new FTRUMConfig()
.setSamplingRate(0.5) // 50% sampling
.setEnableTraceUserResource(false); // Disable resource tracking if not needed
Troubleshooting¶
Common Issues¶
- SDK Not Initializing
- Check network connectivity
- Verify DataKit/DataWay URL accessibility
-
Confirm proper HAR package installation
-
Data Not Reporting
- Check
autoSyncconfiguration - Verify network permissions
-
Confirm RUM App ID is correct
-
Performance Issues
- Reduce sampling rates
- Increase cache limits if experiencing data loss
Debug Mode¶
Enable debug mode for detailed logging:
const sdkConfig = FTSDKConfig.builder(datawayUrl, clientToken)
.setDebug(true) // Enable debug logging
.setServiceName('Your-App-Name');
Support and Resources¶
- Documentation: Guance Documentation
- Community Support: Guance Community Forum
- GitHub Repository: datakit-harmonyos
- Demo Application: Example HarmonyOS App
Compliance and Privacy¶
Data Collection Transparency¶
The SDK is designed with privacy in mind:
- User Consent: Implement user consent mechanisms before data collection
- Data Anonymization: User data is anonymized where possible
- Data Retention: Configurable data retention policies
- GDPR Compliance: Designed to support GDPR requirements
Privacy Configuration¶
To enhance user privacy:
// Disable certain data collection features
const rumConfig = new FTRUMConfig()
.setEnableTraceUserAction(false) // Disable automatic action tracking
.setEnableTraceUserView(false); // Disable automatic view tracking
// Configure data retention
const sdkConfig = FTSDKConfig.builder(datawayUrl, clientToken)
.setDataRetentionDays(30); // Keep data for 30 days
Version Compatibility¶
SDK Version Support¶
| HarmonyOS Version | Minimum SDK Version | Recommended SDK Version |
|---|---|---|
| HarmonyOS 3.0+ | 1.0.0 | Latest |
| HarmonyOS 4.0+ | 1.2.0 | Latest |
Backward Compatibility¶
The SDK maintains backward compatibility within major versions. Always check the release notes for specific version requirements.
Migration Guide¶
From Previous Versions¶
When upgrading from previous versions:
- Backup Configuration: Save your current configuration
- Update HAR Package: Replace the old HAR file with the latest version
- Review API Changes: Check for any deprecated methods
- Test Thoroughly: Test all monitoring features after upgrade
Configuration Migration¶
Example migration from v1.x to v2.x:
// Old configuration (v1.x)
const oldConfig = {
datakitUrl: 'http://localhost:9529',
rumAppId: 'old-app-id'
};
// New configuration (v2.x)
const sdkConfig = FTSDKConfig.builder(datawayUrl, clientToken)
.setServiceName('Your-App-Name')
.setEnv(EnvType.PROD);
const rumConfig = new FTRUMConfig()
.setRumAppId('new-app-id')
.setSamplingRate(1.0);
Performance Considerations¶
Memory Usage¶
The SDK is optimized for minimal memory footprint:
- Typical Memory Usage: < 5MB
- Peak Memory Usage: < 10MB during data sync
- Background Usage: < 2MB when app is in background
Battery Impact¶
Battery impact is minimal:
- Active Monitoring: < 1% battery per hour
- Background Usage: Negligible impact
- Network Usage: Optimized batching reduces radio usage
Network Usage¶
Network usage is optimized through:
- Data Compression: All data is compressed before transmission
- Batching: Multiple events are batched into single requests
- Smart Retry: Intelligent retry mechanisms for failed requests
Customization Options¶
Custom Event Tracking¶
For custom business events:
import { FTRUMGlobalManager } from 'ft_sdk/src/main/ets/components/rum/FTRUMGlobalManager';
// Track custom business events
FTRUMGlobalManager.getInstance().addCustomEvent(
'purchase_completed',
new Map<string, object>([
['amount', 99.99],
['currency', 'USD'],
['product_id', '12345']
])
);
Custom Metrics¶
Track custom performance metrics:
// Track custom performance metrics
FTRUMGlobalManager.getInstance().addMetric(
'custom_operation_duration',
150.5, // Duration in milliseconds
new Map<string, string>([
['operation_type', 'data_processing'],
['complexity', 'high']
])
);
User Flow Analysis¶
Track user navigation flows:
// Start user flow tracking
FTRUMGlobalManager.getInstance().startUserFlow('checkout_flow');
// Add steps to the flow
FTRUMGlobalManager.getInstance().addFlowStep('cart_viewed');
FTRUMGlobalManager.getInstance().addFlowStep('payment_started');
// Complete the flow
FTRUMGlobalManager.getInstance().completeUserFlow('checkout_flow', true); // true for success
Integration Checklist¶
Pre-Integration¶
- Verify HarmonyOS version compatibility
- Obtain RUM App ID from Guance console
- Choose integration method (DataWay or DataKit)
- Configure network permissions
Integration Steps¶
- Download latest HAR package
- Add HAR to libs directory
- Configure oh-package.json5 dependencies
- Initialize SDK in EntryAbility
- Configure RUM, Logger, and Trace settings
- Test basic functionality
Post-Integration¶
- Verify data reporting in Guance console
- Test error tracking functionality
- Validate performance metrics
- Configure alerting and notifications
- Set up dashboards and monitors
Support Matrix¶
Supported Devices¶
| Device Type | Support Level | Notes |
|---|---|---|
| Phones | Full Support | All features available |
| Tablets | Full Support | All features available |
| Smart Screens | Basic Support | Limited performance metrics |
| Wearables | Limited Support | Basic error tracking only |
Regional Support¶
| Region | Data Center | Performance |
|---|---|---|
| China | Optimal | Lowest latency |
| Asia-Pacific | Good | < 200ms latency |
| Europe | Good | < 250ms latency |
| Americas | Good | < 300ms latency |
Security Features¶
Data Encryption¶
All data is encrypted in transit:
- TLS 1.2+: All network communication uses TLS encryption
- Data Encryption: Payload data is additionally encrypted
- Secure Storage: Local data storage is encrypted
Authentication¶
- Token-based Auth: Secure client token authentication
- Token Rotation: Support for periodic token rotation
- Revocation: Immediate token revocation support
Compliance Certifications¶
- ISO 27001: Information security management
- SOC 2: Security, availability, processing integrity
- GDPR: General Data Protection Regulation compliance
Cost Optimization¶
Data Sampling¶
Optimize costs through strategic sampling:
// Strategic sampling configuration
const rumConfig = new FTRUMConfig()
.setSamplingRate(0.3) // 30% of sessions
.setSessionErrorSampleRate(1.0); // But sample all errors
const logConfig = new FTLoggerConfig()
.setSamplingRate(0.1) // 10% of logs
.setLogLevelFiltersString([Status.ERROR.name, Status.WARNING.name]); // Only errors and warnings
Data Retention¶
Configure data retention periods:
// Configure data retention
const sdkConfig = FTSDKConfig.builder(datawayUrl, clientToken)
.setDataRetentionDays(7); // Keep data for 7 days
Cost Monitoring¶
Monitor and optimize costs through:
- Usage Dashboards: Monitor data volume in Guance console
- Cost Alerts: Set up alerts for unexpected cost increases
- Optimization Recommendations: Use Guance's cost optimization suggestions
Future Roadmap¶
Upcoming Features¶
- Real User Monitoring: Enhanced real user experience tracking
- Advanced Analytics: Machine learning-powered insights
- Custom Dashboards: More flexible visualization options
- Integration Ecosystem: Expanded third-party integrations
Platform Expansion¶
- HarmonyOS NEXT: Support for upcoming HarmonyOS versions
- Cross-Platform: Unified SDK for multiple platforms
- Edge Computing: Local data processing capabilities
Performance Enhancements¶
- Reduced Footprint: Further memory and battery optimizations
- Faster Initialization: Improved startup performance
- Enhanced Reliability: Better network resilience