{"_id":"@arms/js-sdk-miniapp","_rev":"3-8d8be4c12f9a7525621d15482d5c7046","name":"@arms/js-sdk-miniapp","dist-tags":{"latest":"1.8.37"},"versions":{"1.8.36-beta.14":{"name":"@arms/js-sdk-miniapp","version":"1.8.36-beta.14","author":{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},"license":"ISC","_id":"@arms/js-sdk-miniapp@1.8.36-beta.14","maintainers":[{"name":"fengsir","email":"fengsir@live.com"},{"name":"yunjin4","email":"xiashujin.xsj@alibaba-inc.com"},{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},{"name":"yangling1996","email":"yl260087@alibaba-inc.com"},{"name":"yunyi-alibaba","email":"ly403664@alibaba-inc.com"}],"dist":{"shasum":"a986222c44ec2c7dd71d019bfd8b82f65eb35b0b","tarball":"https://registry.npmjs.org/@arms/js-sdk-miniapp/-/js-sdk-miniapp-1.8.36-beta.14.tgz","fileCount":53,"integrity":"sha512-0BWVXKauWRxOh4/3faqu00qjQ+NuQ7d+n8Or8anSTzNhLJnF1VggE6t2ll1NDnTFyiiZn+rupswIiL2fXb4aIA==","signatures":[{"sig":"MEUCIGYRD/6DIlHc9IZFroYsdDnZOmM4uJmLuYCdfXPtRtGvAiEAz/Smc/rjr0TUKHe9DdI2arcoX/Ao0y5v61RIco4/uP0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":448314},"main":"./miniapp.js","gitHead":"5b69dc3b6bc8b1c50e9c3d6b9310581a1f62ca78","keyword":["retcode","log"],"scripts":{"dev":"DEV=1 node ./bin/pack","his":"fie commit out","pub":"node ./bin/publish","init":"fie commit init","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","f2etest":"npm run proxy2local && mocha --no-timeouts test/f2etest/** && npm run stop_proxy","dev_local":"DEV=1 LOCAL=1 node ./bin/pack","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","postcommit":"npm run lint","pure-build":"node ./bin/pack.js","stop_proxy":"npx f2etest-local stop","proxy2local":"npx f2etest-local start --port 1080 --server http://f2etest.alibaba-inc.com/ --name maixi.fl --apikey 1c0ca34a085e4c69af399c0ba699b543","test-miniapp":"nyc mocha --timeout 5000 --reporter spec 'test/unittest/**/**.spec.js'","test-miniapp-watch":"mocha --reporter spec 'test/unittest/**/**.spec.js' --watch"},"_npmUser":{"name":"fengsir","email":"fengsir@live.com"},"_npmVersion":"10.8.1","description":"arms rum javascript sdk","directories":{},"_nodeVersion":"22.3.0","dependencies":{},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^13.1.0","chai":"^4.2.0","chalk":"~1.1.3","karma":"~1.7.1","mocha":"~5.1.1","buffer":"4","eslint":"~3.19.0","globby":"^8.0.1","rollup":"~1.1.0","express":"~4.15.3","chokidar":"~1.7.0","fs-extra":"~4.0.2","watchify":"~3.9.0","expect.js":"^0.3.1","uglify-js":"~3.1.7","aliyun-sdk":"~1.10.11","browserify":"~16.2.0","dateformat":"~2.0.0","jwebdriver":"^2.2.5","node-fetch":"^2.1.2","karma-mocha":"~1.3.0","power-assert":"~1.4.4","karma-coverage":"~1.1.1","strip-comments":"^1.0.2","chai-as-promised":"^7.1.1","karma-browserify":"~5.2.0","browserify-istanbul":"~3.0.1","rollup-plugin-uglify":"~6.0.0","karma-chrome-launcher":"~2.2.0","rollup-plugin-commonjs":"~9.2.0","karma-webdriver-launcher":"^1.0.5","rollup-plugin-node-resolve":"~4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/js-sdk-miniapp_1.8.36-beta.14_1735194819536_0.9077756201694422","host":"s3://npm-registry-packages-npm-production"}},"1.8.37":{"name":"@arms/js-sdk-miniapp","version":"1.8.37","description":"arms rum javascript sdk","main":"./miniapp.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","pure-build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","postcommit":"npm run lint","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out","proxy2local":"npx f2etest-local start --port 1080 --server http://f2etest.alibaba-inc.com/ --name maixi.fl --apikey 1c0ca34a085e4c69af399c0ba699b543","f2etest":"npm run proxy2local && mocha --no-timeouts test/f2etest/** && npm run stop_proxy","stop_proxy":"npx f2etest-local stop","dev_local":"DEV=1 LOCAL=1 node ./bin/pack","test-miniapp":"nyc mocha --timeout 5000 --reporter spec 'test/unittest/**/**.spec.js'","test-miniapp-watch":"mocha --reporter spec 'test/unittest/**/**.spec.js' --watch"},"author":{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","buffer":"4","chai":"^4.2.0","chai-as-promised":"^7.1.1","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","expect.js":"^0.3.1","express":"~4.15.3","fs-extra":"~4.0.2","globby":"^8.0.1","karma":"~1.7.1","karma-browserify":"~5.2.0","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","karma-coverage":"~1.1.1","mocha":"~5.1.1","node-fetch":"^2.1.2","nyc":"^13.1.0","power-assert":"~1.4.4","strip-comments":"^1.0.2","uglify-js":"~3.1.7","watchify":"~3.9.0","browserify-istanbul":"~3.0.1","jwebdriver":"^2.2.5","rollup":"~1.1.0","rollup-plugin-commonjs":"~9.2.0","rollup-plugin-node-resolve":"~4.0.0","rollup-plugin-uglify":"~6.0.0"},"keyword":["retcode","log"],"_id":"@arms/js-sdk-miniapp@1.8.37","gitHead":"795358887bd52bade7c546c457ddf166ade54d94","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-2l0IDeOyr6DbAuyE0j5bTaN6Yj70bz96jdYbVOd2PDJN0WuCzZ/HSiaemmLBm3jS3C1lFuLWod9z+j2qHz1bTQ==","shasum":"d1fc196e96d9d6b5aaa665f5d029b37bc1f98eba","tarball":"https://registry.npmjs.org/@arms/js-sdk-miniapp/-/js-sdk-miniapp-1.8.37.tgz","fileCount":53,"unpackedSize":448116,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDioX9s8WffwfxmwkeHS9qtxWt2fI3IS92xnNHkIKO68gIgeKr5FlTXMNUsAXXsQmXrMyUEhTTfG9vKFsEabyIdEac="}]},"_npmUser":{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},"directories":{},"maintainers":[{"name":"fengsir","email":"fengsir@live.com"},{"name":"yunjin4","email":"xiashujin.xsj@alibaba-inc.com"},{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},{"name":"yangling1996","email":"yl260087@alibaba-inc.com"},{"name":"yunyi-alibaba","email":"ly403664@alibaba-inc.com"},{"name":"alibaba_rum_harmony","email":"yanglanxin.ylx@alibaba-inc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/js-sdk-miniapp_1.8.37_1748259312590_0.8965036627636813"},"_hasShrinkwrap":false}},"time":{"created":"2024-12-26T06:33:39.411Z","modified":"2025-05-26T11:35:13.072Z","1.8.36-beta.14":"2024-12-26T06:33:39.712Z","1.8.37":"2025-05-26T11:35:12.784Z"},"author":{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},"license":"ISC","description":"arms rum javascript sdk","maintainers":[{"name":"fengsir","email":"fengsir@live.com"},{"name":"yunjin4","email":"xiashujin.xsj@alibaba-inc.com"},{"name":"guangli.fj","email":"guangli.fj@alibaba-inc.com"},{"name":"yangling1996","email":"yl260087@alibaba-inc.com"},{"name":"yunyi-alibaba","email":"ly403664@alibaba-inc.com"},{"name":"alibaba_rum_harmony","email":"yanglanxin.ylx@alibaba-inc.com"}],"readme":"# ARMS RUM\n\n```\n    ___     ____   __  ___ _____    ____   __  __ __  ___\n   /   |   / __ \\ /  |/  // ___/   / __ \\ / / / //  |/  /\n  / /| |  / /_/ // /|_/ / \\__ \\   / /_/ // / / // /|_/ / \n / ___ | / _, _// /  / / ___/ /  / _, _// /_/ // /  / /  \n/_/  |_|/_/ |_|/_/  /_/ /____/  /_/ |_| \\____//_/  /_/   \n```\n\n## 开始使用\n\n### 申请阿里云前端监控PID\n\n阿里云业务实时监控服务(ARMS)前端监控平台专注于 Web 端体验数据监控，从页面打开速度（测速）、页面稳定性（JS Error）和外部服务调用成功率（API）这三个方面监测 Web 页面的健康度。\n\n您可以在[这里](https://help.aliyun.com/document_detail/58652.html)了解我们的应用.\n\n在接入之前请确保您已经申请待接入**站点唯一PID**\n\n如果需要申请PID，可以参看[帮助文档](https://help.aliyun.com/document_detail/58663.html)\n\n\n\n### cdn引入\n在页面头部或 body 第一行引入脚本：\n\n```html\n<script>\n!(function(c,b,d,a){c[a]||(c[a]={});c[a].config={pid:\"站点唯一ID\"};\nwith(b)with(body)with(insertBefore(createElement(\"script\"),firstChild))setAttribute(\"crossorigin\",\"\",src=d)\n})(window,document,\"https://retcode.alicdn.com/retcode/bl.js\",\"__bl\");\n</script>\n```\n\n### npm包引入\n\n```javascript\nconst BrowerLogger = require('@arms/js-sdk');\n// BrowserLogger.singleton(conf) conf传入config配置\nconst __bl = BrowerLogger.singleton({\n    pid: 'your-project-id',\n    imgUrl: 'https://arms-retcode.aliyuncs.com/r.png?', // 设定日志上传地址,新加坡部署可选`https://arms-retcode-sg.aliyuncs.com/r.png?`\n    // 其他config配置\n});\n```\n\n- 默认会开启 `fetch` 和 `XMLHttpRequest` 的请求上报，以及页面 JS Error 的上报；\n- 站点 ID 会在 ARMS 后台创建的时候自动生成，是当前站点的唯一标识\n\n### config配置项\n\n| 参数名        | 类型       | 描述                                                              | 是否必须 | 默认值            |\n|:--------------|:-----------|:------------------------------------------------------------------|:---------|:------------------|\n| pid           | `String`   | 项目唯一 ID，由 ARMS 在创建站点时自动生成                         | 是       | 无                |\n| page          | `String`   | 页面名称，默认取当前页面 URL 的关键部分                           | 否       | `host + pathname` |\n| sample        | `Integer`  | 日志采样配置，值`1/10/100`，性能和成功API日志按照`1/sample`采样，即`1`表示`100%采样`,`10`表示`10%采样`，`100`表示`1%`采样 | 否 | `1` | \n| enableSPA     | `Boolean`  | 是否监听页面的 hashchange 事件并重新上报 PV，适用于单页面应用场景 | 否       | `false`           |\n| parseHash     | `Function` | 配合 enableSPA 使用，详情见下文                                   | 否       | 见下文            |\n| disableHook   | `Boolean`  | 是否禁用 AJAX 请求监听，默认会监听并用于 API 调用成功率上报       | 否       | `false`           |\n| autoSendPv    | `Boolean`  | 是否初始化后自动发送 PV，默认会自动发送                           | 否       | `true`            |\n| sendResource  | `Boolean`  | 是否上报资源数据，默认不上报                                    | 否       | `false`            |\n| ignoreUrlCase | `Boolean`  | 是否忽略page url大小写，默认忽略                                 | 否      | `true`            |\n| urlHelper | *          | URL 规整规则，详情见下文                                          | 否       | 见下文            |\n| apiHelper | *          | API 规整规则，详情见下文                                           | 否       | 见下文            |\n\n**部分设置项详细说明**\n\n#### 1. `parseHash` 将URL hash 解析为page的方法\n\n此参数用于单页面应用场景中，在设置了 `enableSPA` 为 `true` 的前提下，页面触发 hashchange 事件时，将 URL hash 解析为 page 字段的方法。\n\n默认值是一个简单的字符串处理方法：\n\n```js\nfunction (hash) {\n    var page = hash ? hash.replace(/^#/, '').replace(/\\?.*$/, '') : '';\n    return page || '[index]';\n}\n```\n\n**此项一般情况下不需要修改**，不过如果需要在上报时使用自定义的页面名，或者 URL 的 hash 比较复杂（ _例如 /aaa/bbb/:id?t=xxx_ ），则需要修改此配置项。\n\n示例：\n\n```js\n// 定义页面 hash 和 page 的映射关系\nvar PAGE_MAP = {\n    '/': '首页',\n    '/contact': '联系我们',\n    '/list': '数据列表',\n    // ...\n};\n\n// 页面 onload 后调用 SDK 方法\nwindow.addEventListener('load', function (e) {\n    // 调用 setConfig 方法修改 SDK 配置项\n    __bl.setConfig({\n        parseHash: function (hash) {\n            key = hash.replace(/\\?.*$/, '');\n            return PAGE_MAP[key] || '未知页面';\n        }\n    });\n});\n```\n\n#### 2. `urlHelper` URL规整规则，代替原`ignoreUrlPath`\n\n在页面 URL 类似于 `http://xxx.com/projects/123456` 这样的场景中（projects 后面紧跟的是项目 id），\n如果将 `xxx.com/projects/123456` 作为 page 上报，会导致在数据查看时页面无法聚成一类，所以需要过滤掉这些非关键字符。\n\n此设置项只在自动获取页面URL作为page时才会生效，如果手动调用 `setPage` 或 `setConfig` 方法修改过 page，或者设置了 `enableSPA` 的值为 `true`，则此设置项无效。\n\n默认值是一个数组，**一般情况下不需要修改**：\n\n```js\n[\n    // 将所有 path 中的数字变成 *\n    {rule: /\\/([a-z\\-_]+)?\\d{2,20}/g, target: '/$1**'},\n    // 去掉 url 末尾的'/'\n    /\\/$/\n]\n```\n\n此设置项的默认值会过滤掉类似 `xxxx/123456` 后面的数字，比如 `xxxx/00001` 和 `xxxx/00002` 都会变成 `xxxx/**`。\n\n`urlHelper` 的值可以是多种类型，用法分别为：\n\n- `String` 或 `RegExp`: 将匹配到的字符串去掉；\n- `Object<rule, target>`: 对象包含两个 key，分别是 rule 和 target，作为 JS 字符串的 `String::replace` 方法的入参；\n- `Function`: 将原字符串作为入参执行方法，将执行结果作为 page；\n- `Array`: 用于设置多条规则，每条子规则的都可以是上述类型之一。\n\n#### 3. `apiHelper` api规整规则，代替原`ignoreApiPath`\n\n用于在自动上报 API 的时候过滤掉接口 URL 中的非关键字符，用法及含义同 `urlHelper`\n\n默认值是一个对象，**一般情况下不需要修改**：\n\n```js\n{rule: /(\\w+)\\/\\d{2,}/g, target: '$1'}\n```\n\n此设置项的默认值会过滤掉接口 URL 中类似 `xxxx/123456` 后面的数字。\n\n#### 4. `config.sendResource` 资源上报, 用于慢会话追踪\n\n是否上报资源数据，默认不上报. 如需启用慢会话追踪，需要开启此项(注: 目前新加坡region暂不支持此功能).\n\n开启上报后，会依据[apdex](https://www.apdex.org/)选择性上报资源数据\n    \n- Satisfied(0-2s): 不上报 \n- Tolerating(2-8s): 50%上报\n- Frustrated(>8s): 100%上报\n\n## API 接口\n\n### 通用 API\n\n\n#### 1. @static singleton() 获取单例对象\n\n***该方法只适用于npm引入**\n\n调用参数说明：`BrowerLogger.singleton(config,prePipe)`\n\n静态方法，返回一个单例对象，只在第一次调用时传入的config,prePipe生效，之后调用只返回已经生成的实例：\n\n\n| 参数 | 类型     | 描述              | 是否必须 | 默认值 |\n|:-----|:---------|:------------------|:---------|:-------|\n| config  | `Object` | 站点配置, 其他配置查看 #config配置项 | 是       | -      |\n| prePipe | `Array` | 预上报内容| 否       | -      |\n\n此方法可以用于在应用入口初始化 SDK，也可以在每次调用时获取实例。\n\n\n#### 2. `setConfig()` 修改配置项\n\n用于在 SDK 初始完成后重新修改部分配置项，具体配置请参照 SDK 配置项。\n\n调用参数说明：`__bl.setConfig(next)`\n\n| 参数 | 类型     | 描述                   | 是否必须 | 默认值 |\n|:-----|:---------|:-----------------------|:---------|:-------|\n| next | `Object` | 需要修改的配置项以及值 | 是       | -      |\n\n示例：修改 disableHook 禁用 API 自动上报\n\n```js\n__bl.setConfig({\n    disableHook: true\n});\n```\n\n#### 3. setPage() 设置当前页面的page name\n\n用于重新设置页面的 page（默认会触发重新上报 PV），此接口一般在单页面应用中会用到。\n\n调用参数说明：`__bl.setPage(next, sendPv)`\n\n| 参数   | 类型      | 描述                   | 是否必须 | 默认值 |\n|:-------|:----------|:-----------------------|:---------|:-------|\n| page   | `String`  | 新的page name          | 是       | -      |\n| sendPv | `Boolean` | 是否上报PV，默认会上报 | 否       | `true` |\n\n示例：\n\n```javascript\n// 设置当前页面的 page name 为当前的 URL hash，并重新上报 PV\n__bl.setPage(location.hash);\n\n// 仅设置当前页面的 page 为'homepage'，但不触发 PV 上报\n__bl.setPage('homepage', false);\n```\n\n#### 4. `removeHook()` 移除当前实例上的自动 API 上报\n\n> 如果需要手动上报 API 监听数据，则可以调用此方法移除自动上报监听（推荐在初始化配置中直接设置 `disableHook` 为 true）\n\n```javascript\n__bl.removeHook();\n```\n\n#### 5. `addHook(isForce)`  在当前实例上挂载 API 监听的 hook\n\n> 用于多实例的场景，将 API 监听的 hook 从一个实例上移除后，挂载到另一个实例上，如果 `isForce` 为 true，则强制将挂载实例指向自己\n\n```javascript\n__bl.addHook(true);\n```\n\n#### 6. `createInstance(config)` 创建一个新的 BrowserLogger 实例\n\n> 创建一个新的实例，新的实例默认继承当前实例的 pid，用于单页面应用需要分区块上报的场景\n\n```javascript\n// 创建一个新的实例\nvar sdk2 = __bl.createInstance({\n    tag: 'sdk2',\n    page: 'another_page' // 如果设置了 page，则会自动上报一次 PV\n    // ...\n});\n```\n\n### 数据上报接口\n\n#### 1. api() 接口调用成功率上报\n\n此接口用于上报页面的 API 调用成功率，SDK 默认会监听页面的 AJAX 请求并调用此接口上报；\n如果页面的数据请求方式是 JSONP 或者其它自定义方法（比如客户端 SDK 等），可以在数据请求方法中调用 `api()` 方法手动上报。\n\n另外，如果要调用此接口，建议在 SDK 配置项中将 `disabledHook` 设置为 true，具体配置请参照 SDK 配置项。\n\n调用参数说明：`__bl.api(api, success, time, code, msg)`\n\n| 参数    | 类型            | 描述         | 是否必须 | 默认值 |\n|:--------|:----------------|:-------------|:---------|:-------|\n| api     | `String`        | 接口名       | 是       | -      |\n| success | `Boolean`       | 是否调用成功 | 是       | -      |\n| time    | `Number`        | 接口耗时     | 是       | -      |\n| code    | `String/Number` | 返回码       | 否       | ''     |\n| msg     | `String`        | 返回信息     | 否       | ''     |\n\n示例： \n\n```javascript\nvar begin = Date.now(),\n    url = '/data/getTodoList.json';\n\najax(url, {id: 123456}).then(function (result) {\n    var time = Date.now() - begin;\n    // 上报接口调用成功\n    window.__bl && __bl.api(url, true, time, result.code, result.msg);\n    // do something ....\n}).catch(function (error) {\n    var time = Date.now() - begin;\n    // 上报接口调用失败\n    window.__bl && __bl.api(url, false, time, 'ERROR', error.message);\n    // do something ...\n});\n```\n\n#### 2. error() 错误信息上报\n\n此接口用于上报页面中的 JS 错误或者使用者想要关注的异常；\n\n一般情况下，SDK 会监听页面全局的 Error 并调用此接口上报异常信息，但由于浏览器的同源策略往往获取不到错误的具体信息，这时就需要使用者手动上报。\n\n调用参数说明：`__bl.error(error, pos)`\n\n| 参数         | 类型     | 描述                              | 是否必须 | 默认值 |\n|:-------------|:---------|:----------------------------------|:---------|:-------|\n| error        | `Error`  | JS 的 Error 对象                  | 是       | -      |\n| pos          | `Object` | 错误发生的位置，包含以下 3 个属性 | 否       | -      |\n| pos.filename | `String` | 错误发生的文件名                  | 否       | -      |\n| pos.lineno   | `Number` | 错误发生的行数                    | 否       | -      |\n| pos.colno    | `Number` | 错误发生的列数                    | 否       | -      |\n\n示例：监听页面的 JS Error 并上报\n\n```js\nwindow.addEventListener('error', function (ex) {\n    // 一般事件的参数中会包含 pos 信息\n    window.__bl && __bl.error(ex.error, ex);\n});\n```\n\n示例2： 上报一个自定义的错误信息\n\n```js\nwindow.__bl && __bl.error(new Error('发生了一个自定义的错误'), {\n    filename: 'app.js', \n    lineno: 10, \n    colno: 15\n});\n```\n\n### 3. speed() 自定义测速上报\n\n此接口用于上报页面中的一些自定义的关键时间节点；\n\n调用参数说明：`__bl.speed(point, time)`\n\n| 参数     | 类型      | 描述                                            | 是否必须 | 默认值                   |\n|:---------|:----------|:------------------------------------------------|:---------|:-------------------------|\n| point    | `Enum`    | 测速关键字，必须是 s0 ~ s10                     | 是       | -                        |\n| time     | `Number`  | 耗时(毫秒)，默认是当前时间 - 页面起始时间       | 否       | `Date.now() - startTime` |\n| forceSPA | `Boolean` | 只在 SPA 中有效，上报数据时 page 是否使用子页面 | 否       | false                    |\n\n示例：\n```js\n__bl.speed('s0');\n\n__bl.speed('s1', 1024);\n```\n\n### 4. sum() 求和统计\n\n此接口用于统计业务中的某些事情发生的次数\n\n调用参数说明：`__bl.sum(key, value)`\n\n| 参数  | 类型     | 描述                   | 是否必须 | 默认值 |\n|:------|:---------|:-----------------------|:---------|:-------|\n| key   | `String` | 事件名                 | 是       | -      |\n| value | `Number` | 单次累加上报量，默认 1 | 否       | 1      |\n\n示例：\n```js\n__bl.sum('event-a');\n\n__bl.sum('event-b', 3);\n\n__bl.sum('group-x::event-c', 2);\n```\n\n### 4. avg() 求平均统计\n\n此接口用于统计业务场景中某些事情发生的平均次数或平均值\n\n调用参数说明：`__bl.avg(key, value)`\n\n| 参数  | 类型     | 描述               | 是否必须 | 默认值 |\n|:------|:---------|:-------------------|:---------|:-------|\n| key   | `String` | 事件名             | 是       | -      |\n| value | `Number` | 统计上报量，默认 0 | 否       | 0      |\n\n示例：\n```js\n__bl.avg('event-a', 1);\n__bl.avg('event-b', 3);\n\n__bl.avg('events::event-c', 10);\n__bl.avg('speed::event-d', 142.42);\n```\n\n### 5. percent() 百分比统计\n\n此接口用于统计业务场景中某一类事件下的各自占比\n\n调用参数说明：`__bl.percent(key, subkey, value)`\n\n| 参数   | 类型     | 描述                   | 是否必须 | 默认值 |\n|:-------|:---------|:-----------------------|:---------|:-------|\n| key    | `String` | 事件名                 | 是       | -      |\n| subkey | `String` | 事件成员               | 是       | -      |\n| value  | `Number` | 单次累加上报量，默认 0 | 否       | 0      |\n\n示例：\n```js\n__bl.percent('gender', 'm', 1);\n__bl.percent('gender', 'f', 3);\n```\n\n## FAQ\n\n### 1. 单页面应用 (SPA) 如何分开统计 PV?\n\n在 SPA（ _Single Page Application_ ）中，页面只会刷新一次；传统的方式只会在页面加载完成后上报一次 PV，而无法统计到各个子页面的 PV，也无法让其它类型的日志聚类到对应的子页面。\n\nSDK 提供了两种 SPA 页面的处理方式：\n\n#### 1. 开启 SPA 自动解析\n\n此方法适用于大部分以 URL hash 作为路由的单页面应用场景。\n\n在初始化的配置项中，设置 `enableSPA` 为 `true`，即会开启页面的 hashchange 事件监听（触发重新上报 PV），并将 URL hash 作为其它数据上报中的 page 字段；\n\n另外，与 `enableSPA` 相配套的还有 `<Function>parseHash`，参见 SDK 配置项\n\n#### 2. 完全手动上报\n\n此方法可用于所有的单页面应用场景，如果方法一无法满足，可用此方法。\n\nSDK 提供了 `setPage` 方法来手动更新数据上报时的 page name，调用此方法时，默认会重新上报页面 PV。\n\n示例：\n\n```js\n// 监听应用路由变更事件\napp.on('routeChange', function (next) {\n    __bl.setPage(next.name);\n});\n```\n\n另外，对于页面初始化完成后的第一次 PV 上报，如果也想要手动控制，可在配置项中设置 `autoSendPv` 为 `false`，然后在应用初始化完成后，调用 `setPage`\n\n\n### 2. 解决 JS Error 跨域获取不到的问题\n\n由于浏览器的安全策略，SDK 无法获取到其它 host 下的 JS Error 的错误信息，解决办法：\n\n在 script 标签上添加 `crossorigin` 属性：\n```html\n<script src=\"xxx\" crossorigin></script>\n```\n以上只能解决部分问题，实际情况下还是无法获取具体的错误信息，另一种办法就是用户在自己的 JS 中监听 JS Error，然后上报：\n```js\nwindow.addEventListener('error', function (e) {\n    window.__bl && __bl.errorHandler(e);\n});\nwindow.addEventListener('unhandledrejection', function (e) {\n    window.__bl && __bl.errorHandler(e);\n});\n```\n\n### 3. 如何在 SDK 初始化前预上报数据？\n\n- cdn引入\n\n场景一：\n\n在页面刚刚加载时，有一些数据需要上报，此时 SDK 可能还未初始化完成（或者不确定是否初始化完成）。\n\n场景二：\n\n在应用的初始化逻辑中调用 `setConfig` 方法，但由于 SDK 是异步加载的，此时可能还未加载完成。\n\n解决办法：\n\nSDK 在 `__bl` 对象上增加了一个 `pipe` 属性，用于将预调用的信息缓存到此变量中，例如：\n\n```js\n__bl.pipe = [\n    // 将当前页面的 html 也作为一个 API 上报\n    ['api', '/index.html', true, performance.now, 'SUCCESS'],\n    \n    // SDK 初始化完成后即开启 SPA 自动解析\n    ['setConfig', {enableSPA: true}]\n];\n```\n\n如果只上报单条数据，也可以直接写成：\n\n```js\n__bl.pipe = ['msg', '我是另一个普通的消息'];\n```\n\n其中数组的第 0 个表示方法名，后面依次是入参。\nSDK 初始化完成后，就会将预先挂载到 `window.__bl.pipe` 上的方法及参数依次调用。\n\n_注意：在 SDK 初始化完成前，如果多次设置 `__bl.pipe` 的值，只会以最后一次为准。_\n\n另外，`pipe` 也可以用于 SDK 初始化完成后调用（支持 IE9 及以上），如果不能确定 SDK 是否初始化完成，又不想添加太多的判断逻辑，可以使用此方式\n\n场景：单页面应用中，设置 `autoSend: false` 后，在应用初始化后上报第一次 PV，此时并不确定 SDK 是否初始化完成\n\n```js\n// 设置页面 name 为'homepage'，并且上报 PV\n__bl.pipe = ['setPage', 'homepage'];\n```\n\n- npm 引入\n\n场景：\n\n有部分逻辑在调用`BrowserLogger.singleton()`之前执行，有一些数据想上报\n\n```js\n\nconst BrowerLogger = require('@arms/js-sdk');\n\n// 与cdn的pipe结构一致\nconst pipe = [\n    // 将当前页面的 html 也作为一个 API 上报\n    ['api', '/index.html', true, performance.now, 'SUCCESS'],\n    \n    // SDK 初始化完成后即开启 SPA 自动解析\n    ['setConfig', {enableSPA: true}]\n];\n\nconst __bl = BrowserLogger.singleton({pid:'站点唯一ID'},pipe);\n\n```\n\n## 小程序\n\n基础类的小程序监控，适用于钉钉、支付宝、微信、字节跳动、百度、京东等各类小程序，并支持Taro，Uniapp等跨端框架构建目标为上述小程序的场景。\n\n**参考文档**\n> [eapp](https://open-doc.dingtalk.com/microapp/dev/framework-app)\n> [微信小程序开发](https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/app.html)\n\n###1.开始使用\n\n```ts\n    /**\n     * @desc 监控sdk初始化,debug模式仅打印日志，不发送日志\n     * 以钉钉中的用法为例\n     * monitor.js\n     */\n    import Logger from '@arms/js-sdk/miniapp';\n    module.exports = Logger.singleton({\n        debug: true, // 本地开发不发送日志，但打印日志\n        pid: 'your-project-id',\n        // （可选）基础小程序监控需要手动传入rpc\n        sendRequest: (url) => {\n            dd.httpRequest({\n                url,\n                method: 'GET'\n            });\n        },\n        // （可选）拦截不想上报的数据，返回null，undefined，0， false等，会取消本次上报\n        beforeReport: (data) => {\n            if (data.t === 'api' && data.time > 20000) {\n                return\n            }\n            return data;\n        },\n        // (可选)需要手动传入获取当前页面路径的方法\n        getCurrentPage: () => {\n            if (typeof getCurrentPages !== 'undefined' && typeof getCurrentPages === 'function') {\n                var pages = (getCurrentPages() || []);\n                var pageLength = pages.length;\n                var currPage = pages[pageLength - 1];\n                return (currPage && currPage.route) || null;\n            }\n        }\n    });\n    /**\n     * 启动页 app.js\n     */\n    import logger from './monitor';\n    App({\n        onLaunch(options) {},\n        onShow(options) {},\n        onError(msg) {},\n    });\n```\n\n### 2. 通用API\n\napi示例请参考 **Getting Started**\n\n| 方法  | 参数 |  备注      | 使用场景举例 | \n| -------- | -------- | -------- | -------- |\n| setCommonInfo  | {[key: string]: string;}  | 设置日志基础字段 | 灰度 |\n| appLaunch  | {}  | app launch打点 |  |\n| appShow  | {}  | app show打点 |  |\n| pageShow  | {}  | page show打点，发送pv数据 |  |\n| pageHide  | {}  | page hide打点，发送health数据 |  |\n| error  | string|object  | 错误日志打点 |  |\n\n大部分日志上报api见上面的示例即可\n\n### 3. 说明\n> 小程序系列监控的项目必须符合标准小程序规范: App、Page。\n即App层有 onLaunch、onShow、onError;\nPage层有 onShow、onHide、onUnload。\n\n","readmeFilename":"README.md"}