Skip to main content
Version: 3.7.0

Application

Integration

I. Pre-configure Bonree SDK Environment

Copy the bonree_sdk-signed.har file to the hars folder in the project root directory.

image-202402021355460101

II. Add bonree_sdk-signed.har

2.1 Add the har package dependency to the dependencies field in the project's oh-package.json5: "@bonree/agent": "file:./hars/bonree_sdk-signed.har"

Example configuration:

{
"modelVersion": "5.0.0",
"description": "Please describe the basic information.",
"dependencies": {
"@bonree/agent": "file:./hars/bonree_sdk-signed.har" // Add this configuration to reference the SDK
},
"devDependencies": {
"@ohos/hypium": "1.0.18",
"@ohos/hamock": "1.0.0"
}
}

image-202402021355460201

2.2 Use the new ohmurl concatenation and parsing method

Modify the useNormalizedOHMUrl in the project-level build-profile.json5 to true. If this configuration item does not exist, please add it manually.

{
"app": {
"products": [
{
"buildOption": {
"strictMode": {
"useNormalizedOHMUrl": true
}
}
}
]
}
}

III. Sync & Rebuild Project

Step 1:

Click [Sync Now] in the upper right corner.

image-202402021355460301

If it doesn't appear, you can use the DevEco Studio shortcut: select Run 'ohpm install'

image-202402021355460302

Step 2:

Rebuild the project to ensure the configuration takes effect.

image-202402021355460303

Access

I. Configure Authorization Information

Check the application's module.json5 configuration file and ensure the following permissions are included as much as possible:

// The following permissions are necessary. For details, refer to the permission description section in the "Privacy Policy":
ohos.permission.INTERNET Send network data
ohos.permission.GET_NETWORK_INFO Get network status information

II. Initialize SDK

Please obtain <#Config Address#> and <#AppID#> from the platform. For the method to obtain them, refer to How to Query AppID and Config Address?. Please contact technical support if you have any questions.

Please add the following code in the onCreate function of the custom AbilityStage in the entry module:

Bonree.withAppID("<#AppID#>")
.withConfigAddress("<#Config Address#>")
.start(this.context.getApplicationContext());

Sample Code:

import { Bonree } from '@bonree/agent'
import AbilityStage from '@ohos.app.ability.AbilityStage'

export default class EntryAbilityStage extends AbilityStage {

onCreate() {
this.initBonreeSdk();
}

private initBonreeSdk() {
Bonree.withAppID("<#AppID#>")
.withConfigAddress("<#Config Address#>")
.start(this.context.getApplicationContext());
}
}

III. Web Data Collection

3.1 Native Application Collection

3.1.1 Collect Web Performance Data

Add BonreeTrace.Web.getScriptItem(controller) and BonreeTrace.Web.onControllerAttachedHilt(controller) in javaScriptOnDocumentStart and onControllerAttached respectively.

import { BonreeTrace } from '@bonree/agent';

Web()
.javaScriptOnDocumentStart([BonreeTrace.Web.getScriptItem(this.controller)]) // this.controller: Must be the WebviewController bound to the current Web
.onControllerAttached(() => {
BonreeTrace.Web.onControllerAttachedHilt(this.controller); // this.controller: Must be the WebviewController bound to the current Web
})

3.1.2 Collect Web Exception Data

Add the corresponding methods in onErrorReceive, onHttpErrorReceive, and onSslErrorEventReceive.

import { BonreeTrace } from '@bonree/agent';

Web()
.onErrorReceive((event) => {
if (!event) {
return;
}
BonreeTrace.Web.onErrorReceive(event.request, event.error, this.controller.getWebId()); // this.controller: Must be the WebviewController bound to the current Web
})
.onHttpErrorReceive((event) => {
if (!event) {
return;
}
BonreeTrace.Web.onHttpErrorReceive(event.request, event.response, this.controller.getWebId()); // this.controller: Must be the WebviewController bound to the current Web
})
.onSslErrorEventReceive((event) => {
BonreeTrace.Web.onSslErrorEventReceive(event.error, this.controller.getWebId()); // this.controller: Must be the WebviewController bound to the current Web
})

