原生应用
集成
一、预置Bonree SDK环境
拷贝bonree_sdk-signed.har到工程级目录中的hars文件夹

二、添加bonree_sdk-signed.har
2.1 在工程的oh-package.json5中dependencies字段增加har包依赖 "@bonree/agent": "file:./hars/bonree_sdk-signed.har"
配置示例如下:
{
"modelVersion": "5.0.0",
"description": "Please describe the basic information.",
"dependencies": {
"@bonree/agent": "file:./hars/bonree_sdk-signed.har" // 这里要添加配置,用于引用SDK
},
"devDependencies": {
"@ohos/hypium": "1.0.18",
"@ohos/hamock": "1.0.0"
}
}

2.2 使用ohmurl新的拼接和解析方式
将工程级build-profile.json5中的useNormalizedOHMUrl修改为true, 若没有该配置项请手动添加。
{
"app": {
"products": [
{
"buildOption": {
"strictMode": {
"useNormalizedOHMUrl": true
}
}
}
]
}
}
三、Sync & Rebuid 项目
第一步:
点击右上角的 [ Sync Now ]

若未出现,可使用 DevEco Studio 快捷键解决, 选择 Run 'ohpm install'

第二步:
Rebuild项目,确保配置生效。
接入
一、配置授权信息
检查应用程序module.json5配置文件,尽量确保已引入如下授权:
//下列权限都是必要权限,详情可参阅《隐私政策》中权限说明部分:
ohos.permission.INTERNET 发送网络数据
ohos.permission.GET_NETWORK_INFO 获取网络状态信息
二、初始化SDK
<#Config地址#> 与 <#AppID#> 请于平台上获取,获取方式参见《如何查询AppID和Config地址?》。如有问题请联系技术支持。
请在入口entry moudle自定义AbilityStage中的onCreate函数中,添加如下代码:
Bonree.withAppID("<#AppID#>")
.withConfigAddress("<#Config地址#>")
.start(this.context.getApplicationContext());
样例代码:
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地址#>")
.start(this.context.getApplicationContext());
}
}
三、Web数据采集
3.1原生应用采集
3.1.1 采集Web性能数据
在javaScriptOnDocumentStart、onControllerAttached中分別添加BonreeTrace.Web.getScriptItem(controller)、BonreeTrace.Web.onControllerAttachedHilt(controller)
import { BonreeTrace } from '@bonree/agent';
Web()
.javaScriptOnDocumentStart([BonreeTrace.Web.getScriptItem(this.controller)])// this.controller:必须是当前Web绑定的WebviewController
.onControllerAttached(() => {
BonreeTrace.Web.onControllerAttachedHilt(this.controller); // this.controller:必须是当前Web绑定的WebviewController
})
3.1.2 采集Web异常数据
在onErrorReceive、onHttpErrorReceive、onSslErrorEventReceive中添加对应方法
import { BonreeTrace } from '@bonree/agent';
Web()
.onErrorReceive((event) => {
if (!event) {
return;
}
BonreeTrace.Web.onErrorReceive(event.request, event.error, this.controller.getWebId()); // this.controller:必须是当前Web绑定的WebviewController
})
.onHttpErrorReceive((event) => {
if (!event) {
return;
}
BonreeTrace.Web.onHttpErrorReceive(event.request, event.response, this.controller.getWebId()); // this.controller:必须是当前Web绑定的WebviewController
})
.onSslErrorEventReceive((event) => {
BonreeTrace.Web.onSslErrorEventReceive(event.error, this.controller.getWebId()); // this.controller:必须是当前Web绑定的WebviewController
})
3.2mPaaS应用采集
3.2.1 采集Web性能数据与异常数据
- 采集Web性能数据与异常数据需要在应用启动时初始化Bonree SDK,并实现H5WebClientProvider接口。调用接口注册时,可参考示例
ExampleWebclientProviderImpl类,实际使用时需填写您自己实现的类,示例注册代码如下:HRiver.setProvider(H5WebClientProvider.name, new ExampleWebclientProviderImpl()) - 若要采集Web性能数据,需在
onPageBegin和onControllerAttached方法中分别添加对应的方法调用:BonreeTrace.Web.getScriptItem(controller)和BonreeTrace.Web.onControllerAttachedHilt(controller)。 - 若要采集Web异常数据,需在
onErrorReceive、onHttpErrorReceive和onSslErrorEventReceive方法中分别添加对应的处理方法:BonreeTrace.Web.onErrorReceive(request, error, controller.getWebId())、BonreeTrace.Web.onHttpErrorReceive(request, response, controller.getWebId())和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);
}
}
}
四、视图/启动数据采集
重要说明:
1.暂不支持子窗口中的视图数据采集,子窗口中的视图忽略本步骤。
2.使用uiObserver.off()和UIObserver.off()系列接口时务必传入callback,若off时不传callback会取消掉所有的注册,导致SDK数据采集异常。
4.1 Ability 数据采集
在UIAbility的子类声明上添加 @BonreeTrace.InjectAbility 装饰器
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 数据采集
在AbilityStage的子类声明上添加 @BonreeTrace.InjectStage 装饰器
import { BonreeTrace } from '@bonree/agent';
@BonreeTrace.InjectStage
export default class EntryAbilityStage extends AbilityStage {
onCreate() {
}
onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
}
}
4.3 UI页面/Page 数据采集
在所有@Entry装饰的自定义组件下面添加 BonreeTrace.InjectPage(Index) 接口调用并传入当前结构, Page生命周期( aboutToAppear,onPageShow,onPageHide,aboutToDisappear)函数尽量复写,否则影响快照数据采集和性能准确性
import { BonreeTrace } from '@bonree/agent';
@Entry
@Component
struct Index {
build() {
}
aboutToAppear(): void {
}
onPageShow(): void {
}
onPageHide(): void {
}
aboutToDisappear(): void {
}
}
BonreeTrace.InjectPage(Index)
五、网络采集
目前支持采集框架 hms.collaboration.rcp,ohos.net.http,ohos.net.webSocket,ohos.net.socket.TCPSocket,ohos/axios,mPaaS/rpc,当采集对应网络框架时,需要使用 BonreeTrace 引用这些框架类,各网络框架API使用同官网文档,如下是每个网络采集示例。
5.1 'hms.collaboration.rcp'
重要说明: rcp共有两种方案, 属于互斥方案, 当您集成时只能二选一
方案一:
仅需要在rcp.createSessionAPI前添加BonreeTrace开头引用。
import { rcp } from '@kit.RemoteCommunicationKit';
import { BonreeTrace } from '@bonree/agent';
// 示例1: 无参数传递
let session1 = BonreeTrace.rcp.createSession(); // 这里要添加 BonreeTrace 开头引用
// 示例2: 有参数传递
let session = BonreeTrace.rcp.createSession({}); // 这里要添加 BonreeTrace 开头引用
方案二:
需要在调用rcp.createSession(sessionConfiguration)中的sessionConfiguration.interceptors增加拦截器AgentRcpInterceptor
import { rcp } from '@kit.RemoteCommunicationKit';
import { BonreeTrace } from '@bonree/agent';
// 示例
const sessionConfig: rcp.SessionConfiguration = {
// 这里要添加 BonreeTrace.rcp.AgentRcpInterceptor 拦截器
interceptors: [new BonreeTrace.rcp.AgentRcpInterceptor()]
};
let session = rcp.createSession(sessionConfig);
5.2 'ohos.net.http'
重要说明: http共有两种方案, 属于互斥方案, 当您集成时只能二选一
方案一(推荐):
仅需要在http.createHttpAPI前添加BonreeTrace开头引用。
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { BonreeTrace } from '@bonree/agent';
let httpRequest = BonreeTrace.http.createHttp(); // 这里要添加 BonreeTrace 开头引用
let options: http.HttpRequestOptions = {};
let promise = httpRequest.request(
'request url', options
);
promise.then((responseData: http.HttpResponse) => {
}).catch((err: BusinessError) => {
})
方案二:
第一步(可选配置):端对端的全链路打通需要在请求头中插入Bonree的自定义业务请求头,如不需要全链路业务可跳过此步骤。
API重要说明: 自定义业务请求头是根据URL规则返回,每条网络请求自定义头都需要重新获取赋值,非同一个requestUrl的API调用结果严禁复用!
function getInsertHeaderMap(requestUrl: string): Map<string, string> | undefined
| 参数 | 说明 | 参数限制 | 失败结果 |
|---|---|---|---|
| requestUrl | 请求URL(必要) | string类型。有效请求地址 | 当次获取无效 |
import http from '@ohos.net.http'
import { BonreeTrace } from '@bonree/agent'
let httpRequest = http.createHttp();
let customHeaders: Record<string, string> = {};
// 这里要添加 获取端到端请求头,若您没有端到端业务,可跳过
BonreeTrace.http.getInsertHeaderMap("本次请求的URL")?.forEach((value, key) => {
customHeaders[key] = value;
})
let options: http.HttpRequestOptions = {
header: customHeaders,
};
let promise = httpRequest.request("本次请求的URL", options);
第二步(必要配置):采集正常/异常网络数据
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)
| 参数 | 说明 | 参数限制 | 失败结果 |
|---|---|---|---|
| requestUrl | 请求URL(必要) | string类型。有效请求地址 | 当次网络事件不采集 |
| method | 请求方法(必要) | string类型。非http请求方法,传空字符串即可 | 当次网络事件不采集 |
| responseCode | 响应码(必要) | number类型 | 当次网络事件不采集 |
| requestDataSizeByte | 请求上传数据大小(必要) | number类型(单位Byte) | 当次网络事件不采集 |
| downloadSizeByte | 下载大小(必要) | number类型(单位Byte) | 当次网络事件不采集 |
| timing | HTTP 请求各个阶段所花费的时间(必要) | http.PerformanceTiming类型 | 当次网络事件不采集 |
| remoteAddressIP | 目标地址IP | string类型 | 当次网络事件缺失相关字段 |
| requestHeader | 请求header | Record<string, Object>类型 | 当次网络事件缺失相关字段 |
| responseHeader | 响应header | Record<string, Object>类型 | 当次网络事件缺失相关字段 |
| resourceType | 资源类型 | string类型。遵循MIME类型的Content-Type字段 | 当次网络事件缺失相关字段 |
| optionsUsingProtocol | 协议类型 | string类型。示例:http.HttpProtocol.HTTP2.toString() | 值无效则会根据url自动获取 |
| requestBody | 请求内容 | string类型 | 当次网络事件缺失相关字段 |
function handleError(requestUrl: string, method: string, requestDataSizeByte: number, errorParam: Error,
requestHeader?: Record<string, Object>)
| 参数 | 说明 | 参数限制 | 失败结果 |
|---|---|---|---|
| requestUrl | 请求URL(必要) | string类型。有效请求地址 | 当次网络事件不采集 |
| method | 请求方法(必要) | string类型。非http请求方法,传空字符串即可 | 当次网络事件不采集 |
| requestDataSizeByte | 请求上传数据大小(必要) | number类型(单位Byte) | 当次网络事件不采集 |
| errorParam | 网络Error错误(必要) | BusinessError类型 | 当次网络事件不采集 |
| requestHeader | 请求header | Record<string, Object>类型 | 当次网络事件缺失相关字段 |
示例如下:
promise.then((responseData: http.HttpResponse) => {
BonreeTrace.http.handleSuccess("本次请求的URL", "GET", responseData.responseCode, requestDataSize, downloadSize, responseData.performanceTiming);
}).catch((err: BusinessError) => {
BonreeTrace.http.handleError("本次请求的URL", "GET", 0, err);
});
5.3 'ohos.net.webSocket'
仅需要在webSocket.createWebSocketAPI前添加BonreeTrace开头引用。
import { webSocket } from '@kit.NetworkKit';
import { BonreeTrace } from '@bonree/agent';
let webSocketInstance: webSocket.WebSocket = BonreeTrace.webSocket.createWebSocket(); // 这里要添加 BonreeTrace 开头引用
5.4 'ohos.net.socket.TCPSocket'
仅需要在调用socket.constructTCPSocketInstanceAPI前添加BonreeTrace开头引用。
import { socket } from '@kit.NetworkKit';
import { BonreeTrace } from '@bonree/agent';
let tcpSocketInstance: BonreeTrace.socket.TCPSocket = BonreeTrace.socket.constructTCPSocketInstance(); // 这里要添加 BonreeTrace 开头引用
5.5 'ohos/axios'
仅支持 >=2.2.1 版本
第一步(可选配置):端对端的全链路打通需要在请求头中插入Bonree的自定义业务请求头,如不需要全链路业务可跳过此步骤。
API重要说明: 自定义业务请求头是根据URL规则返回,每条网络请求自定义头都需要重新获取赋值,非同一个requestUrl的API调用结果严禁复用!
function getInsertHeaderMap(requestUrl: string): Map<string, string> | undefined
| 参数 | 说明 | 参数限制 | 失败结果 |
|---|---|---|---|
| requestUrl | 请求URL(必要) | string类型。有效请求地址 | 当次获取无效 |
//示例通过`AxiosRequestConfig`插入请求头,您也可以通过实现请求拦截器处理`InternalAxiosRequestConfig.headers`进行插头操作
import axios, {
AxiosError,
AxiosHeaders,
AxiosResponse,
AxiosRequestConfig,
InternalAxiosRequestConfig
} from '@ohos/axios'
import { BonreeTrace } from '@bonree/agent'
let customHeaders: AxiosHeaders = new AxiosHeaders();
// 先获取Bonree全链路业务请求头
BonreeTrace.axios.getInsertHeaderMap("本次请求的URL")?.forEach((value, key) => {
customHeaders.set(key, value);
});
// 通过AxiosRequestConfig插入到实际请求头中
let requestConfig: AxiosRequestConfig = {
method: this.currMethod,
headers: customHeaders,
params: this.currRequestParam
}
axios.get("本次请求的URL", requestConfig);
第二步(必要配置):采集正常/异常网络数据
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)
| 参数 | 说明 | 参数限制 | 失败结果 |
|---|---|---|---|
| requestUrl | 请求URL(必要) | string类型。有效请求地址 | 当次网络事件不采集 |
| method | 请求方法(必要) | string类型。非http请求方法,传空字符串即可 | 当次网络事件不采集 |
| responseCode | 响应码(必要) | number类型 | 当次网络事件不采集 |
| requestDataSizeByte | 请求上传数据大小(必要) | number类型(单位Byte) | 当次网络事件不采集 |
| downloadSizeByte | 下载大小(必要) | number类型(单位Byte) | 当次网络事件不采集 |
| timingParam | axios 请求各个阶段所花费的时间(必要) | http.PerformanceTiming类型 | 当次网络事件不采集 |
| remoteAddressIP | 目标地址IP | string类型 | 当次网络事件缺失相关字段 |
| requestHeader | 请求header | Record<string, Object>类型 | 当次网络事件缺失相关字段 |
| responseHeader | 响应header | Record<string, Object>类型 | 当次网络事件缺失相关字段 |
| resourceType | 资源类型 | string类型。遵循MIME类型的Content-Type字段 | 当次网络事件缺失相关字段 |
| requestBody | 请求内容 | string类型 | 当次网络事件缺失相关字段 |
function handleError(requestUrl: string, method: string, requestDataSizeByte: number, errorParam: Error,
requestHeader?: Record<string, Object>)
| 参数 | 说明 | 参数限制 | 失败结果 |
|---|---|---|---|
| requestUrl | 请求URL(必要) | string类型。有效请求地址 | 当次网络事件不采集 |
| method | 请求方法(必要) | string类型。非http请求方法,传空字符串即可 | 当次网络事件不采集 |
| requestDataSizeByte | 请求上传数据大小(必要) | number类型(单位Byte) | 当次网络事件不采集 |
| errorParam | 网络Error错误(必要) | BusinessError类型 | 当次网络事件不采集 |
| requestHeader | 请求header | Record<string, Object>类型 | 当次网络事件缺失相关字段 |
示例如下:
axios.get("本次请求的URL",requestConfig).then((responseData: AxiosResponse) => {
BonreeTrace.axios.handleSuccess("本次请求的URL", "GET", responseData.status, requestDataSize, downloadSize, responseData.performanceTiming);
}).catch((err: BusinessError) => {
BonreeTrace.axios.handleError("本次请求的URL", "GET", 0, err);
});
5.6 'mPaaS/rpc'
第一步(可选配置):端对端的全链路打通需要在请求头中插入Bonree的自定义业务请求头,如不需要全链路业务可跳过此步骤。
API重要说明: 自定义业务请求头是根据URL规则返回,每条网络请求自定义头都需要重新获取赋值,非同一个requestUrl的API调用结果严禁复用!
function getInsertHeaderMap(requestUrl: string): Map<string, string> | undefined
| 参数 | 说明 | 参数限制 | 失败结果 |
|---|---|---|---|
| requestUrl | 请求URL(必要) | string类型。有效请求地址 | 当次获取无效 |
以下以 ExampleRpcInterceptor 为例,实际使用时请替换为您实现的拦截器类名
- 添加RpcInterceptor接口实现类
import { MPRpc, RpcInterceptor, RpcInvokeContext } from '@mpaas/rpc'
import { BonreeTrace } from '@bonree/agent';
export class ExampleRpcInterceptor implements RpcInterceptor {
preHandle(rpcInvokeContext: RpcInvokeContext): boolean {
//这里要添加 获取端到端请求头,若您没有端到端业务,可跳过
BonreeTrace.mPaaSRpc.getInsertHeaderMap("本次请求的URL")?.forEach((value, key) => {
rpcInvokeContext.addHeader(key, value);
});
return true;
}
}
- 在应用启动阶段添加全局拦截器配置
import { MPRpc } from '@mpaas/rpc'
MPRpc.addGlobalInterceptor(new ExampleRpcInterceptor());
第二步(必要配置):采集正常/异常网络数据
function handleSuccess(requestUrl: string, requestHeader: Map<string, string>, responseHeader: object,
method?: string, remoteAddressIP?: string, timing?: OhosHttp.PerformanceTiming, requestDataSizeByte?: number,
downloadSizeByte?: number, requestBody?: string)
| 参数 | 说明 | 参数限制 | 失败结果 |
|---|---|---|---|
| requestUrl | 请求URL(必要) | string类型。有效请求地址 | 当次网络事件不采集 |
| requestHeader | 请求header(必要) | Map<string, string>类型 | 当次网络事件缺失相关字段 |
| responseHeader | 响应header(必要) | object类型 | 当次网络事件缺失相关字段 |
| method | 请求方法 | string类型。非http请求方法,传空字符串即可 | 默认请求方法为 post |
| remoteAddressIP | 目标地址IP | string类型 | 当次网络事件缺失相关字段 |
| timing | 请求各个阶段所花费的时间 | http.PerformanceTiming类型 | 相关字段的值为0 |
| requestDataSizeByte | 请求上传数据大小 | number类型(单位Byte) | 相关字段的值为0 |
| downloadSizeByte | 下载大小 | number类型(单位Byte) | 相关字段的值为0 |
| requestBody | 请求内容 | string类型 | 当次网络事件缺失相关字段 |
function handleError(requestUrl: string, error: Error, requestHeader: Map<string, string>,
responseHeader?: object, method?: string, requestDataSizeByte?: number)
| 参数 | 说明 | 参数限制 | 失败结果 |
|---|---|---|---|
| requestUrl | 请求URL(必要) | string类型。有效请求地址 | 当次网络事件不采集 |
| error | 错误信息(必要) | Error类型 | 当次网络事件不采集 |
| requestHeader | 请求header(必要) | Map<string, string>类型 | 当次网络事件缺失相关字段 |
| responseHeader | 响应header | object类型 | 当次网络事件缺失相关字段 |
| method | 请求方法 | string类型。非http请求方法,传空字符串即可 | 默认请求方法为 post |
| requestDataSizeByte | 请求上传数据大小 | number类型(单位Byte) | 相关字段的值为0 |
以下以 ExampleRpcInterceptor 为例,实际使用时请替换为您实现的拦截器类名
- 添加RpcInterceptor接口实现类
export class ExampleRpcInterceptor implements RpcInterceptor {
preHandle(rpcInvokeContext: RpcInvokeContext): boolean {
//这里要添加 获取端到端请求头,若您没有端到端业务,可跳过
BonreeTrace.mPaaSRpc.getInsertHeaderMap("本次请求的URL")?.forEach((value, key) => {
rpcInvokeContext.addHeader(key, value);
});
return true;
}
postHandle(rpcInvokeContext: RpcInvokeContext): boolean {
BonreeTrace.mPaaSRpc.handleSuccess("本次请求的URL", rpcInvokeContext.getRequestHeader(),
rpcInvokeContext.getResponseHeader());
return true;
}
handleException(rpcInvokeContext: RpcInvokeContext, exception: RPCException): boolean {
BonreeTrace.mPaaSRpc.handleError("本次请求的URL", exception, rpcInvokeContext.getRequestHeader());
throw exception
}
}
- 在应用启动阶段添加全局拦截器配置
import { MPRpc } from '@mpaas/rpc'
MPRpc.addGlobalInterceptor(new ExampleRpcInterceptor());
六、嵌码验证
启动已嵌码的APP,查看hilog日志,搜索过滤BRSDK-Agent标签,出现如下log则表示嵌码成功且数据开始采集:
BRSDK-Agent I starting... (注:BRAgent 集成成功)
BRSDK-Agent I Bonree token***** (注:BRAgent 启动成功)
BRSDK-Agent I BRAgent connect server success (注:BRAgent 数据设置成功)
BRSDK-Agent I BRAgent v*** (注: ***为当前zip包文件名后所对应的BRAgent版本)
