:::tip
SDK 在 init 之前不接受任何方法调用,想要调用 SDK 内部方法,需要先进行 init,且 init 方法已做合规处理,init 不会自动采集敏感信息与发送请求。
可以考虑在 AbilityStage 的 onCreate 中 sdk init,在隐私同意后进行 sdk start。
:::
appLog.init(context, config)
:::tip
请不要在 init 之前调用 start,调用 start 后,SDK 真正开始做敏感信息采集与请求上报。
:::
appLog.start()
import { InitConfig } from '@volcengine/applog'
let config = new InitConfig('yourAppId', 'yourChannel')
// 开启 SDK 日志
.setLogEnabled(true)
import { InitConfig } from '@volcengine/applog'
let config = new InitConfig('yourAppId', 'yourChannel')
// 也需要先开启 SDK 日志
.setLogEnabled(true)
// 实现日志接管方法
.setLogger({
log: (_: hilog.LogLevel, __: string, msg: string, err?: Error) => {
hilog.debug(0x0100, 'AppLogH_test', `${msg} ${err ? JSON.stringify(err) : ""}`)
}
})
import { InitConfig } from '@volcengine/applog'
import { createByDomain } from '@volcengine/applog/src/main/ets/core/base/url/UriConfig'
let config = new InitConfig('yourAppId', 'yourChannel')
.setUri(createByDomain("your_REPORT_URL"))
SDK 默认开启加密,且内置的默认加密方式与 Android 一致。
如果需要修改 SDK 加密方式,建议在 init 和 start 之间插入对应代码,这样可以确保启动后请求应用加密方式。
无需额外设置。
import { AppLog, InitConfig } from '@volcengine/applog'
let appLog = new AppLog()
let config = new InitConfig('yourAppId', 'yourChannel')
appLog.init(context, config)
// 默认无需添加,默认开启加密
appLog.encrypt()?.enablePlugin()
// 切换至默认加密方式,建议在 start 之前调用,因为 start 就开始请求
appLog.encrypt()?.useDefaultEncrypt()
appLog.start()
:::warning
该加密方式目前仅私有化版本支持。
:::
import { AppLog, InitConfig } from '@volcengine/applog'
let appLog = new AppLog()
let config = new InitConfig('yourAppId', 'yourChannel')
appLog.init(context, config)
// 默认无需添加,默认开启加密
appLog.encrypt()?.enablePlugin()
// 切换至国密 SM2 非对称加密,需要手动传入公钥
appLog.encrypt()?.useSm2Encrypt("your_public_key")
appLog.start()
对于调试阶段,可以关闭 SDK 加密,方便抓包查看数据是否正常。
import { AppLog, InitConfig } from '@volcengine/applog'
let appLog = new AppLog()
let config = new InitConfig('yourAppId', 'yourChannel')
appLog.init(context, config)
// 关闭加密
appLog.encrypt()?.disablePlugin()
appLog.start()
:::warning
自1.3.0版本开始支持通过以下开关的配置来关闭 Oaid、运营商信息采集。
:::
:::tip
鸿蒙 Oaid 为用户授权权限,需要应用侧主动申请权限,如果申请权限且用户同意,SDK 才能采集到 Oaid,也支持在用户同意的情况下关闭 Oaid 采集。
:::
设备的 OAID 信息采集默认开启,如需关闭:
let config = new InitConfig('yourAppId', 'yourChannel')
.setOaidEnabled(false)
设备的运营商信息默认采集,如需关闭:
let config = new InitConfig('yourAppId', 'yourChannel')
.setOperatorInfoEnabled(false)
用户行为日志采用事件 event + 属性 params 的形式,事件一般对应多个属性,也可以仅有事件没有属性。代码埋点方案一般由数据分析师或产品运营设计。
// 示例:上报事件 event,该事件不包含属性
// 置于业务逻辑对应位置
appLog.event("event")
// 示例:上报事件 event,该事件包含两个属性
// 一个 string 类型的属性,属性名为 key_string,属性值为 value_string
// 一个 int 类型的属性,属性名为 key_int,属性值为 10
// 置于业务逻辑对应位置
appLog.event("event", {
"key_string": "value_string",
"key_int": 10
})
如需在每个事件中都包括某属性,可通过公共属性设置,无需在每个事件中重复设置。公共属性只需设置一次,即可包括在所有代码埋点事件、预置事件和全埋点事件中。
公共属性存储逻辑与 iOS 一致,非持久化。
/*
* 示例:设置自定义的公共属性,属性名为 key_public,属性值为 value_public
* 关于自定义 “公共属性” 请注意:
* 1. 上报机制是随着每一次日志发送进行提交,默认的日志发送频率是 1 分钟,
* 所以如果在一分钟内连续修改自定义公共属性,按照日志发送前的最后一次修改为准;
* 2. 不推荐高频次修改,如每秒修改一次。
*/
appLog.setHeaderInfo("key_public", "value_public")
// 示例:移除属性名为 key_public 的公共属性
appLog.removeHeaderInfo("key_public")
获取用户信息模块
appLog.user()
如您的产品中有账户体系,请在用户登录后立即设置 uuid,以保证用户登录前后口径一致性。 6.13.0+ 版本支持在初始化 AppLog 之前调用,用于设置已登录的用户 uuid。
// 设置 UUID
appLog.user()?.setUserUniqueID("your_uuid")
// 如果有多口径需求可以看下面的设置
// 设置 UUID + UUIDType
appLog.user()?.setUserUniqueID("your_uuid", "your_uuid_type")
// 单参数的 setUserUniqueID(uuid) 等效于 双参数的 setUserUniqueID(uuid, lastuuidType) 只是默认情况下 uuidType 没有,如果设置过 uuidType 想要清空,需要额外设置:
appLog.user()?.setUserUniqueID("your_uuid", null)
在账户登出时调用。
// 登出 UUID
appLog.user()?.setUserUniqueID(null)
// 如果有多口径需求可以看下面的设置
// 登出 UUID + UUIDType
appLog.user()?.setUserUniqueID(null, null)
since:1.3.3-rc3。
:::tip
仅 SaaS-云原生 / 私有化支持,多ID口径功能需单独申请开通,使用时,需在上报用户 ID、ID type 时,同时配置 id_bind 关系,以尽可能准确还原一个真实的用户。更多关于多 ID 口径的介绍和使用指导请参见使用多ID类型。
:::
// 示例演示
appLog.user()?.bind({
"id_type_1": "id_type_value_1",
"id_type_2": "id_type_value_2"
}, (result: IDBindParams) => {
hilog.info(0x0000, 'AppLogH', `IDBindSuccess result: ${JSON.stringify(result)}`)
// 更新用户状态
appLog.user()?.setUserUniqueID("id_type_value_1", "id_type_1")
}, (code: number, message: StringOrNull) => {
hilog.info(0x0000, 'AppLogH', `IDBindFail code: ${code}, message: ${message}`)
})
设置用户属性,存在则覆盖,不存在则创建。
appLog.profile()?.set({
"set1": "value",
"set2": "value"
})
设置用户属性,存在则不设置,不存在则创建。适合首次相关的用户属性,比如首次访问时间等。
appLog.profile()?.setOnce({
"setOnce": "value"
})
设置数值类型的属性,可进行累加。
appLog.profile()?.increment({
"increment": 1
})
设置List类型的用户属性,可持续向 List 内添加。
appLog.profile()?.append({
"appendStr": "1",
"appendNum": 1
})
删除用户的属性。
appLog.profile()?.unset("set2")
appLog.topicReceiver()?.on(Topic.DidReady, (didInfo) => {
setTimeout(() => {
hilog.info(0x0000, 'AppLogH', `AppLog did ready: ${didInfo["bd_did"]}`)
})
})
didInfo 格式:
// device_info_from 表示该信息来自本地还是服务端请求返回
// device_info_from: did_from_remote 表示数据来自服务端返回
// device_info_from: did_from_local 表示数据来自本地缓存
{
"bd_did": "xxxx",
"install_id": xxxx,
"device_info_from": "did_from_remote"
}
本小节功能在 1.3.1 后开始支持。
:::tip
调用时机说明:请在 SDK 内部初始化完成后开始请求 SSID,如何判断 SDK 初始化完成,可以订阅 HeaderReady。
:::
使用当前 SDK 内部的 uuid / uuidType(如涉及到多口径)值,去请求对应 SSID。
// 调用 requestSsidWithCurrUUID 请在 HeaderReady 后
applog.topicReceiver()?.stickyOnce(Topic.HeaderReady, async () => {
let ssid = await applog.user()?.requestSsidWithCurrUUID()
hilog.info(0x0000, 'AppLogH', `AppLog ssid: ${ssid}`)
})
使用开发者指定的 uuid / uuidType(如涉及到多口径)值,去请求对应 SSID。
// 调用 requestSsidWithSpecifyUUID 请在 HeaderReady 后
applog.topicReceiver()?.stickyOnce(Topic.HeaderReady, async () => {
let ssid = await applog.user()?.requestSsidWithSpecifyUUID("test")
hilog.info(0x0000, 'AppLogH', `AppLog ssid: ${ssid}`)
})
// 仅针对多口径
applog.topicReceiver()?.stickyOnce(Topic.HeaderReady, async () => {
let ssid = await applog.user()?.requestSsidWithSpecifyUUID("test", "test_type")
hilog.info(0x0000, 'AppLogH', `AppLog ssid: ${ssid}`)
})
AB 实验默认关闭(与 Android 一致),如果需要使用 AB 实验需要先手动开启。
import { AppLog, InitConfig } from '@volcengine/applog'
let appLog = new AppLog()
let config = new InitConfig('yourAppId', 'yourChannel')
appLog.init(context, config)
// 开启 AB 实验,建议在 init 与 start 之间调用
appLog.abTest()?.enablePlugin()
appLog.start()
// 建议每次在获取最新 AB 后获取所有实验结果
appLog.topicReceiver().on(Topic.ABTestConfigReady, (_) => {
appLog.abTest()?.getAllAbTestConfigs()
})
// 建议每次在获取最新 AB 后触发实验
appLog.topicReceiver().on(Topic.ABTestConfigReady, (_) => {
appLog.abTest()?.getAbConfig("ab_key", defaultValue)
})
appLog.abTest()?.getAbSdkVersion()
appLog.topicReceiver()?.on(Topic.ABTestConfigReady, (abTestConfig) => {
hilog.info(0x0000, 'AppLogH', `AppLog abtest config ready: ${JSON.stringify(abTestConfig)}`)
})
abTestConfig 格式:
就是具体的实验配置
{
"ab": {
"val": "访问页面 A",
"vid": "1"
},
"ba": {
"val": "对照版",
"vid": "2"
},
"tt": {
"val": true,
"vid": "3"
}
}
appLog.topicReceiver()?.on(Topic.ABTestVidChanged, (vids) => {
hilog.info(0x0000, 'AppLogH', `AppLog abtest vids: ${JSON.stringify(vids)}`)
})
vids 格式:
{
// 最新曝光的 vid
"new_vid":"1",
// 已曝光的 vid 集合(包含最新的)
"vids":"1"
}
如果您的应用同时集成 Web/JS SDK 以及 Harmony SDK,默认情况下,所有 H5 事件会通过 Web/JS SDK 上报,如果您希望 H5 事件由 Harmony SDK 接管上报,可以使用打通内嵌 H5 功能,此时 H5 页上产生的事件将通过 Harmony SDK 上报,而不在 Web/JS SDK 上报,这种接管上报场景下会复用 Harmony 端设置的user_unique_id和公共属性,但是也支持打通时 web 侧设置 / 更新端上的 uuid / 公共属性,请在打通时注意采用哪边数据,如果完全以端上为准可以去掉 web sdk 侧的 uuid / 公共属性操作。
:::warning
打通功能需要 Web/JS SDK 与 Harmony SDK 同时集成并彼此配合。 Web/JS SDK 集成请参考Web/JS SDK 集成。
:::
初始化SDK
import { AppLog, InitConfig } from '@volcengine/applog'
let appLog = new AppLog()
let config = new InitConfig('yourAppId', 'yourChannel')
appLog.init(context, config)
// ...
appLog.start()
export {
appLog
}
在Web组件上使用
import web_webview from '@ohos.web.webview'
import { appLog } from './applog'
@Component
export struct Webview {
controller: web_webview.WebviewController = new web_webview.WebviewController()
bridgeProxyInfo = appLog.bridge()!.injectJsBridgeByJsProxy()
build() {
Web({ src: $rawfile('webview.html'), controller: this.controller })
.javaScriptAccess(true)
.javaScriptProxy({
object: this.bridgeProxyInfo.object,
name: this.bridgeProxyInfo.name,
methodList: this.bridgeProxyInfo.methodList,
controller: this.controller,
})
}
}
当前版本每个实例都是新创建出来的,所以创建新的 AppLog 对应传入不同的应用实例即可。
import { AppLog, InitConfig } from '@volcengine/applog'
// 创建新的 AppLog 实例
let appLog1 = new AppLog()
// init sdk 传入配置,init 之后可以
appLog1.init(context, new InitConfig('yourAppId1', 'yourChannel')
// 是否打开日志
.setLogEnabled(true))
// 鸿蒙 SDK 需要手动调用 start 才开始采集敏感信息与发送请求
appLog1.start()
// 创建新的 AppLog 实例
let appLog2 = new AppLog()
// init sdk 传入配置,init 之后可以
appLog2.init(context, new InitConfig('yourAppId2', 'yourChannel')
// 是否打开日志
.setLogEnabled(true))
// 鸿蒙 SDK 需要手动调用 start 才开始采集敏感信息与发送请求
appLog2.start()
since:1.3.3-rc3,该功能依赖系统能力,暂不支持 LazyList 等类似列表。
用户需要手动标记监听某个 View 的曝光事件。当这个 View 出现在屏幕可视范围内时,会自动触发一个曝光事件。
目前版本能力基本和 Android 对齐,暂不支持按时间曝光配置以及调试视图。
:::tip
可以根据曝光事件内部的 $exposure_type 属性区分:
如果想在实现组件只曝光一次的效果,可以在新版曝光回调中通过 $exposure_type == 0 进行首次曝光过滤。
:::
// 开启插件
import { AppLog, InitConfig } from '@volcengine/applog'
let appLog = new AppLog()
let config = new InitConfig('yourAppId', 'yourChannel')
appLog.init(context, config)
// 开启曝光插件
appLog.exposure()?.enablePlugin()
appLog.start()
// 使用插件
// 需要给组件添加 ID
Button('Test', { stateEffect: true, type: ButtonType.Capsule })
.id("test_btn"))
// 请在页面 build 后开始监控,如果传入过早,无法通过 NodeId 找到对应组件,就无法处理曝光
// 开始曝光监控,曝光时给 SDK 传给 ID,来确定需要监控哪个组件的曝光
appLog.exposure()?.observeByNodeId("test_btn", this.getUIContext(), {
// Optional,默认为 "$bav2b_exposure"
eventName: "custom_exposure",
// Optional,自定义曝光事件属性
properties: {
"test": "test"
},
// Optional, 曝光配置,有效曝光面积和曝光事件回调
// 有效曝光面积: 有效曝光的 View 显示面积的比例,默认是 0,取值 0-1
// 曝光事件回调: 触发曝光事件时回调,会携带当前曝光事件相关属性,可以进行自定义追加以及支持过滤
config: {
exposureCallback: (param) => {
// 支持在回调中添加自定义属性
// true 保留曝光事件
return true
}
}
})
// 在适当实际停止曝光监控,如离开页面或者其他逻辑
appLog.exposure()?.disposeByNodeId("test_btn")
since:1.3.3-rc3,该功能依赖系统能力,部分组件可能不支持监听,如 Tab 组件。
:::tip
由于鸿蒙已不再推荐 route 页面路由,主推 Navigation 组件导航,所以 SDK 以 Navigation 组件导航为主。
:::
暂不支持 Tab 切换监听,目前系统 Tab 监听不完善,无法监听到 Tab 进入、退出,只能监听到 Tab 切换。
onWindowStageCreate(windowStage: window.WindowStage): void {
// 推荐在 EntryAbility loadContent 时开启,以便对页面生命周期更完整
windowStage.loadContent('pages/Index', (err, data) => {
appLog.bav()?.enablePlugin(windowStage.getMainWindowSync().getUIContext(), {
// 是否采集页面离开事件
enablePageLeaveEvent: true,
// 是否采集组件点击事件
enableClickEvent: true
})
})
}
本小节功能在 1.3.1 后开始支持。
带有时间属性的事件可以使用时长事件采集接口,例如采集视频播放时长事件等。示例:
// 在视频开始播放时调用
applog.eventPlugin()?.startDurationEvent("play");
// 在视频暂停播放时调用
applog.eventPlugin()?.pauseDurationEvent("play");
// 在视频继续播放时调用
applog.eventPlugin()?.resumeDurationEvent("play");
// 在结束播放时调用,此时会上报一个 play 事件,且带有 $event_duration 属性(记录了播放时长,单位毫秒)
applog.eventPlugin()?.stopDurationEvent("test", {
"key": "value"
})
// 支持自定义时长事件事件名,默认情况事件名为方法第一个参数
applog.eventPlugin()?.stopDurationEvent("play", {
"key": "value"
}, "custom_play")
当前 SDK 支持通过 errorManager 采集 JS crash,SDK 内部默认关闭。
let appLog = new AppLog()
let config = new InitConfig('yourAppId', 'yourChannel')
appLog.init(context, config)
// 主动开启 JS Crash 采集
appLog.crash()?.enablePlugin()
appLog.start()
与 Android 一样,开启隐私模式后,SDK 停止接收事件并丢弃,并停止网络请求发送。
applog.eventPlugin()?.setPrivacyMode(true); //默认是 false,设置后 true,不采集不上报
如需使用实时埋点检测,请配置 Scheme,否则可跳过此步骤。
该方式无需配置唤醒协议,
集成 Devtools 后点开,控制台 -> 扫一扫 按照流程操作即可。
现阶段鸿蒙系统浏览器已支持扫码跳转。
「应用列表」-> 接入应用的「详情」->「URL Scheme」中可查看您的 scheme,一般为rangersapplog.xxxxx的形式。

// 在 entry 模块下的主 Ability 中配置 uris:
"uris": [
{
// rangersapplog.xxx 请替换为官方文档中展示的 scheme
"scheme": "rangersapplog.xxx",
"host": "rangersapplog",
"path": "picker"
}
]
// 示例:
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
// 也需要配置
"actions": [
"ohos.want.action.viewData"
],
"uris": [
{
// rangersapplog.xxx 请替换为官方文档中展示的 scheme
"scheme": "rangersapplog.xxx",
"host": "rangersapplog",
"path": "picker"
}
]
},
]
}
]
import { InitConfig } from '@volcengine/applog'
// 在配置跳转协议的 Ability 中添加以下代码:
// 在示例中的 EntryAbility 中添加:
// onNewWant 是在启动后又有启动调用回调
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 传入协议 uri 即可
appLog.simulate()?.start(want.uri)
}
// 如果还没有启动 App 就想要扫码实时埋点
onCreate(want: Want, _: AbilityConstant.LaunchParam): void {
// 注意,需要在 SDK init 之后调用才可以
// 传入协议 uri 即可
appLog.simulate()?.start(want.uri)
}