3.2 mPaaS Application Collection

3.2.1 Collect Web Performance Data and Exception Data

  1. To collect Web performance data and exception data, you need to initialize the Bonree SDK when the application starts and implement the H5WebClientProvider interface. When calling the interface for registration, you can refer to the example ExampleWebclientProviderImpl class. In actual use, fill in your own implemented class. The example registration code is: HRiver.setProvider(H5WebClientProvider.name, new ExampleWebclientProviderImpl())
  2. To collect Web performance data, you need to add the corresponding method calls in the onPageBegin and onControllerAttached methods: BonreeTrace.Web.getScriptItem(controller) and BonreeTrace.Web.onControllerAttachedHilt(controller).
  3. To collect Web exception data, you need to add the corresponding handling methods in the onErrorReceive, onHttpErrorReceive, and onSslErrorEventReceive methods: BonreeTrace.Web.onErrorReceive(request, error, controller.getWebId()), BonreeTrace.Web.onHttpErrorReceive(request, response, controller.getWebId()), and BonreeTrace.Web.onSslErrorEventReceive(error, controller.getWebId()).
import { BonreeTrace } from "@bonree/agent";
import { H5WebClientProvider, Page } from "@mpaas/hriver";

export class ExampleWebclientProviderImpl extends H5WebClientProvider {
onHttpErrorReceive(page: Page | undefined, request: WebResourceRequest | undefined,
response: WebResourceResponse | undefined): void {
const controller = page?.webcontroller;
if (request && response && controller) {
try {
BonreeTrace.Web.onHttpErrorReceive(request, response, controller.getWebId());
} catch (error) {
}
}
}

onSslErrorEventReceive(page: Page | undefined, handler: SslErrorHandler, error: SslError): void {
const controller = page?.webcontroller;
try {
if (error && controller) {
BonreeTrace.Web.onSslErrorEventReceive(error, controller.getWebId());
}
} catch (error) {
}
}

onErrorReceive(page: Page | undefined, request: WebResourceRequest | undefined,
error: WebResourceError | undefined): boolean {
const controller = page?.webcontroller;
if (request && error && controller) {
try {
BonreeTrace.Web.onErrorReceive(request, error, controller.getWebId());
} catch (error) {
}
}
return false;
}

onPageBegin(page: Page | undefined, url: string | undefined): void {
const controller = page?.webcontroller;
if (controller) {
page.webcontroller?.runJavaScript(BonreeTrace.Web.getScriptItem(controller).script)
}
}

onControllerAttached(page: Page | undefined): void {
const controller = page?.webcontroller;
if (controller) {
BonreeTrace.Web.onControllerAttachedHilt(controller);
}
}
}

IV. View/Launch Data Collection

Important Notes:

  1. View data collection in child windows is temporarily not supported. Please ignore this step for views in child windows.

  2. When using uiObserver.off() and UIObserver.off() series interfaces, you must pass the callback. If callback is not passed when calling off, all registrations will be canceled, causing abnormal SDK data collection.

4.1 Ability Data Collection

Add the @BonreeTrace.InjectAbility decorator to the subclass declaration of UIAbility.

import { BonreeTrace } from '@bonree/agent';

@BonreeTrace.InjectAbility
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {

}

onWindowStageCreate(windowStage: window.WindowStage): void {

}

onForeground(): void {

}

onBackground(): void {

}

onWindowStageDestroy(): void {

}

onDestroy() {

}
}

4.2 AbilityStage Data Collection

Add the @BonreeTrace.InjectStage decorator to the subclass declaration of AbilityStage.

import { BonreeTrace } from '@bonree/agent';

@BonreeTrace.InjectStage
export default class EntryAbilityStage extends AbilityStage {

onCreate() {
}

onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
}
}

4.3 UI Page/Page Data Collection

