SDK 在 init 之前不接受任何方法调用,想要调用 SDK 内部方法,需要先进行 init,且 init 方法已做合规处理,init 不会自动采集敏感信息与发送请求。
可以考虑在 AbilityStage 的 onCreate 中 sdk init,在隐私同意后进行 sdk start。
appLog.init(context, config)
请不要在 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()
该加密方式目前仅私有化版本支持。
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()
自1.3.0版本开始支持通过以下开关的配置来关闭 Oaid、运营商信息采集。
鸿蒙 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)
本小节功能仅付费版支持,如有需要请联系我们,默认提供的基础版不带该功能。
多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 后开始支持。
调用时机说明:请在 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 / 公共属性操作。
打通功能需要 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 对齐,暂不支持按时间曝光配置以及调试视图。
说明
可以根据曝光事件内部的 $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")
本小节功能仅付费版支持,如有需要请联系我们,默认提供的基础版不带该功能。
由于鸿蒙已不再推荐 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) }