Add the BonreeTrace.InjectPage(Index) interface call below all custom components decorated with @Entry and pass the current structure. The Page lifecycle functions (aboutToAppear, onPageShow, onPageHide, aboutToDisappear) should be overridden as much as possible; otherwise, it may affect snapshot data collection and performance accuracy.

import { BonreeTrace } from '@bonree/agent';

@Entry
@Component
struct Index {
build() {
}

aboutToAppear(): void {
}

onPageShow(): void {
}

onPageHide(): void {
}

aboutToDisappear(): void {
}
}

BonreeTrace.InjectPage(Index)

V. Network Collection

Currently supports collection for the frameworks: hms.collaboration.rcp, ohos.net.http, ohos.net.webSocket, ohos.net.socket.TCPSocket, ohos/axios, mPaaS/rpc. When collecting for the corresponding network framework, you need to use BonreeTrace to reference these framework classes. The API usage for each network framework is the same as the official documentation. Below are examples for each network collection.

5.1 'hms.collaboration.rcp'

Important Note: There are two mutually exclusive schemes for rcp. When integrating, you can only choose one.

Scheme One:

Only need to add the BonreeTrace prefix reference before the rcp.createSession API.

import { rcp } from '@kit.RemoteCommunicationKit';
import { BonreeTrace } from '@bonree/agent';

// Example 1: No parameters passed
let session1 = BonreeTrace.rcp.createSession(); // Add BonreeTrace prefix reference here

// Example 2: With parameters passed
let session = BonreeTrace.rcp.createSession({}); // Add BonreeTrace prefix reference here

Scheme Two:

Need to add the interceptor AgentRcpInterceptor to sessionConfiguration.interceptors in the call to rcp.createSession(sessionConfiguration).

import { rcp } from '@kit.RemoteCommunicationKit';
import { BonreeTrace } from '@bonree/agent';

// Example
const sessionConfig: rcp.SessionConfiguration = {
// Add the BonreeTrace.rcp.AgentRcpInterceptor interceptor here
interceptors: [new BonreeTrace.rcp.AgentRcpInterceptor()]
};
let session = rcp.createSession(sessionConfig);

5.2 'ohos.net.http'

Important Note: There are two mutually exclusive schemes for http. When integrating, you can only choose one.

Scheme One (Recommended):

Only need to add the BonreeTrace prefix reference before the http.createHttp API.

import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { BonreeTrace } from '@bonree/agent';

let httpRequest = BonreeTrace.http.createHttp(); // Add BonreeTrace prefix reference here
let options: http.HttpRequestOptions = {};
let promise = httpRequest.request(
'request url', options
);
promise.then((responseData: http.HttpResponse) => {
}).catch((err: BusinessError) => {
})

Scheme Two:

Step 1 (Optional configuration): For end-to-end full link tracking, you need to insert Bonree's custom business request headers. If you don't need full link business, you can skip this step.

Important API Note: The custom business request header is returned based on URL rules. Each network request's custom header needs to be obtained and assigned separately. It is strictly forbidden to reuse the API call results for different requestUrl calls!

  function getInsertHeaderMap(requestUrl: string): Map<string, string> | undefined
ParameterDescriptionParameter ConstraintsFailure Result
requestUrlRequest URL (Required)string type. Valid request addressCurrent fetch is invalid
import http from '@ohos.net.http'
import { BonreeTrace } from '@bonree/agent'

let httpRequest = http.createHttp();
let customHeaders: Record<string, string> = {};
// Add: Get end-to-end request headers here. If you don't have end-to-end business, you can skip this.
BonreeTrace.http.getInsertHeaderMap("Current request URL")?.forEach((value, key) => {
customHeaders[key] = value;
})
let options: http.HttpRequestOptions = {
header: customHeaders,
};
let promise = httpRequest.request("Current request URL", options);

Step 2 (Required configuration): Collect normal/abnormal network data

function handleSuccess(requestUrl: string, method: string, responseCode: number, requestDataSizeByte: number,
downloadSizeByte: number, timing: OhosHttp.PerformanceTiming, remoteAddressIP?: string,
requestHeader?: Record<string, Object>, responseHeader?: Record<string, Object>, resourceType?: string,
optionsUsingProtocol?: string, requestBody?: string)
ParameterDescriptionParameter ConstraintsFailure Result
requestUrlRequest URL (Required)string type. Valid request addressCurrent network event not collected
methodRequest method (Required)string type. For non-http request methods, pass an empty stringCurrent network event not collected
responseCodeResponse code (Required)number typeCurrent network event not collected
requestDataSizeByteRequest upload data size (Required)number type (Unit: Byte)Current network event not collected
downloadSizeByteDownload size (Required)number type (Unit: Byte)Current network event not collected
timingTime spent in each stage of the HTTP request (Required)http.PerformanceTiming typeCurrent network event not collected
remoteAddressIPTarget address IPstring typeCurrent network event missing related field
requestHeaderRequest headerRecord<string, Object> typeCurrent network event missing related field
responseHeaderResponse headerRecord<string, Object> typeCurrent network event missing related field
resourceTypeResource typestring type. Follows the Content-Type field of MIME typeCurrent network event missing related field
optionsUsingProtocolProtocol typestring type. Example: http.HttpProtocol.HTTP2.toString()If value is invalid, it will be automatically obtained based on the URL
requestBodyRequest contentstring typeCurrent network event missing related field
function handleError(requestUrl: string, method: string, requestDataSizeByte: number, errorParam: Error,
requestHeader?: Record<string, Object>)
ParameterDescriptionParameter ConstraintsFailure Result
requestUrlRequest URL (Required)string type. Valid request addressCurrent network event not collected
methodRequest method (Required)string type. For non-http request methods, pass an empty stringCurrent network event not collected
requestDataSizeByteRequest upload data size (Required)number type (Unit: Byte)Current network event not collected
errorParamNetwork Error (Required)BusinessError typeCurrent network event not collected
requestHeaderRequest headerRecord<string, Object> typeCurrent network event missing related field

Example:

promise.then((responseData: http.HttpResponse) => {
BonreeTrace.http.handleSuccess("Current request URL", "GET", responseData.responseCode, requestDataSize, downloadSize, responseData.performanceTiming);
}).catch((err: BusinessError) => {
BonreeTrace.http.handleError("Current request URL", "GET", 0, err);
});

5.3 'ohos.net.webSocket'

Only need to add the BonreeTrace prefix reference before the webSocket.createWebSocket API.

import { webSocket } from '@kit.NetworkKit';
import { BonreeTrace } from '@bonree/agent';

let webSocketInstance: webSocket.WebSocket = BonreeTrace.webSocket.createWebSocket(); // Add BonreeTrace prefix reference here

5.4 'ohos.net.socket.TCPSocket'

Only need to add the BonreeTrace prefix reference before the call to the socket.constructTCPSocketInstance API.

import { socket } from '@kit.NetworkKit';
import { BonreeTrace } from '@bonree/agent';

let tcpSocketInstance: BonreeTrace.socket.TCPSocket = BonreeTrace.socket.constructTCPSocketInstance(); // Add BonreeTrace prefix reference here

5.5 'ohos/axios'

Only supports versions >=2.2.1

Step 1 (Optional configuration): For end-to-end full link tracking, you need to insert Bonree's custom business request headers. If you don't need full link business, you can skip this step.

Important API Note: The custom business request header is returned based on URL rules. Each network request's custom header needs to be obtained and assigned separately. It is strictly forbidden to reuse the API call results for different requestUrl calls!

function getInsertHeaderMap(requestUrl: string): Map<string, string> | undefined
ParameterDescriptionParameter ConstraintsFailure Result
requestUrlRequest URL (Required)string type. Valid request addressCurrent fetch is invalid
// Example: Insert request headers via `AxiosRequestConfig`. You can also handle `InternalAxiosRequestConfig.headers` by implementing a request interceptor for header insertion.
import axios, {
AxiosError,
AxiosHeaders,
AxiosResponse,
AxiosRequestConfig,
InternalAxiosRequestConfig
} from '@ohos/axios'
import { BonreeTrace } from '@bonree/agent'

let customHeaders: AxiosHeaders = new AxiosHeaders();
// First, get the Bonree full link business request headers
BonreeTrace.axios.getInsertHeaderMap("Current request URL")?.forEach((value, key) => {
customHeaders.set(key, value);
});
// Insert into the actual request headers via AxiosRequestConfig
let requestConfig: AxiosRequestConfig = {
method: this.currMethod,
headers: customHeaders,
params: this.currRequestParam
}
axios.get("Current request URL", requestConfig);

Step 2 (Required configuration): Collect normal/abnormal network data

function handleSuccess(requestUrl: string, method: string, responseCode: number, requestDataSizeByte: number,
downloadSizeByte: number, timingParam: object, remoteAddressIP?: string,
requestHeader?: Record<string, Object>, responseHeader?: Record<string, Object>, resourceType?: string,
requestBody?: string)
ParameterDescriptionParameter ConstraintsFailure Result
requestUrlRequest URL (Required)string type. Valid request addressCurrent network event not collected
methodRequest method (Required)string type. For non-http request methods, pass an empty stringCurrent network event not collected
responseCodeResponse code (Required)number typeCurrent network event not collected
requestDataSizeByteRequest upload data size (Required)number type (Unit: Byte)Current network event not collected
downloadSizeByteDownload size (Required)number type (Unit: Byte)Current network event not collected
timingParamTime spent in each stage of the axios request (Required)http.PerformanceTiming typeCurrent network event not collected
remoteAddressIPTarget address IPstring typeCurrent network event missing related field
requestHeaderRequest headerRecord<string, Object> typeCurrent network event missing related field
responseHeaderResponse headerRecord<string, Object> typeCurrent network event missing related field
resourceTypeResource typestring type. Follows the Content-Type field of MIME typeCurrent network event missing related field
requestBodyRequest contentstring typeCurrent network event missing related field
function handleError(requestUrl: string, method: string, requestDataSizeByte: number, errorParam: Error,
requestHeader?: Record<string, Object>)

ParameterDescriptionParameter ConstraintsFailure Result
requestUrlRequest URL (Required)string type. Valid request addressCurrent network event not collected
methodRequest method (Required)string type. For non-http request methods, pass an empty stringCurrent network event not collected
requestDataSizeByteRequest upload data size (Required)number type (Unit: Byte)Current network event not collected
errorParamNetwork Error (Required)BusinessError typeCurrent network event not collected
requestHeaderRequest headerRecord<string, Object> typeCurrent network event missing related field

Example:

axios.get("Current request URL", requestConfig).then((responseData: AxiosResponse) => {
BonreeTrace.axios.handleSuccess("Current request URL", "GET", responseData.status, requestDataSize, downloadSize, responseData.performanceTiming);
}).catch((err: BusinessError) => {
BonreeTrace.axios.handleError("Current request URL", "GET", 0, err);
});

5.6 'mPaaS/rpc'

Step 1 (Optional configuration): For end-to-end full link tracking, you need to insert Bonree's custom business request headers. If you don't need full link business, you can skip this step.

Important API Note: The custom business request header is returned based on URL rules. Each network request's custom header needs to be obtained and assigned separately. It is strictly forbidden to reuse the API call results for different requestUrl calls!

function getInsertHeaderMap(requestUrl: string): Map<string, string> | undefined
ParameterDescriptionParameter ConstraintsFailure Result
requestUrlRequest URL (Required)string type. Valid request addressCurrent fetch is invalid

The following uses ExampleRpcInterceptor as an example. In actual use, replace it with your implemented interceptor class name.

  1. Add an implementation class for the RpcInterceptor interface
import { MPRpc, RpcInterceptor, RpcInvokeContext } from '@mpaas/rpc'
import { BonreeTrace } from '@bonree/agent';

export class ExampleRpcInterceptor implements RpcInterceptor {
preHandle(rpcInvokeContext: RpcInvokeContext): boolean {
// Add: Get end-to-end request headers here. If you don't have end-to-end business, you can skip this.
BonreeTrace.mPaaSRpc.getInsertHeaderMap("Current request URL")?.forEach((value, key) => {
rpcInvokeContext.addHeader(key, value);
});
return true;
}
}
  1. Add global interceptor configuration during the application startup phase
import { MPRrc } from '@mpaas/rpc'
MPRpc.addGlobalInterceptor(new ExampleRpcInterceptor());

Step 2 (Required configuration): Collect normal/abnormal network data

function handleSuccess(requestUrl: string, requestHeader: Map<string, string>, responseHeader: object,
method?: string, remoteAddressIP?: string, timing?: OhosHttp.PerformanceTiming, requestDataSizeByte?: number,
downloadSizeByte?: number, requestBody?: string)
ParameterDescriptionParameter ConstraintsFailure Result
requestUrlRequest URL (Required)string type. Valid request addressCurrent network event not collected
requestHeaderRequest header (Required)Map<string, string> typeCurrent network event missing related field
responseHeaderResponse header (Required)object typeCurrent network event missing related field
methodRequest methodstring type. For non-http request methods, pass an empty stringDefault request method is post
remoteAddressIPTarget address IPstring typeCurrent network event missing related field
timingTime spent in each stage of the requesthttp.PerformanceTiming typeRelated field value is 0
requestDataSizeByteRequest upload data sizenumber type (Unit: Byte)Related field value is 0
downloadSizeByteDownload sizenumber type (Unit: Byte)Related field value is 0
requestBodyRequest contentstring typeCurrent network event missing related field
function handleError(requestUrl: string, error: Error, requestHeader: Map<string, string>,
responseHeader?: object, method?: string, requestDataSizeByte?: number)
ParameterDescriptionParameter ConstraintsFailure Result
requestUrlRequest URL (Required)string type. Valid request addressCurrent network event not collected
errorError information (Required)Error typeCurrent network event not collected
requestHeaderRequest header (Required)Map<string, string> typeCurrent network event missing related field
responseHeaderResponse headerobject typeCurrent network event missing related field
methodRequest methodstring type. For non-http request methods, pass an empty stringDefault request method is post
requestDataSizeByteRequest upload data sizenumber type (Unit: Byte)Related field value is 0

The following uses ExampleRpcInterceptor as an example. In actual use, replace it with your implemented interceptor class name.

  1. Add an implementation class for the RpcInterceptor interface
export class ExampleRpcInterceptor implements RpcInterceptor {
preHandle(rpcInvokeContext: RpcInvokeContext): boolean {
// Add: Get end-to-end request headers here. If you don't have end-to-end business, you can skip this.
BonreeTrace.mPaaSRpc.getInsertHeaderMap("Current request URL")?.forEach((value, key) => {
rpcInvokeContext.addHeader(key, value);
});
return true;
}

postHandle(rpcInvokeContext: RpcInvokeContext): boolean {
BonreeTrace.mPaaSRpc.handleSuccess("Current request URL", rpcInvokeContext.getRequestHeader(),
rpcInvokeContext.getResponseHeader());
return true;
}

handleException(rpcInvokeContext: RpcInvokeContext, exception: RPCException): boolean {
BonreeTrace.mPaaSRpc.handleError("Current request URL", exception, rpcInvokeContext.getRequestHeader());
throw exception
}
}
  1. Add global interceptor configuration during the application startup phase
import { MPRrc } from '@mpaas/rpc'
MPRpc.addGlobalInterceptor(new ExampleRpcInterceptor());

VI. Embedding Verification

Start the embedded APP and check the hilog logs. Filter for the BRSDK-Agent tag. The following logs indicate successful embedding and that data collection has started:

BRSDK-Agent   I   starting...         (Note: BRAgent integrated successfully)
BRSDK-Agent I Bonree token***** (Note: BRAgent started successfully)
BRSDK-Agent I BRAgent connect server success (Note: BRAgent data setting successful)
BRSDK-Agent I BRAgent v*** (Note: *** corresponds to the BRAgent version in the current zip file name)

image-202402021422250301