{"_id":"alife-logger","_rev":"105-717c5f970583a2284cc37451846bc683","name":"alife-logger","description":"retcode cloud sdk","dist-tags":{"latest":"1.8.30","alpha":"1.8.13-alpha","test":"1.4.7-alpha.1","wx":"1.4.7-alpha.2","beta":"1.8.28-beta.2"},"versions":{"1.1.14":{"name":"alife-logger","version":"1.1.14","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},{"name":"yufeng.wjj","email":"yufeng.wjj@alibaba-inc.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"4489a61600c8248b834bd40254e4228f82fd8bb3","_id":"alife-logger@1.1.14","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-wx1fuO0zVOeBUQyNzMe/5rL7OcmZsRAtHwjlxHgiJmeqQny7YgHjvu+OfQeBg7AAWKZU3SZQDLaNXAAL3TI38w==","shasum":"6669873ab12f7f40f398156b525053134d166e3c","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.1.14.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBpHwx8eVFuoYEygibyZq2c+qJt8IhXB2HO0bnP60hq1AiEA1pIdKMWrU10Wgi3UjXhweqImOiCVwUmx8rb4QEfmLQk="}]},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger-1.1.14.tgz_1517472272321_0.7530247368849814"},"directories":{}},"1.2.0":{"name":"alife-logger","version":"1.2.0","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"josephku","email":"jawnkuin@gmail.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"fa7f347f5baa2254d1c89b0b01b0d8d0d5c02cde","_id":"alife-logger@1.2.0","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-t9KAt34LrixGG6iXRSlCeLxiNa8rSojWN7Jigm4jOrjgfp92RRmHt+OjwktNl7IduqK5BK7gfu+Kth1C4CRM6Q==","shasum":"82480955cb52b49f0432859036ee6cca6fb0b873","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFaOOvJUWpyS+BRWQZrkASYiwi9sfg7++ZSIJeYk+hL3AiEA1Z1YWhFQxbdIJXpAO756aa2M8yqedH1TDU/e07AzeBs="}]},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger-1.2.0.tgz_1517473481718_0.7413785473909229"},"directories":{}},"1.2.1":{"name":"alife-logger","version":"1.2.1","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"josephku","email":"jawnkuin@gmail.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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| enableSPA     | `Boolean`  | 是否监听页面的 hashchange 事件并重新上报 PV，适用于单页面应用场景 | 否       | `false`           |\n| parseHash     | `Function` | 配合 enableSPA 使用，详情见下文                                   | 否       | 见下文            |\n| disableHook   | `Boolean`  | 是否禁用 AJAX 请求监听，默认会监听并用于 API 调用成功率上报       | 否       | `false`           |\n| autoSendPv    | `Boolean`  | 是否初始化后自动发送 PV，默认会自动发送                           | 否       | `true`            |\n| ignoreUrlPath | *          | URL 过滤规则，详情见下文                                          | 否       | 见下文            |\n| ignoreApiPath | *          | 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. `ignoreUrlPath` URL 过滤规则\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    {rule: /(\\w+)\\/\\d{4,}/g, target: '$1'},\n    {rule: /([^\\/]\\/[^\\/]+)(\\/[^\\/]+)\\/.*$/, target: '$1$2/'}\n]\n```\n\n此设置项的默认值会过滤掉类似 `xxxx/123456` 后面的数字，以及超过 3 层 `/` 的 URL path，比如 `xxx.com/aaa/bbb/ccc.html` 只会取 `xxx.com/aaa/bbb`。\n\n`ignoreUrlPath` 的值可以是多种类型，用法分别为：\n\n- `String` 或 `RegExp`: 将匹配到的字符串去掉；\n- `Object<rule, target>`: 对象包含两个 key，分别是 rule 和 target，作为 JS 字符串的 `String::replace` 方法的入参；\n- `Function`: 将原字符串作为入参执行方法，将执行结果作为 page；\n- `Array`: 用于设置多条规则，每条子规则的都可以是上述类型之一。\n\n#### 3. `config.ignoreApiPath` API 过滤规则\n\n用于在自动上报 API 的时候过滤掉接口 URL 中的非关键字符，用法及含义同 `ignoreUrlPath`\n\n默认值是一个对象，**一般情况下不需要修改**：\n\n```js\n{rule: /(\\w+)\\/\\d{4,}/g, target: '$1'}\n```\n\n此设置项的默认值会过滤掉接口 URL 中类似 `xxxx/123456` 后面的数字。\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"d2fd195fce53c863a99bacacb4c1feb18fd6b24f","_id":"alife-logger@1.2.1","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-tqNhcslZcSCWdTo8Juq8Pz4Nedrk8wENf8Lhfq0OxIM0H3iTlFTV1o2ak/NyTG4M9I9z/rAfamVTXoJxnODttw==","shasum":"02ca8ea2d1afbe7d52a20a1eb29e134c3fbf1b53","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.1.tgz","fileCount":22,"unpackedSize":205644,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/WFB3GttASRgJKWO6EXMq32krXqzSzUBOa/LNxg3l6wIgC/t1/wUntAgfDKRohgHInHs83O8Ixt8hr4iOcmBvicM="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.1_1518340788197_0.7485993539631033"},"_hasShrinkwrap":false},"1.2.1-alpha":{"name":"alife-logger","version":"1.2.1-alpha","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"josephku","email":"jawnkuin@gmail.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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| enableSPA     | `Boolean`  | 是否监听页面的 hashchange 事件并重新上报 PV，适用于单页面应用场景 | 否       | `false`           |\n| parseHash     | `Function` | 配合 enableSPA 使用，详情见下文                                   | 否       | 见下文            |\n| disableHook   | `Boolean`  | 是否禁用 AJAX 请求监听，默认会监听并用于 API 调用成功率上报       | 否       | `false`           |\n| autoSendPv    | `Boolean`  | 是否初始化后自动发送 PV，默认会自动发送                           | 否       | `true`            |\n| ignoreUrlPath | *          | URL 过滤规则，详情见下文                                          | 否       | 见下文            |\n| ignoreApiPath | *          | 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. `ignoreUrlPath` URL 过滤规则\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    {rule: /(\\w+)\\/\\d{4,}/g, target: '$1'},\n    {rule: /([^\\/]\\/[^\\/]+)(\\/[^\\/]+)\\/.*$/, target: '$1$2/'}\n]\n```\n\n此设置项的默认值会过滤掉类似 `xxxx/123456` 后面的数字，以及超过 3 层 `/` 的 URL path，比如 `xxx.com/aaa/bbb/ccc.html` 只会取 `xxx.com/aaa/bbb`。\n\n`ignoreUrlPath` 的值可以是多种类型，用法分别为：\n\n- `String` 或 `RegExp`: 将匹配到的字符串去掉；\n- `Object<rule, target>`: 对象包含两个 key，分别是 rule 和 target，作为 JS 字符串的 `String::replace` 方法的入参；\n- `Function`: 将原字符串作为入参执行方法，将执行结果作为 page；\n- `Array`: 用于设置多条规则，每条子规则的都可以是上述类型之一。\n\n#### 3. `config.ignoreApiPath` API 过滤规则\n\n用于在自动上报 API 的时候过滤掉接口 URL 中的非关键字符，用法及含义同 `ignoreUrlPath`\n\n默认值是一个对象，**一般情况下不需要修改**：\n\n```js\n{rule: /(\\w+)\\/\\d{4,}/g, target: '$1'}\n```\n\n此设置项的默认值会过滤掉接口 URL 中类似 `xxxx/123456` 后面的数字。\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"d2fd195fce53c863a99bacacb4c1feb18fd6b24f","_id":"alife-logger@1.2.1-alpha","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-FcfN8kUktnac3MhTMWe3KnEH6cJ7samP1K899io/zOXXP8p5zs/3E/lqLoZv0CMbNfQztUdWkFCRazQ8gTh+jg==","shasum":"4fdd838c66efc938e6f787fb4c5ca36c5b34963a","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.1-alpha.tgz","fileCount":22,"unpackedSize":205725,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDcYOSP12Fnu3ciqpXEbG2LGF/IdIkA3CQU3kr5pxdf4AIhAIQNOx0OliP19U53X7pYK3VtOtvezyKRVWXrsN+1Ewc3"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.1-alpha_1518347619157_0.9590949662629777"},"_hasShrinkwrap":false},"1.2.1-alpha2":{"name":"alife-logger","version":"1.2.1-alpha2","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"josephku","email":"jawnkuin@gmail.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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| enableSPA     | `Boolean`  | 是否监听页面的 hashchange 事件并重新上报 PV，适用于单页面应用场景 | 否       | `false`           |\n| parseHash     | `Function` | 配合 enableSPA 使用，详情见下文                                   | 否       | 见下文            |\n| disableHook   | `Boolean`  | 是否禁用 AJAX 请求监听，默认会监听并用于 API 调用成功率上报       | 否       | `false`           |\n| autoSendPv    | `Boolean`  | 是否初始化后自动发送 PV，默认会自动发送                           | 否       | `true`            |\n| ignoreUrlPath | *          | URL 过滤规则，详情见下文                                          | 否       | 见下文            |\n| ignoreApiPath | *          | 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. `ignoreUrlPath` URL 过滤规则\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    {rule: /(\\w+)\\/\\d{4,}/g, target: '$1'},\n    {rule: /([^\\/]\\/[^\\/]+)(\\/[^\\/]+)\\/.*$/, target: '$1$2/'}\n]\n```\n\n此设置项的默认值会过滤掉类似 `xxxx/123456` 后面的数字，以及超过 3 层 `/` 的 URL path，比如 `xxx.com/aaa/bbb/ccc.html` 只会取 `xxx.com/aaa/bbb`。\n\n`ignoreUrlPath` 的值可以是多种类型，用法分别为：\n\n- `String` 或 `RegExp`: 将匹配到的字符串去掉；\n- `Object<rule, target>`: 对象包含两个 key，分别是 rule 和 target，作为 JS 字符串的 `String::replace` 方法的入参；\n- `Function`: 将原字符串作为入参执行方法，将执行结果作为 page；\n- `Array`: 用于设置多条规则，每条子规则的都可以是上述类型之一。\n\n#### 3. `config.ignoreApiPath` API 过滤规则\n\n用于在自动上报 API 的时候过滤掉接口 URL 中的非关键字符，用法及含义同 `ignoreUrlPath`\n\n默认值是一个对象，**一般情况下不需要修改**：\n\n```js\n{rule: /(\\w+)\\/\\d{4,}/g, target: '$1'}\n```\n\n此设置项的默认值会过滤掉接口 URL 中类似 `xxxx/123456` 后面的数字。\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"d2fd195fce53c863a99bacacb4c1feb18fd6b24f","_id":"alife-logger@1.2.1-alpha2","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-OQu7VCMjvu30UC0AeGSXRDy8kTwvWS4vy5oZRw2MS7YjH1HpqmoglIsHJsnJLEtiX1/Xrxq9kE1pBq2Vb7sAfA==","shasum":"088d8fe588d37d5ee4b0ff92543de463bad1e09d","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.1-alpha2.tgz","fileCount":22,"unpackedSize":205703,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCuqBz04ls+eK+9oGJNP95BqjtTffY/RruBQvgUSpYgQgIgTwekgN6HitK2mux6HjxBkG4C3DEDNtlzAOe9+gb9wZg="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.1-alpha2_1518348244080_0.30528770103172054"},"_hasShrinkwrap":false},"1.2.2":{"name":"alife-logger","version":"1.2.2","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"josephku","email":"jawnkuin@gmail.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"9cfc7cd697d5194dc847eeb32b0f71be25a7930d","_id":"alife-logger@1.2.2","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-YUYIgPa1SN2dbrbIRDYkSjZ3abWh55aVEtw1a6fFmhnnyDQmtdlnNZDlsv1pC3zzxi/Tom2TzcFmv55ffa7bjQ==","shasum":"daa85da6f8b25e3009d87b1e14942759e7c22a75","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.2.tgz","fileCount":22,"unpackedSize":205528,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAPhcb1oaya6dNfewtc3SUDA6fL0hY2hKahN1E7AM8UXAiEAi9YhHMVq0iimYmz4MEzr6LxA6vUiHl2wUbcyPupGJWc="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.2_1518348636166_0.813398205166934"},"_hasShrinkwrap":false},"1.2.3":{"name":"alife-logger","version":"1.2.3","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"josephku","email":"jawnkuin@gmail.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"9cfc7cd697d5194dc847eeb32b0f71be25a7930d","_id":"alife-logger@1.2.3","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-au32tQKI/P/Qbb64pa9IJXmwF1eNz5yUTigMZVflTveTDGHlAyhgKKrdPJcZmWr7awOAmtFEAh8BfW6SWRqlVw==","shasum":"222f8cb0fa6887639f4e0c7c965d6edb886dd0a9","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.3.tgz","fileCount":22,"unpackedSize":205836,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC2et3W7kE0QpH3tkySsmVFjHmCkcTtMwQzzKzi7YyOyQIgQ+/xjNB6aNBwYYIcQPkVF7NqpuivcJBv2CBrQVhNHqE="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.3_1518412928322_0.8171091355999909"},"_hasShrinkwrap":false},"1.2.4":{"name":"alife-logger","version":"1.2.4","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"josephku","email":"jawnkuin@gmail.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"83965689b180ddb786c4a33c73d488e250b3ec42","_id":"alife-logger@1.2.4","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-h8l7+5uLRabkHlrpwBthrBNXfqOL5tOUaZLhjXQG5JPwEttftAWLS9crZ1pk3Z1vgD+lc0KI1UzrT4MRyjLStg==","shasum":"da6e1c999616a17664c00a8f3cda32bc1acdf076","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.4.tgz","fileCount":22,"unpackedSize":206317,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCAw7i6Fa6x9syFDf5BM1QuRWLkWUvfdAXPpjiKm5N+SAIgGNiswzsrPYPStYJ6DiLw7dntxhnR5QvZJnom7tljWCA="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.4_1519380407641_0.18544398668217799"},"_hasShrinkwrap":false},"1.2.5-alpha":{"name":"alife-logger","version":"1.2.5-alpha","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"josephku","email":"jawnkuin@gmail.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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| enableSPA     | `Boolean`  | 是否监听页面的 hashchange 事件并重新上报 PV，适用于单页面应用场景 | 否       | `false`           |\n| parseHash     | `Function` | 配合 enableSPA 使用，详情见下文                                   | 否       | 见下文            |\n| disableHook   | `Boolean`  | 是否禁用 AJAX 请求监听，默认会监听并用于 API 调用成功率上报       | 否       | `false`           |\n| autoSendPv    | `Boolean`  | 是否初始化后自动发送 PV，默认会自动发送                           | 否       | `true`            |\n| ignoreUrlCase | `Boolean`  | 是否忽略page url大小写，默认忽略                                 | 否      | `true`            |\n| ignoreUrlPath | *          | URL 过滤规则，详情见下文                                          | 否       | 见下文            |\n| ignoreApiPath | *          | 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. `ignoreUrlPath` URL 过滤规则\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`ignoreUrlPath` 的值可以是多种类型，用法分别为：\n\n- `String` 或 `RegExp`: 将匹配到的字符串去掉；\n- `Object<rule, target>`: 对象包含两个 key，分别是 rule 和 target，作为 JS 字符串的 `String::replace` 方法的入参；\n- `Function`: 将原字符串作为入参执行方法，将执行结果作为 page；\n- `Array`: 用于设置多条规则，每条子规则的都可以是上述类型之一。\n\n#### 3. `config.ignoreApiPath` API 过滤规则\n\n用于在自动上报 API 的时候过滤掉接口 URL 中的非关键字符，用法及含义同 `ignoreUrlPath`\n\n默认值是一个对象，**一般情况下不需要修改**：\n\n```js\n{rule: /(\\w+)\\/\\d{2,}/g, target: '$1'}\n```\n\n此设置项的默认值会过滤掉接口 URL 中类似 `xxxx/123456` 后面的数字。\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"23b7860a6368e0f9838b15fb6968cc63afb87df0","_id":"alife-logger@1.2.5-alpha","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-e+GCH1giEGExBP1iiIVL3BL1efpv6IVVEcBM0CQZO4L4j2RLukZWyAue4/Me9TxcD/61X6x8WDEYOZM2GD9P6w==","shasum":"f29c8a28e0d176463a77f19cad864c6f4052c45d","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.5-alpha.tgz","fileCount":22,"unpackedSize":104122,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE3CuNOoq/QxCM+gtae5WMIQFhZh4aaujKbBR1oGRMx8AiBlivuERJSHG7hZ6rD6QmGSKheOA82ywbU6t82/5VyuLQ=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.5-alpha_1522225448960_0.7713051761846024"},"_hasShrinkwrap":false},"1.2.5-alpha2":{"name":"alife-logger","version":"1.2.5-alpha2","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"josephku","email":"jawnkuin@gmail.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"94c0dbb19d766b824899b252c61e7defbcabb8c9","_id":"alife-logger@1.2.5-alpha2","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-c4NXhDVFv2HBLfQ7Xz5qFxZAvDoQwdfG8DGK6te9FAA+cE43jQjesmyTsno9qbQiE57m3tI0hLrIG9LsxceSEg==","shasum":"1f34ed99a8ee3b77ede295bc9bea2cf5397e1940","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.5-alpha2.tgz","fileCount":22,"unpackedSize":104322,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAuc3qIZjGXM3BHaG705Qkg5isLOhDB28pcg+yIaW4+RAiEAm98TnHpBTrkJfKiec8VQ9SCo2ZM+oIpag3dCbWFPjLE="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.5-alpha2_1522719805213_0.4747326179396827"},"_hasShrinkwrap":false},"1.2.5":{"name":"alife-logger","version":"1.2.5","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"josephku","email":"jawnkuin@gmail.com"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"1d9d119f70d39a2e7940cdea0c09e40f34a5bcce","_id":"alife-logger@1.2.5","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-q++ZTafcUvZA3vGTtMcYTotKUqGIwXYfqNPs0z4oXFtmc/kSHPJ7+9nWQFSHrcWW0Dzojhh1rk53yXpiEwaaYQ==","shasum":"a42fd3d11582a4c858f123ca393a759259e45b1e","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.5.tgz","fileCount":22,"unpackedSize":104490,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLnlPBIyuL51vphSc1qO3U07GrJxR+O/GK0mvmPVcjoAIgMvx5OYktCg3uPI1oAq3CUtVq1lA2BeX8x8C76hsyGoc="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.5_1523156671960_0.4512951348303311"},"_hasShrinkwrap":false},"1.2.6":{"name":"alife-logger","version":"1.2.6","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once","init":"fie commit init","pub":"node ./bin/publish","his":"fie commit out"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~14.5.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","karma":"~1.7.1","karma-browserify":"~5.1.2","karma-chrome-launcher":"~2.2.0","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~4.0.1","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"062fba36f1d8e9083f5d6444db7323351620e7a2","_id":"alife-logger@1.2.6","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-GaMitzky0kxROHcoYf9CyED4mv0WmVq+b6SNeIN5vVwsqf2EFqG2437UOiPcHDlUNHtvUjxX9s7MfubJ2JiG+w==","shasum":"c452b0e91466fc8c8b6dbf31899ca497db0fe3c5","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.6.tgz","fileCount":22,"unpackedSize":104840,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa1VeWCRA9TVsSAnZWagAA/cAP/0ritpkE9ZOv7dkckJrK\nIxjO8fY2//mw97l3ATqDjW1HaDHKPuJ+hYZeVzY4hNzp8OhzCgE9vNKJfQke\nxadhQ7pg85445q66tKNEaOyNPFAk4tMNxgbMKHg1KT+HAZQzqhVjQxg0v+qo\niOSttOr+xSDYpEdeY7iYdfLsv7SxxrnBvjzJMjRFetN6uscMJZiffGCHJRX0\ndXp517LommE5rYwk7WyunYkboopNGFkunM42a4XuxuCBdDd1qoa5tkLaUUzh\nm4CmptPtbkmyzibrfswvrcFNAcJ4G1LWGwWKH2t/95RkYybktUGKIi1BcKBr\n+F2fREsV3eJuz0YFXBn8uvDhqyKz1ojhIe+ra7t8KVlbHpOuRn7JtkThgZiv\noFMUXst/D04yiNHvlpnwkrg0X7ATKhVPAJBjnjVvBkA5oEe4YUIhcRNUPgZd\nn/wf3cVA8C09B5n8YMgCoapBBxktkWt12PCziApnUPOPgFFcyRhnBHFXMzj2\nZF64ooGL5U8hmvsPejCrbNDkpS/EsoVsdyoOOOaYb2qz4uV7VPLeZ4bJuTPN\ndvQ9fPE1K580uvy11H1RiInsP2oxHvf7CmgrQyiCDWW+dE7kmD/fEoYYlxmb\nAWS7wCk+AxSYTPW9Y06OXZAB49PEydvnWKqtLhBJcACekaYp6tO3/Hlriy4U\nLTUf\r\n=CZ7G\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAz8EtzCh+hYx0ifM+JJK7dggBu/B9FzSXHnrxHgVjguAiBQSUvBTd6FnS9RnlD3TV9p9TjJjm4mUqGKMWs89z/NWg=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.6_1523931028811_0.12021284947137945"},"_hasShrinkwrap":false},"1.2.7":{"name":"alife-logger","version":"1.2.7","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","f2etest":"npm run proxy2local && mocha --no-timeouts test/f2etest/** && npm run stop_proxy","stop_proxy":"f2etest-local stop"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"gitHead":"748df4a4da34a7c6268b8ba3ca29690d3593d0e1","_id":"alife-logger@1.2.7","_npmVersion":"6.0.0","_nodeVersion":"8.11.1","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-9Z8MPBhrg8Bckinf5X63cePLljpbvLy3ku4A1FXqEVAtM1za0JyXHrFRqY+OwtohIKzR+w9B3abjqN7pOSew6w==","shasum":"dfb45defe2cfe83ef5a5518fbc3279425a6f074f","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.7.tgz","fileCount":22,"unpackedSize":80809,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa8EHrCRA9TVsSAnZWagAAhQUP/2O/ZkUh1t+qyIJde7VI\ngfdixCuQKBaR2Ogd6quvPVVtHT0kT+ZmvwrJbLphsFyGfD0pk3MXdLnRilPr\nrowrAxC0StA81XHX2FiiGI8wL41R9nVX10EBPrRuYoHVcvY2mgWuF9ZW2Vw7\n3jkN64UnreUhynBUe1F9EHKKflAkS5kq+iWvhvo41whlt+MhJLucVmWP/T51\nYaCPYaiwJu1Jjl+cZBhLkd4bRcU/PBolensxRPdXNZRDhQymwQKW0+1iIcJk\n80oneIcQ0s5NYR1zDFwsaRsXCIa+aBySXM7uX4+tUsQ8ZRgm/WJwIC7ftdX2\nkxLjvcmUWnJtTpZuFtgdQrtvzkXgXd20elw+2OuiTh5WbmwRx+Yhp75RnLVR\no6vXUOuAOy0ZQAy4Oz3vnoM64kvt86vTScuRFOhLgixQ7FTrg2xfr5ZRgPrk\n7SvbV0X3yAryWcDq8C2k+smBfhdYRmp7p7FLjbRiCH+0cnJ4Y+ujsoYx8sIw\n3SPA69xRok5NzHA85/1pgRmVN0LNxZzxTjUkW2Onf/3zP2jjaldJiGuhqWR0\ni/T3EdWUX8xVbH2JXbEusDDLKITLl3nEEYxr/gAaDl5nSAW4RRrfe114VlZD\n7ICKX/82JSZM9/2mws670ZcAII8aasI2iN2qUoDvCmw50T9ftTHcdDrohitz\ngmYp\r\n=tdqs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHj6ONBK+J0n5S+gqmMLMRgG7SxtjRgBDlD2wab4guJhAiAwr+7EiTlk6zYvy+/Rp++GgCZJat9pOzsK2iGjumqJHQ=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.7_1525694954207_0.7742799246231835"},"_hasShrinkwrap":false},"1.2.8":{"name":"alife-logger","version":"1.2.8","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","f2etest":"npm run proxy2local && mocha --no-timeouts test/f2etest/** && npm run stop_proxy","stop_proxy":"f2etest-local stop"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"gitHead":"3c3442382468471485145b0f100d9827b358f5f6","_id":"alife-logger@1.2.8","_npmVersion":"6.0.0","_nodeVersion":"8.11.1","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-6u4ElKcZ1tC6m0CeSpZcIRY5SuaGDoUQmUKlwkhLHaWTHG1rvxXNu1v7zIY/PJ2iSd6GGRRFZKJllwmdOiZvsQ==","shasum":"06a512fe6697af6013532ae5c8b4a3e9915fa342","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.8.tgz","fileCount":22,"unpackedSize":80827,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa8+h4CRA9TVsSAnZWagAAEYUP/2LYmPFODSxNYNFnM+r4\ncCi1dGbYdwLBinD124wWFuLU04/docM46qUP59APlZu2eJlIjxk/gsVpjDaa\n0ATFNtszjpXp83iKcySCo/4rPhimQsTttCj79LVInt11Bt5AYfIzdjn5xEL4\ndkfBqbYFHUaR0icUbXO3ugzfnftiapM/LyvTuJA1lp6O0iXryfgFwy1ofBNX\nrqj9YT83JxamZXs+75eU5eU/3E0M5E/JfCJYyO6CJUo5rMRz+2S1j4/eGr60\nTL/b4M8goSQkI5Ut2XUqS/ALWOzLm8ia1xyv00TiF9kzFWXTmkig9AGDwh2O\nmPvNNphbNqu1LdMsubN6yFJQ0qJ2q12Gf6J5nlqM6hLWPIOhIg1GzK+r3W98\nX6+hX60Vmuum2udbH83sZzjW8oO/9RNyo+7o6YL5OSX5wDk3rMRGpvl27iAS\n9/cNqG+aBNC+mJs+lSLjTvn8n9lYN8mg5sZ3wI5a7pweE68OuNWWSRqkw2wP\nvGjH3kFo2FqS6bGFjOWleOvRz5Xa0uqP5n4fv0FjoLPYjEVf9muQ+28E5jX3\nix8jL3c0PB4Og7hRGw1JCsMc//2ftsoBGI+Otr9uttzIw/rj/aXJMqyv9E3q\npnB2ygBqZvc4oNZX9Atx8FKr+a4DmdyojKVz08D4WLcwxoyiPx7KPJTfaGwZ\ntFJC\r\n=sqeM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIColpUS1T204Jg2YG3PcB6KlkUvhb59hpaB2ay/0Vyi8AiA7z98E4w1sIaougl4hTpGbfL1RZERjsE6cm0C1mEGChw=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.8_1525934198850_0.1090457120330175"},"_hasShrinkwrap":false},"1.2.9-alpha":{"name":"alife-logger","version":"1.2.9-alpha","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","f2etest":"npm run proxy2local && mocha --no-timeouts test/f2etest/** && npm run stop_proxy","stop_proxy":"f2etest-local stop"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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| ignoreUrlCase | `Boolean`  | 是否忽略page url大小写，默认忽略                                 | 否      | `true`            |\n| ignoreUrlPath | *          | URL 过滤规则，详情见下文                                          | 否       | 见下文            |\n| ignoreApiPath | *          | 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. `ignoreUrlPath` URL 过滤规则\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`ignoreUrlPath` 的值可以是多种类型，用法分别为：\n\n- `String` 或 `RegExp`: 将匹配到的字符串去掉；\n- `Object<rule, target>`: 对象包含两个 key，分别是 rule 和 target，作为 JS 字符串的 `String::replace` 方法的入参；\n- `Function`: 将原字符串作为入参执行方法，将执行结果作为 page；\n- `Array`: 用于设置多条规则，每条子规则的都可以是上述类型之一。\n\n#### 3. `config.ignoreApiPath` API 过滤规则\n\n用于在自动上报 API 的时候过滤掉接口 URL 中的非关键字符，用法及含义同 `ignoreUrlPath`\n\n默认值是一个对象，**一般情况下不需要修改**：\n\n```js\n{rule: /(\\w+)\\/\\d{2,}/g, target: '$1'}\n```\n\n此设置项的默认值会过滤掉接口 URL 中类似 `xxxx/123456` 后面的数字。\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"726a4b4e8be70484065209c92c68fb7be1bd529b","_id":"alife-logger@1.2.9-alpha","_npmVersion":"6.0.0","_nodeVersion":"8.11.1","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-Mdv9h0fRYO78t79W7yjYIM7GSOvajNUt3xHhxqgAg3bnNWlIMXb+32Hv4N0sPi4aQ95n7APKAt76pJoBsvGqdg==","shasum":"947becd8b06fc21a1e276f70ce9438588fffd84b","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.9-alpha.tgz","fileCount":22,"unpackedSize":80533,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa+o7XCRA9TVsSAnZWagAAZ/cP/A/UHhlwO80jsMveoRWu\n1uCdMLVI6ICZcZDNm6T+XqaTNCQwnfk5KCGDIuadvx8nfRRT4OULpQBzFvwW\nRhAmoHPxsIQySCxoHI1JkKFnp4090/GT+AyuPETz680zj0MTgIa9DWSqA3f5\nw0tVlRzsHfULANWt+VujinqIRFKmHeqAiozhlUYgeZ8trE3TVrf9jIcKSSw7\ns0/z1KmS1x46ooAmxd7bYy5byymPX03gWuOZ/yEYuFcf0NcbzI08gtnZzSsQ\nDnwX4eWiG1boT3HNe6/+vFzYxIR8nxrTeYfg178KzD8b/rqBJh4M//Mje9sX\non+Vry1KCRR9l3/9srsHjVIEcyH7aOMDQzEtepkUvxtDUTWjC0175VrTsOVs\nZKbw6H0HdwmtufScmHK2qq84EUquZ43+IkvBETrdTZW4oj3kpqnJOeaZD7H4\nwjwxvDF+CWbX2TLx1rGkcFtYSzEQ59w3LsLpwk8tSkgQUcqgIV74nbyT6Gf6\naQmv6CTrj7/P/0x29NiMdWMC/6uR4uxFBL/ySx0q+Rj4E48OTtQLCINDEglL\n5nX7pBbUkZKSGfpeokO7B0AFPE18VymFH2GgHsAMdo1rZ/zZknhx9YoDtCbb\nGf8ylSYV8AIZLNxL4G8Wd2z5Q50C9oUeTG8R0WERugUH4lDsAUljhxS6lkda\nfqXh\r\n=lS3H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGaTTpXm7Bw5o9vdtzOVzKT7CnyRR83ClbGsb3TXCmfTAiEArJRBgAWvluDTckuQWnQozgRvcpRHFpeybbb+1qj/cMc="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.9-alpha_1526370006543_0.5952957693970122"},"_hasShrinkwrap":false},"1.2.9":{"name":"alife-logger","version":"1.2.9","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","f2etest":"npm run proxy2local && mocha --no-timeouts test/f2etest/** && npm run stop_proxy","stop_proxy":"f2etest-local stop"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"gitHead":"e07ed677ab11d44f6d6bee3838eb18ffd9eb0e4a","_id":"alife-logger@1.2.9","_npmVersion":"6.0.0","_nodeVersion":"8.11.1","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-0mXGWHzWsPWvZOpQ9pjbKoL79GhbMhrceCSMqYEOZVXf8HR68sB7wdJgs+UBGEwaeVstK3RqP7BJLvoqrTy3qg==","shasum":"e1c215a31536c81cc1610e0d5bf53c667fdd17ea","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.2.9.tgz","fileCount":22,"unpackedSize":80520,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa/OwhCRA9TVsSAnZWagAAsGUQAIYLHqh1s/E5XPCrJ0SL\naB4NwmoIJm5PfGPrKouR+06S4d+cXlRjapnjIy8N/7MscgoIb/Xucya6q5oT\n3Pz9m9e3reY6IjZ10xgbQqo+VdDhLsRoMNrcf/sWLXL2nMzrc03zrTf0RJo4\nBPrxLELdZwuiy2KFho83fdXFHt0KpjYJmA7l2adH7uQw8ntAecMXs8VyHaVb\nliahjwEta86+X6kA38q17n83qe4JhMKPihuZY58zfNKsZ7FWpiKs3mVyYgya\nC3PzgS6PZ56CNweBo46dk2Yt4uzp+jAgl5qLeAGbCUhdjTXdauRiyR/5CtVA\nfcHmcrt+Idai6/I8XLiARprB+k6nThe4jBSGQ7fBjozB4RKcsrV9Y/PzzcVc\novFu7uED6ueyN7baV5YrYLOhGVjaLoDOgSp7i26Z9jWOxyZsWckQMm9c7ZQM\n5W8LbFV2MgIby0c5ujAOiZVMdEuGADHYkxBaalqs0pT1NvelI6SsAxOOiTB+\ncGKOmTgSHB2KZLpbVVPJStIYcs/4mHvdJKIqvm26ZhrnnWwXQBsYhL2N+YYr\n2m6kf3YdBtTVyv0vrO7TssxCXFJWCE8y6lKgVHTvLv4DCXc7amCqaZXDWjZB\nZh8+18LO4RAliMXqw9Lr5zQtN+qFySx5gm6nmfgsLUdHZT0s3BNuCjV6T+Cd\nBoRk\r\n=dX7+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDUG5gST6MfRzXr6t6XJaRyLf8TdG7/NOQfO/oiGGENKAiA8QGClNjwsA52qPWKbkyyZMmYrWZBDSs8CY/uRrpte8w=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.2.9_1526524959950_0.30385865485599095"},"_hasShrinkwrap":false},"1.3.0":{"name":"alife-logger","version":"1.3.0","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","f2etest":"npm run proxy2local && mocha --no-timeouts test/f2etest/** && npm run stop_proxy","stop_proxy":"f2etest-local stop","dev_local":"DEV=1 LOCAL=1 node ./bin/pack"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"gitHead":"ea96775dd3737d2d47dfd9a27c51635a710607ae","_id":"alife-logger@1.3.0","_npmVersion":"6.0.0","_nodeVersion":"8.11.1","_npmUser":{"name":"josephku","email":"jawnkuin@gmail.com"},"dist":{"integrity":"sha512-Z8GP8ktJR40P9f5OMhO5YML4xwqTZcReiovWgI3I7O0S8xhRmrTKTXRNcyYByHc35Br5h6avAFRTJEfTECmSdw==","shasum":"a5db8631f63d6f82e8f1d70d4288ba9420970dc2","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.3.0.tgz","fileCount":23,"unpackedSize":85091,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbDVP0CRA9TVsSAnZWagAAbZoP+wY9+Sif9FbzLv7htH8d\nR1eNofGpixv2ALXRr/yaKebLXw9MFzC6UroiIkK15htbaNZ3nuZQP+05XuH+\nm+wu9J8KxRzdoojnP4j4J+WUxccsvervqZo2LLkoX09J6fUSSbpKNij7HLoc\nmtUoS6m7JupD4jMhICT4Nx7xv0fqyFeFiCm2lmX+tyhsJKV4yo9kzXRqcLkP\ngKqz9gXrg82ht2ThSTuzoEySKzfx0eR1QeC8Fbccv6b3KEmnHUXfnOm58KTG\nbgmvp784rVwQBAPmr/mnafTVvUEhd1YjkDQMObdjS/QRX7NuuzbEJ2A5APm9\nWOigIiC795tKHEBztu0VZHgVVoGK77gRXn1wLl8FvmPuzUdSOQ1uAoVqjcoq\nKdBRGwwLs+KTPfvjM2BsL8kcs0Az7hQjVh1v4XwyoSsQFEE01EQyx9E61IlD\n8TcHsThGejuDCvDunpJ3zFHyCSYiPj9sNpze3xkHBumiU4ZIK+c3C0//xoMJ\nH0rTTDPB8vpjFOwYGh5ZuH6siu6lK0U30Uc7Zxwi6iKT5k2X4kGJED7iF1zR\nzJ+ckLmRHcFl5dBgb3my4Hcy7ht2b67HJyqyTrGMmnuizBE1dz1+7MIac/IS\nPwOxLlELSH5PLJZTazEw/1hW2IlnOIqdFywjvMScArBi60b9GYDWtiz5eFyl\nS3Cw\r\n=NTBW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGDqlh2MTYWXUkcQZLjwqUrJ3mJwERaBDq6EugvAt4HAAiBY1AlA8pZvTJe1m7JcmKhU93RO9TUS6tqdcuCT9y6Y4g=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.3.0_1527600114911_0.9357483475278832"},"_hasShrinkwrap":false},"1.3.1":{"name":"alife-logger","version":"1.3.1","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"gitHead":"1a16c19c85e572f42a7034efc39d715b9d0144a9","_id":"alife-logger@1.3.1","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-rUuioxnBzHZNwYnWI2pm808W3c3dobnYHfySDGpE1UfqHJJOa5VKnLYjGhmIx0tCMCkZR6t4eO/Yk0e1egjukQ==","shasum":"2f16d0edead40871514c28cd01330c95c14bbf9a","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.3.1.tgz","fileCount":23,"unpackedSize":85080,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbDhyoCRA9TVsSAnZWagAA0bMP/387iY18BB3G3OgitASz\nr2b/B3mhmOCBu8PH/zRfjN7Jxt/4YFwKcMwuhaqQv3gfgZTFVQz7HFcKiqdc\nEgWivvBHSHi3gurX6HXPMEO+Qw6HZL3oRZXXHtztYEMwPq301fUYSEsGqreN\nJjFMjSQ1CX5IjSP4rsDtM32ErMx5klflTsFFyaOqfU8y5DIzWmmXwa067MfH\nxtNT72j5RRvuxTJpA2IdvURtzJkTuqPorMNL+uMCedAdIcpxgeR9Z8NQw2sF\nioPsNcBDe2Vey9I6fZNVAsFJoQ/tKlKrFODiOXDemurg8ukfsgFZowKCUhd1\ns3WMtDKM0wWyiT7WJeMasVzRcSJDpJIFH23qQSW5VLyShw5+RKOU7q49ectn\neaH6psKqvkR7tCAkulbGMm4rOxx1VLzELUzb9BBgeRmSo5bI2Gtvvgsc/gGB\nLYrB7T1ja1wVh6tM5DhdLO13u34YhTUakr0DMCqEcCdoehbslBMYrRmIhOwn\nr/LqgNw9S5kDwrjrg4t50B2d2GvKMyB1c1S+Vb/FHFkT1DhGQQd/UWyYqC8C\n/Sn6+RKOdaEQCCZ8y2I2WUallTRqeS2Lv35XlRHh42l0sZFoc2Y7ymsSKV8e\n4XRw+7O6oa8W5I4OpQdZEKcukTmgu7qGdBZiIg/wC7HallUXAQydaic5PesD\nJ3xm\r\n=Pz4X\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD72GRDlY/5Xt7yr9Xo3CuhdizwZHQaOUyF1cNvNVWGSAIhAO3g6GZQwobKjPwACbY5rHTH+gfcKLAfZMcrBzypYyRL"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.3.1_1527651495547_0.03780214388860559"},"_hasShrinkwrap":false},"1.3.2":{"name":"alife-logger","version":"1.3.2","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"gitHead":"c723be3516769b8d2650599d3b8b2ee2a0070a4f","_id":"alife-logger@1.3.2","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-t+3Qyn35FA39LOZlNAvGlgdkp9hHNWUcOJcj57cUp7eD06EwRRj5SgfE/kvN4yHjXXVyEKIJB8Pg0fclq8e/kg==","shasum":"7d5ae62adf4bf6c4995288558ad178c4f5568b7c","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.3.2.tgz","fileCount":26,"unpackedSize":88681,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbXs0hCRA9TVsSAnZWagAAVY4P/3IiJ+bCcgNpVZyHrDxh\nOsKxZE9waqqif1ErOvLSqesrx/r93BtaQD5Y8j2XxssvxO2X6tiaKN3TDD+Z\nIYqZ23NYs9KqKGqkszi/rdr/kBvLWe92ujrnVBaExkj9bPlc9ro/TLxZzdK1\nzA740ASCBNyA91aOp7fvcGa9QqSozSotXjVWxSlKcvWtMqjlPr5jacIF5NGe\n03+uAh9dXCu9vMPxpRtbuLPOAj0AbSwwUvzqkSH9aTD6z7U5g+sjxWfGsmA6\nkSggXjHlT+TLqUBcpTp7yTABj5+CEFtdH7A+S/bC7OofwD4Fqaip2ARyNNHN\n9tAWRFGjcXER+G9V4+IhnS5etPPG3ycXmqKAbZiD4uxjUMzD9QDN1FPmn9Yd\nITC4ttlH7U7qn9nhexK86E9IwYthNMwj5HFb2zMZfD9pkdscXP7RdSGk7HhG\ner0uqnFRpj9Z3aa8MP3nt2GLe/PD51nKQjlhGVp0MM5aoe32WUdlKmRLFWv3\nQwn0wZaHHPDB794WjEGRobutgr/g36vHwXLwp5IkiaWWye6UlEe+ao1qCZFH\ne3sEfY8xJLK8Z2kbm/6gV/RqSsYtMoUg2snxZmaVD2ACwjW6O7VBYA7Q7A+g\nEm+4g09vn5i7FwnzKEp8PZW3ctgn30RM0TuWVOK1hC1OftMCoeog5YiyHISj\nb+IE\r\n=+qUQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG+8uEM6CF2DwOsdXuoV+yRkwC3y7/9vV8W9UJC//kUqAiBzz4E+gf4rTX6EqgxEVc6NHAvKWfB+0dPR0dhLfNWSmw=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.3.2_1532939553099_0.332277409470739"},"_hasShrinkwrap":false},"1.3.4":{"name":"alife-logger","version":"1.3.4","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"gitHead":"b24827c56cc9a7e6037079141ba874653ea6f33d","_id":"alife-logger@1.3.4","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-4bRSGTBDx01TvUQvFqlOYSYUH8t0zC8CaYSFl8Ko0La4L72nx9F64SgX+hQSWDsSYr6vwTl7xwg+SSi85BTQtw==","shasum":"636ea6ff274b893a81c99a26f2c014778a477c9f","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.3.4.tgz","fileCount":26,"unpackedSize":89231,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbdl2YCRA9TVsSAnZWagAATaQP/2qfQaargo3vRZTHy90m\ntdjwE9xknJBxWdXiTl/zdyKFOpJit7dmEUoloUxWdu/FgQrcSl8zCCuyTsJW\n9x2FtXScwlfkWtMC6+5Oq1EUYwg5M2W6xeHrs/ZuyS0UUHxMP3LHqxRxV3ez\n3VSnL9aoAzM2ukPnSih4zI/SmpuiXYR5Qr6T+0t+OTLrdjjTGiWW+Vj2UnJh\nkOIQOoGhc4OINUN/nMm1IEG7ROfu048sH+tdW8dHJQYqRRlw3eDj4LinRasP\nmII5E+/5yrGcc9cLlN9i3ehztd8MGTNsdWUXXyOxL6W4a3cnBBVOUQuzZrea\n9VdkiYT3zhtRNqFKkRSu0UdQpWjV2v0NGfewTFBAPmfGnurWEksr1a4O+xBI\ngHmNackXUQLxeTdxSZ1ueRjoULOBLYu+ehNm0aBFgQYk5XNNvah8UYgosDgc\ne3nIGqJrKPdDke7Vrwtw07Jr6KMgFRdN4b0AKYxUF0/ybT8mj1+JTrvVWUU/\nPJVpjYjKH7jFJLXSyfIJjiwkIuq1wq6DNkf80Nj5uxHHTbGPuT+fO0Ok8ffP\nCDM6kFltOZgKk2b02z8aTsv5yKy0Fua/RbcZU6JBainArvYUPEmpKkebjfqt\n23j1YyWuQmM0R5GL1D7xJ7yEUwD5pkIHfrRe9JMFNPvEOsy0Fqy5VTxzDCDB\nezm3\r\n=UiJ/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID28CATlrA+RREK+D08FS7a+aSGBHFnz+p0JXs2tNHCnAiEAiPSNqQdaTKS4YHAlQu+TiXBrB6Mc1fhGokVlzR0boUs="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.3.4_1534483864080_0.88979350150811"},"_hasShrinkwrap":false},"1.3.5":{"name":"alife-logger","version":"1.3.5","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"gitHead":"ef3f7eddfc1cdf2ab040d379a352103e90948e84","_id":"alife-logger@1.3.5","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-ecRDhjc9B1kAaniANm0rWOG9enK5dvzLjbK/KiBGr+OIX3EFTVy2BfRGjlj3DgJf7b9+kfwQvmAdOtxu9p80RA==","shasum":"c53a0175b9389a97dd3ca11eb6e2cd6ce5f8e98a","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.3.5.tgz","fileCount":26,"unpackedSize":89313,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbeiY+CRA9TVsSAnZWagAAqLcP/R/OT6433R05LjzL5QWO\nwcI340a92+5EAFsuU1QUG8hXONZ7XLFkaiN34FfZmn8lp0raZ5guKsZ3uidx\nqbWEpNnSB7DwyWLK92A+N7mgjSfpWQ40hu40KZGnOmaWRvoStAdnxJDkE1oN\nbDWH4Uyl9JX5f+yM9TjTEqI6N5wE2wVwZhZZEMfnTxJByZ0/oEjXl+Awy/VU\nJI8z5+R7hTLDTFaQRRX/JWe/cqXb60isLcjML5xvDlJ9IwO7X/lSpOmjUzPm\nb/p15h8sEvlxczVK4TZU+Vnw9gkYcUZ8ykv4sUb+Nf3BzzBJkvZtB6xvyCMm\n1TIZjyPHmKPx7wlTowFhrxQSQI3PskSe+ry7QJvbD7cQUCvDBXHx18CSVdrP\nUQJ5nmivs6wWyYZkCx2KZR2zPwJ00pgKm9kq3JyoGPj/Rf4H0OsDT30HTHO5\nNoF5H2SLKu1/11PVZ7mj5QziXqbtfuHN/bw8zZ4lHp8KhAXw/y6wKCiUHaQ0\nyE9R0bnfgxST5ilj2q8TAFq941TgQMrYTYqVc7V6/zDOi3HBOoKtwuf/QzPz\n0RZNepUCWKGJsoCQsYKoECb7xw7IqaJgusIY7MjtWVvrybzdE4TBEOx6BEqT\nfItrtnnnTS/KrsAzNKCli5rjsb4SyvNIMr90DZ5I1lj6TQdkR50SIoUTNhuQ\nnWRp\r\n=Bhf9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDviqRzghohRBCGnTsIthkvPlXrKH77WmnQ5VAiMcqJ5gIhAOYg1zSgkCPtiGphur1LnxasIMU3dkHN8wNWeK869sDx"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.3.5_1534731837327_0.2948747355190735"},"_hasShrinkwrap":false},"1.3.6":{"name":"alife-logger","version":"1.3.6","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"gitHead":"fda71defd2f285c21734f22f495872644e4dc4ac","_id":"alife-logger@1.3.6","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-+YkyFadDvidV73tvZjS93g3+/HXFf9RddH0gr4aXcMP06DqNv6CATXDlBFuJ+BWuz+O/2rWvJKeTEFdvgeYESA==","shasum":"ae0f83cb0e8428a3e27cace83afc3428a3f5a956","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.3.6.tgz","fileCount":26,"unpackedSize":89511,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbjJ1gCRA9TVsSAnZWagAAnHcP/j2oajEJel1RNTb91s73\nndW9ozwSKOlPmpFqja2YzG9Mobgl/edh/WpGHYn5GqaCBbcIkZVOHUpw1riE\nPM3S6axC2Pq4PEmHwtvB/PNxjx8YnEg4UPVVdvS4WlymrB6hrk8M789AphH6\nkyIXlvlS+pQT/bTHFDiN6whiagDrNns361lgNaDdOL8Kzxb990uSqoHTlN/y\neorVKRa1eE6GsMOQU32uxY7A+NmXYeYmQzuayEppP8OLv+qr1cc3Tj5IAVJa\no5GcTL9hmmtm2OpAFUeIJdAm7gfO2fHu/sAQSlc6gN8Hiab0HqKRPv/gT2a0\nHfQztNT05kUO+tWMcdPvr9fDGnmIcmOdXf5mOGFyT+RCG9qOTFAEztzcnj9N\nhZO5h6Hbw4Tn7G942TUmS9kMdBl88dKzHz3nse0OMY7Ddtfwty1hF/aBM1Rw\nD/82xBtkPLnZbQvQUi50uYdnmtmRXQdM9P8PBkOvb6lxeVTY36CrzA3RbQO+\nH/GXKbLoSyuWPbO2RBw++X/jxdJ10KJK6IekPpTO+7xTqOEfZF0VQttOlFFr\nOEhrQUL5wBW76o3n4NCDB+mMrOqY+ELFRQnKP+iUYiorRedcuNqsSl+X0r+s\n6ge8ZdxykDU82Ivp3ufc1KxeSrEwnUmEAVCL+48gIL6PCOQj/P1Q9j4wFygU\nzjrL\r\n=7n9u\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHjZjAN85nxgE/4ZPbBFUcYaw2QZwm9JZXYDYqvmJR4YAiAUS+aZunSxmfQeH7jHj6fYD8olYKlrqfYZVGLIj3H/ag=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.3.6_1535941984087_0.46340377084311246"},"_hasShrinkwrap":false},"1.3.7":{"name":"alife-logger","version":"1.3.7","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","express":"~4.15.3","fs-extra":"~4.0.2","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","uglify-js":"~3.1.7","watchify":"~3.9.0","buffer":"4"},"keyword":["retcode","log"],"gitHead":"a3b43306a84411825926825599b353e7337d81ba","_id":"alife-logger@1.3.7","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-pVO7H1xPjC/k986gLV95MS2oKX77RCSwCOB/o3U+Dz1O5skH/RAShM45JByDaO+sBJpdULBfwqCo4M+nsuTA6g==","shasum":"5289cd12f87b850cab2eeeba7db05290eb47007d","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.3.7.tgz","fileCount":26,"unpackedSize":89511,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbjKSaCRA9TVsSAnZWagAARDkP/iGXet+stkkJ0pAtowlt\nhDDOWO0GJwTOf5VkoKqTlDolUmmukbbVwVf5vL/aU09GyFpTit/B9OgBtq9d\nDcIj166Hl2BjOY/wJYRCDHHFnY31JQmL48SmQo88JVL0Oym4yudwSuouHiM7\n7ct+f2Q7rNvAWpOFpBAR6QEYIZQvQC3tl5g+cg4OvNCtZepbm/SXEBMByq5w\nBXkIGCWqXFEhQIerjOC76GXONm+7DEElLUs1n8Rtx6v92jK4imb2uXiHIFiQ\nN/uw8aCTNehEMvspPGXF0bR6H+eyr0hBDmDUy4oK4SOn+jihLNGEvoMZj180\nlawjVT1nh1Y9lxHnTwQp8NaugKxJzSyyIwf6PMMhW7J8iPljL5nL1+Niia9O\n64s4VG6t8pVJ3PLW6qzdJM3PEO5MY7CwWPZJEzjY5Toe6I5HixlD7Fuajq33\nvlO2d+uVSmhriSJilyQkhSZsZMoiBm/332FCL3I3gEEsIClOnfsepySJM2KX\nOLSJJDNqkaBvVuh680BTxw7SYOTy3/sNsHyw61JXCnPRVP8N6c10g32FtDjo\nJaAARkhcflgRXQHhUAbYPM3asuoWJIX80AEFumXQsirnuHVawTyLD4G0+ooC\nGs4GDiJJS2DMuDY+I4P5kYzZK3OOl2ujJvsQoSj+DcphgISUgGpHwtpg2acC\npBRw\r\n=jTMD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDSz3nh/lZtkL8ov+G0GSDeh7LguFNhJrWnJXd15kSsnwIhAOLJxIAOS7mR5aNowU91sdw6eyUMOGlUh/xbS+cLQw66"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.3.7_1535943833579_0.7649474457450876"},"_hasShrinkwrap":false},"1.4.0":{"name":"alife-logger","version":"1.4.0","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","buffer":"4","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","strip-comments":"^1.0.2","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"0f7521b3772261d690b77cf108a87d168aa099ee","_id":"alife-logger@1.4.0","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-dd7WbXh28wM3aFfQ0CTu/opEskDuMaY3CvHct6mNjgrmhU0Yk9VqWBiUHGoZoo/M4gKqivwfAADeQ+9+ySr4ag==","shasum":"405ad11af3a3e98e23aafea164571e28970f6822","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.4.0.tgz","fileCount":28,"unpackedSize":90726,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJboGAQCRA9TVsSAnZWagAASPAQAJ8i7NMDPBmx3ELy5xuh\ng1VgrLI2cN84Lx36ikLkreZbHkDE9tX2zxq1K4za1teTBZJlUkmu+D3dsTG/\n+dlzQuFJS8fZKWiR7F0WNcB0bI1Kq4bukgBUGn2QztzxUJ+WUJtmTU5WCAeZ\nfCQYUi6FOSMYAtqVlrOW+6LYnXe+xE9UY3Iv4qYtT1mEcq8e7eZVrfRFR0kT\n0KISJH7kmYuq9Osaik1F00mCroKG9Z8AbBsguWKiBsLLkjr47J+3usHQkYGX\n1p3CYVPFw9y9Qhta12W8SYBw/ixb4QnnK7YKlrZLH6X6ldxI8ymj+IJ/a0Tl\nja8tn3YkJtB6Lc8igUtEL0UvpWExLsaFZ+2X6ZL0FU64mku50JeWsjGtM03Q\nO0pRdjaN8LfdlWbaFi9QIf/5i4N/Q27XRSN/MTQckUQeZPEIz/Xn32hrkgS8\nNePJytKpSnxV1DEvllxx5zGDHLiZgdATLauR/3pD4ksUTTlTs49svvPHi9QM\noa3TP+hDPKdw3LPrmM6CrRJOuRhaowbk7OfhHFJjXaBnVApMp9Hp46yCySXJ\nghirp3B282uz51siNA5UnqccINYplTOVU6dgKnXmuls/iIYhcOe9YhrCkV+V\nETCbRzGECxaCpTosNnPSLqmXaXVgGvg+qav+B5t75YavO+/jmlr8XcmjU2OP\nMCxo\r\n=rKo4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFCzkOIeZwQJYokQx2oQwfq7/JpAejBlDoqx+60Cva7QAiA/dxO4qva8zSSiToahhjtO3bRVDWebWlZEY49nd17cdQ=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.4.0_1537237007152_0.7480026332740974"},"_hasShrinkwrap":false},"1.4.1":{"name":"alife-logger","version":"1.4.1","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","buffer":"4","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","strip-comments":"^1.0.2","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"8a0e609c810d3769cfcafb69c758673f574a1fcc","_id":"alife-logger@1.4.1","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-2AQa99Yb9qFehE7rSk/8MdhCtddOd5u5OoggGuf0bUijmCuxqQytm3JkzeMfAVvSY3V4TdDV/z2lC9f5lZum7Q==","shasum":"5589486463338fe192a49f12a5659704c4ae04fe","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.4.1.tgz","fileCount":28,"unpackedSize":98410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJboHVKCRA9TVsSAnZWagAA984QAJTQC363qlXqWXXNUUhS\nAe8yaCzQGwgRp7Hlt+CUivhYAb0LwQJsGO0RY7PQxMxxVC3h2I5zZE1I8pZ0\ndKqySjC/So76xq7YU5CGydCBFaGZrtcq/UE0p44tDW9MPvVbWsID6aSlPX/+\nsygFU+Lf92vxgsaE6VKV/vSrsIcCSFu/8Y5US62p6ZG8r5Xx5pI924vROnPD\n8ZmGjjitED4vRo5coQQtqe7tTOHU1eTvpdQE+qgAA4lrpgh12hu0dHNzNrPf\n6QBlFWF1OdWRq1565yBRbIvKVRz/3tXWVrAPJO14fBtoMNeQLqhU0TroSO1m\nnWsFm+fGbfr6ghSoveZfCdXfru8bbUQ3gxG4zEJ4Qo7WIYUkmppWJBotb8fy\nD57yYjAmgtdSMqcFim12L9AJemIQCN5pbjh/Ub2hHwAogIFOkcNyMSVW4bS/\n1wJv2A31Bn5FLtLJqQI1Fjw7kr2i0rG8492ksoPnj0/GYMXM0RyT9PcN3tHs\n7BUkAT2Qn4iVgHmkEWUOgAjfRc2MIr/0MzjVZN4Pm8s8X5wzmGQKtOnFKOIE\nTq12A6kgACYoKqVo2iTYitAALtsKn+G4jxr5kX8XKJ/m5zelii2a7RUbGEu0\noQkqRnX/jzutnI/8J8Npfj4EgWmt1HoSU89X2pzEkcdqysM63w8FzutUv9Xa\n3leo\r\n=QjRP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBRPnvh9xvMw4/xJJ4AKb6Z1gqi/vFSDfMwvXVWumoE0AiEAvAEI+RZtungt0Y/o6gkXPDqkHRQbhFDrm3VLDxDCpi4="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.4.1_1537242441906_0.8027162359846722"},"_hasShrinkwrap":false},"1.4.2":{"name":"alife-logger","version":"1.4.2","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","buffer":"4","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","strip-comments":"^1.0.2","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"a4e7f433127cd6913b19f86c7c3b41e04999514e","_id":"alife-logger@1.4.2","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-um//aG3S7mcw/DeONavB3afN1O3eCrZ+2E3ufnqzazsBGwoiaqa1viNeJy67IjGpd0xOd3c2tpRzMpyZrYQfYg==","shasum":"de7f104331a48393255c3f5a8fc34f7332866170","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.4.2.tgz","fileCount":28,"unpackedSize":98546,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbpKSdCRA9TVsSAnZWagAAPcEP/Rqhh4NJ3ZASjHKRuxjE\np9DlqS1tIArWyDn4OVDWsBxwrz9Lj1Vxj4zVoQQfG9pZAbUDu8TqY1sF+FQb\nW8mScR5ZtrN5Jlj9BT7u+tzS1RkxFVg16Zh/w94Zd+KEyIP4vb9RtvG3cz+U\n6B5Jx2HEKxJ7v6zJX4LKpEgDSailj2Q2DgQ/D6rnpaWG9X/kBSuRDx5oq+Rt\nTBN/Ez0D5Tc2i5JiN5UrIr8vbleIRntbYvFxNSn+0k/YYUNOrjoS+j0q0iYH\nwXXfvi+X0iUivlNWBe2Wr0nRAH8fkvpXVRoD+3wikLS06sn+h+6GZmz/fEWN\n97/Rs0/kTiwbN+eNZ0vv7SuSSjk+FsF7jWjrQ8WC8IWhlhD+j2Tw8N/N2JcP\nCEPJSKYfg73Pb44pv9lkyaVO9w5paVkkJFVsjcKRNRQXEF9KcCxfHWPmQ8cq\neSOhvpRFqaC2bQNz4eFG6ZLHEe85uflXjKRw+9KwjspHbvpFbj/lR8W9Vu8s\nN3sfVSqW5jGRWjdYpieHFEFI2LrG+TCeBLx3Lc3YIH4YqVpc5PyGuk9c5LYt\n82tKK9I78+G5bDop6UgaZrnQt/lA4Hc2N0rdXbWNBJw3M+P5p1J56a/qJdtC\nfVd2LSUIbFTtkA69ZCQRFIJ8NyxM92glf2/xEpBXcK9wc3QkDSj0MdyPjYuq\nijVL\r\n=yMOp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDgj8wpgLehEs6iIhpI2rjCQVneFPZ/tQ1jDS0SvkI1jAiBnmNWF+ozGFedX60cfZfWyLGMlBS+G4AaDn66jBfAoWg=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.4.2_1537516700363_0.59506589314301"},"_hasShrinkwrap":false},"1.4.3":{"name":"alife-logger","version":"1.4.3","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","prebuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","buffer":"4","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","strip-comments":"^1.0.2","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"196b9a63b961118feb6c29b2a23a3199e97a060f","_id":"alife-logger@1.4.3","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-gu2U+EIS4m/fewPob/cy9UnQdSuTATjdvnPB9LsT+gDRtBgbdQ+xxFS6dvyg1QHig42K2a8U81qltDd+PIGfgg==","shasum":"22a61acae82d878845507a5ae33b4771a68729dd","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.4.3.tgz","fileCount":28,"unpackedSize":99094,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0FvJCRA9TVsSAnZWagAA+1MQAIhyPXD5OKctHHGn7FXc\nm21jULgn3pdcDkfJo8cVEoEykGL1Gb8u+ey89LxXt0hgVw9/65OFXujCYrBv\n5ROUGU/0xVmzTs4/FhJ6SU7qZzHVYr0ce+H9ydeym/cwAyLBoncEY7g/9C0+\n1dvbij0zYOZ21vOeKJMST7CEdiQS+SofPQtQwxC9OQ8R/stU4cy2wf0oCjQA\nBgFCobEvBxLh8DBH8Abwcdllw7P9JkQDOuPoClgHYdpea132cI8x4i8vXRUO\nAqYlgYoMbsw6orTQCRsdEkrAzv3vIv4VbRAAMswDpj0O7LfQKMj1qvKAoW/w\nmeaunOLy1a1zbF9WDYJ0IjEA/AvFwp1xH5U1aXyMzEqBcycfsWW3p8/baFZv\nb9dINqpbiU6sKizpZjkEufigl4aHfvbF28cmvZphyhEMNPOqsYyGi3uk//aP\nBfDy/RioMOWqBjQerHHmKJePBAwNvn3SKj9rQdva1Sn6RxXv6u2NJN6+uIbB\nrq5ipcByMOhhl9dmXk7/XpNWT7mN5Ovfypkk16G7rP/JhXlOTGDdDugzikDs\nFCPLgNWV5syDCvUIewPsTWCJEUFFcH3e2LO+Il5jCEwmPTFGBvixQ2is/9dL\nHFcD0Im/NulXa6MgIXG2mE55ZRaYXqggnxMK5/dXYazCzt23LO6ilWTaAkxP\neu+E\r\n=msI2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHraNtHsWI0+Pwsvs0KIYdB9DRF+Q/kgA2QF1lsq70aRAiEA4qwiqZVTVjQPB/zxioSdSOGtj2xZX+nxQRDq9v41rAc="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.4.3_1540381640470_0.1412763315457215"},"_hasShrinkwrap":false},"1.4.4":{"name":"alife-logger","version":"1.4.4","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","buffer":"4","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","strip-comments":"^1.0.2","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"47499624b883db9469da7a2fafe93be33e23a011","_id":"alife-logger@1.4.4","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-rZgV64OQviagmgdNQ74ETcJS4NjKqBcawUPgHFrpB74OWPjrseFUpxksxEmXHz3D+d9vMz2+MXLCD887AmAmFA==","shasum":"cfd308b6ead3ab460b38e899e97cae234d18bd10","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.4.4.tgz","fileCount":28,"unpackedSize":99362,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcBjQOCRA9TVsSAnZWagAAolcQAKTeQIYPthZ5qvjFrgHb\nMTeX04wn1ap4hd+wH8HoF1Hu2inM7bQ/sEYa97DiwEKs5oRVHx6PrreaUz2H\nQvvaCmLk1lMmt4VI0hE8teN4IkvPgkan2Rwc+NmnTdtNlxdx2rDIfEMXVD1L\n+bhSJMbGXJ8rr5bEz0WlLJA3Yzoe4jm7ldqoyX37gCsK04BKi5F6Hk5VuCv2\nSEjOAX7XO1wMTZZufBuTCe3dAC58diLJIhNQVPVe5tPjMe4BDjHTMS5p1X3X\n+sg0xLPTnV2Cc9OC7gMg9CTnwmYtOL75VQWPTz8tTUrHDjNhiDPeTHdPFVrg\n3+oPowKcLhGNoZzBehUt3mhZS8Djn48aewilzXMK6dAZHRFpG+2WAdmkaIYD\nF+JMU5TnUZIL8Nxa6mlEoUQIEhaKIaa7a40bV+OUu0bPtqkLOnGeKaj2+Ypx\nvKEzLPIqg7L4B/5cK3rCIY91qV+0HNpc/jt9SZXOw7tv7oMNjTINBnd8I2uy\nDvaqUahVpQ5QlcrfmayACmk2pNc4zEIFIbTAWvxmUYoFezlOVpk21Wf+G/Kd\nKVFTh5f0tN7xhICO6ZIHm29GZa67bInPH3tTbHTOzMHKhOjh6f5tNVZ17pRw\nRqUXGJJ3c15eQEHGB21N7fdFJgGCSh0MVS/iPXAx+xAnZWRLWgRooZQkcq4f\n4C9S\r\n=CM84\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD2ihgJlZsofyjgEmLmDkSYygnTBnfcNbgFVDdEA2YTAQIhANiopVZRF0/3opWQ32cikn3YGo9wLk6AYU35zOR4POIj"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.4.4_1543910413622_0.4453473713943923"},"_hasShrinkwrap":false},"1.4.5":{"name":"alife-logger","version":"1.4.5","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","buffer":"4","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","strip-comments":"^1.0.2","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"3480e5261fa7e77dbb003adc7a584c6081f49947","_id":"alife-logger@1.4.5","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-STz+sQLTAbiLc3U3+w8LJ7epiNtRWQKwtxrMQdX36Qx+TMBydvgiut3ZJMay4NTHE7feM8i7cjBOEPzl2RUYYg==","shasum":"f34b24f4301ea17c4d100084ab7a764f59bf4519","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.4.5.tgz","fileCount":28,"unpackedSize":99167,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcCLROCRA9TVsSAnZWagAAbmYP/10Kp3cQXsVtzkWCZFdW\noZD0lEGfKBNH4WZ6qgKqflTChJGgih44D2CDZJQQwRG76Cu8Isomvya3p9N+\n/BPOLoasK1CAhBPve3AXr40lh5ROHHI2PpWtCP/tbJmonCIqnCwKkgp8YTOa\nczsz0lDSPBLOiq1MUMRxl5rPSAGFn72Ulzw9FoikkJDurphPUu+P1fRT3VoQ\ncKWOOHMkqGHjLBC0YBeAmAx02InrC5mllbpclQIkH87pX9VuIECZG1NHQs6l\naBirxj/8uheqM8xk2luohjrTk5Sr4F/Qk4RV8sWP5ragGltnidKYfIMBb0q3\nV4x6Ixl37lr4GK3yxVhiMt2/wSD0KturnSdvcfdqQonACpDSnTPJVsXfrec+\nHaCFT1tW3SdATDjJh90zukU7Bf7tGpe0u3+jaXr+gCZ1RrG755Oh1ItoyDyK\n912gpIngH4KTthyOzIzcB9aUtFEZttTtNEWkai+6mWdPM5RPoMb9+BBtdacZ\nRUFtZhSbE5ulmdfpVDGxiStSQERfsnbUKqZx6ESSKtGjwfQhoWY2T2retiJz\nj8OOdwhy+hYCJ6GB2GHeg+naHHVTESXz211EoXnpSqd9maKnHkKqEXQszlCv\nb77GpMAOfS/LF8YMfyMRzql7VA6cwvkOhRmLsJ5dC07GK2YE6sG6/37uNfJ0\n0lxf\r\n=V1gN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC141D/cVmz3tQ5bcBc45WVw3blRElJckrGuSp5tJwP/wIgaDgAIUM+WpDPfa2tiKv+b/bHtXUlIrsVHGxY5q8rfAc="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.4.5_1544074317388_0.29747359917552885"},"_hasShrinkwrap":false},"1.4.6":{"name":"alife-logger","version":"1.4.6","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{"chai":"^4.1.2","jwebdriver":"^2.2.5"},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","buffer":"4","chalk":"~1.1.3","chokidar":"~1.7.0","dateformat":"~2.0.0","eslint":"~3.19.0","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","mocha":"~5.1.1","node-fetch":"^2.1.2","power-assert":"~1.4.4","strip-comments":"^1.0.2","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"b9acd0877eb9eaca28fa4965378f14c01c18e0c3","_id":"alife-logger@1.4.6","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-h5aR6eYwD8zoyhEbRbNzXAIQvLehld5dr7x77uc57WAbLQ2WHDA862gEWpRXGok+wunI2oMk0IIxQ1rFg3NsjA==","shasum":"fd5b9be8c370bf3f75bd4ed91f8625f7e032734c","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.4.6.tgz","fileCount":28,"unpackedSize":99671,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcFwhKCRA9TVsSAnZWagAA3VcP/3ps7Bpf20D8N0kS2Fbd\ndft3q1H+tzPb+pfq6flaK/gbucO2odXpBFlg6ff5SHzabCusvnqCFqgX2EJ8\n+5BlHkJnSG2UEijCgJBSS/B66rV3aF6fRrHjvWrLVMTuekYBl4WxElo6IGll\ncN28ho8zSfrk/ilWOgXkc2Ju/GwWK4sIRe76Oub0I3AsRKiVFc72KxCRzCS0\nZNf0hsNSdSBd7ddFpuAShxxQs29Ag69QW7WL8SZ4VSqp9IizKNw8rAKahccN\nV4EpVV4lFOfSTWYbMJUxxtkc1PcRLLsCsHazUYfa8j5WZCzV2HJ4oBfK3jSQ\njUie8zdnSj4eSaA03sfNxS4++csddnNs+Y9+DNAjwz6+nnobquRCl8mVe/YS\nNX9wAqvBWfevrBfWyXvhhgPRhbIPNohGaL7fYawNyfSpkSKy0aszh2sjF9a4\nEMe5bkwpuo08Cnh6v7leXVGlM6ppG3Pt61XoWkYWb6/AjSbKaXATdgpD4mMf\nOXgpBTQSlWmIRYhB8kgzYlh6ncNZnZvGGTjZ1pRkhTsQmHME3QVyIeGHo200\njyjb6s4lLqWT01GKNqtmbgxj2NXw/JVw6vWWI43e774wFZy1HQVTHt3iVZO2\nkzwwEk4gpsTTDKdsyav+Cn1Ny9wVEVBU1FKeNm/252moKqw2OK/ux2l30lH4\n2Ryf\r\n=/qhs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFgGspYBDYryCGdyWXvfte2uOGWSn9fGYTLmgb7og8n4AiAYivLwRUzHiq7fqFxDRL/UbTAnWELznEf5dVN+BstRBw=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.4.6_1545013321821_0.7250128738145558"},"_hasShrinkwrap":false},"1.4.7-alpha":{"name":"alife-logger","version":"1.4.7-alpha","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","buffer":"4","chai":"^4.1.2","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"},"keyword":["retcode","log"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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| ignoreUrlPath | *          | URL 过滤规则，详情见下文                                          | 否       | 见下文            |\n| ignoreApiPath | *          | 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. `ignoreUrlPath` URL 过滤规则\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`ignoreUrlPath` 的值可以是多种类型，用法分别为：\n\n- `String` 或 `RegExp`: 将匹配到的字符串去掉；\n- `Object<rule, target>`: 对象包含两个 key，分别是 rule 和 target，作为 JS 字符串的 `String::replace` 方法的入参；\n- `Function`: 将原字符串作为入参执行方法，将执行结果作为 page；\n- `Array`: 用于设置多条规则，每条子规则的都可以是上述类型之一。\n\n#### 3. `config.ignoreApiPath` API 过滤规则\n\n用于在自动上报 API 的时候过滤掉接口 URL 中的非关键字符，用法及含义同 `ignoreUrlPath`\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"f81cfa7127da90079d2d4f7b939564495ba3fc7a","_id":"alife-logger@1.4.7-alpha","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-8DHkDSsjhGum93QYtCqJQ1wVI2pnZuENm47GN4Ji3kkYSq5JLIBMV+eVxMXVkiwY64HbPg/WvgkKsHJRnBPQgw==","shasum":"26577a207b57da1ddb043917656e4665c8e61ff6","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.4.7-alpha.tgz","fileCount":37,"unpackedSize":246030,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcGiruCRA9TVsSAnZWagAASzoP/3dzzpzR3DebntowMG/k\ncR+5MPIX1II2/dmM6Z2ExjESv1apUo2XWPcMRt60K/sbbgRUUhTO/xFK+9hj\nLOFDc20CR0ztpXVLxpe+QKXfln97TMQQfJ6h+eJ7X+QSxdn/IEJU+aD+YTxd\n5DaXxU/z1zvOdFSlbiwllx/u6RlF5GtiZ1o+Dk8iQXA4YTxg1uMCmGbL35HA\n0UrUZxANnvbsv3MiplVNGamJbA0Qstbl9KjIRanC/L/nrH4vl0CjueUAkZ78\njBZdyBKgaJtPGICxeskIiimUBP5mKPyoPlIxqjVrt36zG1WT5//ivieLZR2u\nNqMmr60Rb8cp423yegOplwRaE+qloqqGjCbw53HJgRje1s3D5JMAQLcGeMRL\nJwyANF3k2oDy5U4OgVLCXNvlQDbL0B7zQbj6vJ93c54KI3zfckqXbK0DkdO/\n14O8JXbgQzU1H8M4XXt1+L1p+4elI2nK0bn7OsixFC6H8Da40w+mXhgyp0wb\nEUkh0JufJxJMBYsdE81pC4KTe0NsU9LdO67winH2bsUd6aAHClmr3b5HW50J\nQFKLMYH1vsWCOQjeADm8ncb2lMfKElNV92kWKzfA6JChIm+h7ARWeaHozDI1\nPULR5Vngz5AGiBEvxoetD3SFJ9UgdRmmrUK0VmNqqiwgbKU6KV2X9liY/qjX\nKm4x\r\n=BOMQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCdydgnhIfmKJNV7TykQW4iApfPNxlJqHZdxtop8vV3PwIgRukiRVbj2Z/EHTBjv9hrn7FfRK4YWDtLvoQrIMfzZPY="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.4.7-alpha_1545218798188_0.7269809845707598"},"_hasShrinkwrap":false},"1.4.7-alpha.1":{"name":"alife-logger","version":"1.4.7-alpha.1","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"},"keyword":["retcode","log"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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| ignoreUrlPath | *          | URL 过滤规则，详情见下文                                          | 否       | 见下文            |\n| ignoreApiPath | *          | 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. `ignoreUrlPath` URL 过滤规则\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`ignoreUrlPath` 的值可以是多种类型，用法分别为：\n\n- `String` 或 `RegExp`: 将匹配到的字符串去掉；\n- `Object<rule, target>`: 对象包含两个 key，分别是 rule 和 target，作为 JS 字符串的 `String::replace` 方法的入参；\n- `Function`: 将原字符串作为入参执行方法，将执行结果作为 page；\n- `Array`: 用于设置多条规则，每条子规则的都可以是上述类型之一。\n\n#### 3. `config.ignoreApiPath` API 过滤规则\n\n用于在自动上报 API 的时候过滤掉接口 URL 中的非关键字符，用法及含义同 `ignoreUrlPath`\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"f491de2b5414442e717a00d42370d1d19ed99101","_id":"alife-logger@1.4.7-alpha.1","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-XplNHQQ2GM2blUW2ymSTBL4uKt8rQOrJljgr4qjqdmtm58bH02/JGQZ5te7bL58K5wwl9+sQw5Zr2/7b+E4HOQ==","shasum":"6ebb9fee3fd7cae66837bce0bd86aafc996eb7fa","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.4.7-alpha.1.tgz","fileCount":40,"unpackedSize":268836,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcIIuBCRA9TVsSAnZWagAAm0gQAJU72lAklrHDxzcfsEtx\nxeegADyOz5WqHsF6BZftFnbUkqLGmRkTcwV6C9nJBv9PfFfRnvwhTx5CIIQ2\n85kxO4pe3wGHrojWldwyhGWfxXu30gw0T7La0GbXECwUqUttpsMUUu++SJKd\nSFVhwrwsV470YBMievydhr0qjZwk2eQWvtrR7sBFA9EBlzRETJfI5PUWkUu8\neJI1a7nwbqj2SMluxqZIB50pV6k9aEqdeizOq9tzqecQV98Wru2XhwRqAIg8\nJ5oDBjLKV8yG83H7lZkN4s3NqDGDfxD5yWrDZJSxf0q3CLGj+/dfUTAGc5T0\nbvo8m/RDLGpOa5JVal+q/yW2BsTxk+UwDLBK+MnPB0dWOHyo7mpCb/K00337\n+df4cMLhxkeQUKv2KEssK/iEcbAN10RCQoL94Xl61+StH2IFH5gZNw84ZC6A\nmENPZgA0AVAxBT2uq8aj45avXqEjXZ6MyJ8tpptofzRLw/lf0az5r+/coTFF\nqjtR2g5c9EuUna07daLnps38dmdTeZCpdGPqqjMRav+mG4DIcqjR4/PIa27w\ngoo9j4rJ4hrfK6adjLiPcyJ38VWoIUwcn6ENSuu4dtKVZVzeCcQ/sgWn5JiN\nDcFp7EMxmZHhatKHbWIhVW0m9EX9IzGdoCpaEnf5SwJ+GTNTwNEE99UCHy0v\n+fzK\r\n=MIlO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA1HDm1zW7es4AD47qPxgvzcVY3RHat4ZCxyKr7dUbicAiBfonei/O3bF/KrsUIeizgIymvblPi/PRMDXmhUrAKFpw=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.4.7-alpha.1_1545636736587_0.020200455940833306"},"_hasShrinkwrap":false},"1.4.7-alpha.2":{"name":"alife-logger","version":"1.4.7-alpha.2","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"},"keyword":["retcode","log"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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| ignoreUrlPath | *          | URL 过滤规则，详情见下文                                          | 否       | 见下文            |\n| ignoreApiPath | *          | 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. `ignoreUrlPath` URL 过滤规则\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`ignoreUrlPath` 的值可以是多种类型，用法分别为：\n\n- `String` 或 `RegExp`: 将匹配到的字符串去掉；\n- `Object<rule, target>`: 对象包含两个 key，分别是 rule 和 target，作为 JS 字符串的 `String::replace` 方法的入参；\n- `Function`: 将原字符串作为入参执行方法，将执行结果作为 page；\n- `Array`: 用于设置多条规则，每条子规则的都可以是上述类型之一。\n\n#### 3. `config.ignoreApiPath` API 过滤规则\n\n用于在自动上报 API 的时候过滤掉接口 URL 中的非关键字符，用法及含义同 `ignoreUrlPath`\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"90f313b09d4c6edc051015f85a36463247e7226f","_id":"alife-logger@1.4.7-alpha.2","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-FIq5M49Ig5WnoFEZibvDNqhHaNt2tInDt0hKxDrMBusPftuOO0fovm53cp2sV280GzVB3NumHk92F+U6Rh6uuQ==","shasum":"def53568c5a38c07ab565d464ead1b56fba98531","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.4.7-alpha.2.tgz","fileCount":41,"unpackedSize":142109,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcMvZ9CRA9TVsSAnZWagAA5jAP/1JxySZt9Aw1WmBk1kXU\nGZbVES93eb4hwZnqkInTc67+oZWFzIApgdyY9Einnlm8NA919MnwiN45gvrb\nkSwoOO/TL2qe4vkvAaWgrSCeLgAALCkw7wwhGE5XGE5NwkqlLXWOJEHUZt87\ntBMl692R/ZfeaQMGQqHqXwIYvwEhz/qNJ8OOhCfc8cyzQoCM+7LUF2sA0tdl\n1uWxcjHUYc8QpqgbCkOYiVzWfZNKuWw1iTPoSdPbtT+8uka4xM4WhE9G8BHC\nhe54bZ/bFCA5M91UBk8oC4YcI+1HVqbIKDpA+jCjp161JPSByPddmIF/0RYz\n+iKAeU+TjLf54IynqiWDn+TQq/xVeZiUT8xfX68NqEUEJ37L8wGV41kjTdAI\nVY7e6q8gjsc2/Oqx8cow4PJ556Gqcsq5GlLGBpZHRGaUUpW7k9VIPPm+0FGp\nZ6sq9LRad5eyI10ODtShl/R+IFdz9UQUHDMACrmNkz5uQ9Vdfjjg6kRISmgd\njV8MCcfIN4+1Man0c7Phcphk+9LUFdx452usaIgDCEkki0MTyAylODYPttGB\nNHUwKsolVLn4AiR7x60tR7Nzb/8OEBzFknK6oZf9/Y8/65TJCQu1sXPnrd57\nZtzo2vpwKJ4we1yHcN4ethbv/aXYc5gRcgS807CHIBeKi4gnQIxAimpl2wX2\ntinx\r\n=PAq8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAhhHnqOfJNj1RkIUmXr//yjN7hnc/+j1q3CHCdVpMzBAiEAwaE9VBbFO4zj1Yq3E/BASSpuLEMxqiAW/1jljA37QEw="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.4.7-alpha.2_1546843772891_0.6479784087601423"},"_hasShrinkwrap":false},"1.5.0":{"name":"alife-logger","version":"1.5.0","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"3961864a391ff8060563e7a2760c4c2eea1d2c46","_id":"alife-logger@1.5.0","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-2GJldyp7aqGd5vKqq+IfjDfWLH4zsUkcicKYpAw23i4PGU0b3Y3qXgce9hl6RSlpDAJr4Q1XlcFx55N5naqsRQ==","shasum":"9a6871026b4ca70adb4f734cbf8eb47a5ef736b8","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.5.0.tgz","fileCount":44,"unpackedSize":364924,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcSY/LCRA9TVsSAnZWagAACBMP/1OlxtlfTP/o0G8w5y15\n2x01T2baFdBo8oRwdbUkIAip3quax7cwK2MJDjrc4M6j8C368LFW+Wg9VD5f\nYvvgRnt2cAlx2ldxURR6ouCuGg31T+B10DZhlcL63lYxlSxb4ZinRJ4Xv5du\nihxBAFu0KIw3MfiFKw06qLGZqOLhec7o5Jhf71TClt77Wvw3Z0vvNdA4HYzP\nt7WwyMo+NpX1xeLhQZp7YY1tnEdxoWkiEIoI7XfZXseORDSQ6t5gqoh39WCT\n3aJPqUIo4oUO0VGKxAJ99pMc/Q7/ozcvvs4E6nCm5qXVZfL43CMGnadd5VnP\n92V2KZRZF6InZQUOrjSFCessiI28VOCD/TONmeXyY6XapXHrYES3/ncEP/C3\nQt65xvQS9XwrbSTHi/GbSVos26QZsGaMs40QoTEqm8CVCACZF7APtPPQzj6R\nvQhyXXNo7KGsWfymgA0lHs/Yss0aqNB/agvsHWhyxMipfyjJx6/OlU8v75iw\nW/b6UwMQKshmzWcDF978T4oHV4cvi2B7U2EZOWj+/zneHX19p8DAv10arwE2\nqrcs2vqNZBKnAMMVcRuARa84aDy/zaYnXjph1lncKKyF9S1zrsrIwqNneXfw\nV46YYJs0iCg75yhQ2D30ddv9W4N1rR295x15eZveOmqtC7ie6iR3DA9NvxqH\nnPeR\r\n=Q5Za\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD8NtCbDJY07KojX47/p32PbHwY/X24+2EwfxHJg3g4lQIgIJ2IaW+iSuVIZNa7ecKxoeeQMIJn2w1TYU7qo3tMlK4="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.5.0_1548324810834_0.4828175269964907"},"_hasShrinkwrap":false},"1.5.1":{"name":"alife-logger","version":"1.5.1","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"977b6509e96e83e153469356358d579bf1a49269","_id":"alife-logger@1.5.1","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-cwv7gYJwddVpTkx7qNPdkMhEvxPbxwd4eVUMZ6FAWm3AvBmce8lpMlHkPkR6jHbJyEBpruqvlJ21XN8jlOAY6w==","shasum":"f40b783f6057471015c21040768299c150a39d33","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.5.1.tgz","fileCount":44,"unpackedSize":364927,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcdnbKCRA9TVsSAnZWagAAB9EP/3hrMj4OMNSJPNkVLXtr\nP/3dWk4eg4LOtORcYNcfhf2t8YxCEj82eTuXKM9O5q/OfagfKKe0TrCtYk/4\nwu3rquMCGJrNYVW1EOERqJt/v1VaGrr/PEr7ZxCfOCYbBhaQJytvdFXRzMjb\n2iXC1Isn+HQAgmOo0KqChKB17qP5XnaulKfOI33h0O4aUZ1dCIWWJVxzxH7R\nD27I1nRTqYZgBMZhEBprZM/Ljdff2Yg2miHi1MDw1vFcCUiJFE73ozNPt4z6\n5TvlPGyeLO50aqEz8Ha+pu9kGp+EjodVAh+cblmERX3SgHVwMX2QCqrMF+FT\nb5Q4MzpXkUv0hF5y9w9qb7+KD2bQ7en9iQOIVNTCaeh5EsVRKe8uMAJ78Mtx\nSEE5BRIqrpHLoE78OxphfljNJIm3J2DNz0mCyj9o5EQCvvyd1M+kg9Mhgn1X\nAxyKhELXtzRuzFd2hfRE/PRyrCwUGT2yLKOJ7MFn/AnjNmoUsstF+QZTkJp6\nwR31zSugevPjXMM6q0/1LaN8Igyz+qGLpILtP+BtAPOsC+LD9w2MRBhTSv7E\nyd+MEBHqzKB9KW+GFG1UlJMpzvYzeAIxEwbiyqoKvtVezRBjmjKl7VHxIyfD\nMcWaNc4KRGR0q4zAh1cFvaKKAKTQV0GLZQKCPW+R/kd+NZNZvQoZAo7br25L\naT+N\r\n=ufGq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCMHqP2nIEaCTkrlJnDFS5OUQfP3eEl1blHZko8fIt99gIhAO9Ijz17d2chZl/5NVK8Kg+jsbgVjKHZsauURxEh8O+U"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.5.1_1551267529416_0.04287006717832109"},"_hasShrinkwrap":false},"1.5.4":{"name":"alife-logger","version":"1.5.4","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"c1dcbbe3b442dcace810643abbf513fc7de750d3","_id":"alife-logger@1.5.4","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-BGw1Lolj30yACWZqnNZSM6wUL2VqY9X3N4komOIkEYb+QML+69pQXCwRY+lc/iOG1yWBU6rplanxvAlNhVD3Cw==","shasum":"d632647cd50e784c060eb6d6e35e96dbe8ef17a8","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.5.4.tgz","fileCount":44,"unpackedSize":416045,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcztlrCRA9TVsSAnZWagAACJkP/3u6ov7vCWXTpfaRqvIr\nHZr3/RSt45HRXceR/8955HBOxm/ekmNmcpuSnwgDcSTRSlc0hMEZmYFEa9u6\n60W0XinVTu8ViJdKb0bmgxFm0Ha6mGbs59raI08QFJp+n6Jo3xua9BqJW7Fp\nEBcfJ+0tmDV/ISJfXkV/ex9FpBM/kdLxuwAVmxD0slwx/7zpBxceKdmoVAvv\n/qyiIK7rugK3ckk/DZb8FCap2pOrTXyFEGZ3dt5TJ68y9e4gjnSBYHMmDPN8\n8sNZrdjFzbXjwe7XCSWVVuDIxPr42fWVlwZL2SdydH6HF4zeScxGrSHBeN8U\ni0R4V/OOLuR9Nl/IMuXuKo/BSCjrxgphlMmunQc685OH0TQP3E21nAAtyjvY\n0LOjIFLKNZAANayCQ5ol5pTJja3LnKQ40l6GuxZ7Tw1pb3sjTy0HqH8YSqI1\nX/PKnj8TejVs3wVFgRfVBAV+0znBNIEJNqyeaSSdBEwygcZtLDXXT3w6v+jQ\ngIFxW2kO61+Zvly2LmWy8/IoKjJeUhDtKTAOoGDupGwfUwRPzBpHoYChI/is\nbmaPv3R8bMQimpTDEu6Ydilj/4KgJOc6wtQFCfJvA+8N99hlzf/4dKnr1sik\n4422ywhPSPML/Hi/P8/d/55ulAD+BVraJykGzMIyAmVBC3qI2pk8qmIlkCWD\nBF3d\r\n=6B6h\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBj0MveOFnpNrI/tMQxegWymWZqOyo7G7ZsFyrlej/pZAiB+wOL/yrpe5QgiBMc02oGEdbCAtJ9I4TlJgLEVOZlKkg=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.5.4_1557059946611_0.995324654580688"},"_hasShrinkwrap":false},"1.5.5":{"name":"alife-logger","version":"1.5.5","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"c05622f0fd96652daaf3d3716c18def979bf34b4","_id":"alife-logger@1.5.5","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-cpfl1nuYVg+CF+iojVEPII2Wbx8XsKRC4OOaVHsckUMo6Brr7BUqKVxBkMI5xI59YSkLjo4yzZzDitDqs4pUAA==","shasum":"1ebfc53bb3f82db5130709cdae12182e4c45d823","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.5.5.tgz","fileCount":44,"unpackedSize":416406,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc6lWxCRA9TVsSAnZWagAACLkP/il5adUrDuq2cZs/DuXM\niCnA8bZaGAjYfcp2C4/Z6xWOxNG80ALkfatDdXRvOgOgF3b59Pjj8P9DY/u6\nt8tRBoQB9A3zDuIjlg1g0QCw+kuhawsCF7wmVd9jYM7tV1HroToTfMgpi0of\ncTXKih+0JL+lDsRL7p+dw2ySO2OehasX06r2daVt0bDK0xM3vx2gOo6BMVRq\n+5pQe7TFnL0V77Hd/GW+Y45DXtqEEfPAGVguwMZ64CoPC8KB9x85LbyCjKRL\n8nNQF3oSLjqRjk8daRj1VoInkeScIyjIW9DibFHMy6hzA4cI76h9QlGpmhpe\nNNWGk3jzG52/gAn9MCw5UALJSaWCMk7W/TmC47kzEey+7D5JxXhb8huYDorf\nRz+mmlvHzbyemkcu0CLIFkyon8x9cDzHWZE9/azlnRN/3K1XNO0p0tyU6qNI\nm1CgFtyeo9sv+wydf+kz0I+GQGgiN/KGMIvxNssMOkn3RQwsj8smAVvyf2J+\nfi4mTO14gHSgjPmWjDOgFAmuGq2Spy4C8Eh2jT9zgSblqIWf41WjaaLhWhf/\n6Vn8o2A8FOcS/WyfnF8Las8yHeyHwdXcxvvRQLyU3meVzfqYSfBp7nRzgh24\n0QBbBESUcmGNQZjZkF3aWSROzwOoYk2zWxwF3Omx/VVvjMxaAg5sWUexBmna\nXYns\r\n=CsoG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG40md+EBWWKEhF8XneShHpH9PX8pEz+2QTsIgeOVkkhAiAA3McEqr0XxsTcyOomsK62sm29WLL+PUFRlC5zV575Ng=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.5.5_1558861232427_0.3149183259449977"},"_hasShrinkwrap":false},"1.5.7":{"name":"alife-logger","version":"1.5.7","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"70cb0e69dadc9cbac2e42eb36118cd6604685330","_id":"alife-logger@1.5.7","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-CCiReZga6oiHYhS/AEpbPf+CeoxLmbyS43z+4QaVeO1Yjz3wqph/ghMYwWSwFTFuWVUGuTqfyRQDqblmV8DAqA==","shasum":"ee476e773bed5c212e7dccd398208eec12fd6e3f","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.5.7.tgz","fileCount":44,"unpackedSize":424726,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdDIvwCRA9TVsSAnZWagAA/EQP/0s0kKutTrH37wm3G3a4\neV2BuXIo++Zq90rxShvaMgJ0gH/krsCAUa3my4BJqzAhc6iiaJC5LrKec8vB\n081ks5L+qGvFcfphyeO3XnWcb5Yv1jbDcoyDWxkPljcv+Bx6724ML/rNxAFr\n/DVnKwRiC+ldFDEU52blSrBxa8jFivI589Ah73qzLbzq5/jfA9fyHibVripF\nVB5D/E3NSjBcvaf0mE/D3R+lx3qY7ERsVYRqyZDWw5jA+ZjydQYheCqUW+E2\nhiVlwayRaz0JrgE1UwMOejotcgStUYsPDefllEdPSW4BpLHwWN5FvPFhvm7c\nF9dRSP3VWAD8lXlrTBM8YaS1lDykc9K3vX+Pc8nYZY1qwJvM2a8dCEpzAp2p\n7s+B8G7P59sYgIylm609JPe8J4LH+Wsm9ydW7jwQEOaK6lb/y24acUNsHGls\nuQDjbTDSEcPzdJmM3cPFOFPZbimtjIQeTllwg7x9Qj9OtV1gHNwraxe8IAWz\nyr1WcFz1dF+pnSxPf7W2gprlRncP9WuhKoMmI27DvZqCfq0HllKAADxRDKUY\nWTzJDLlrjygsA6TGRllztu9fVbJV/Ws0WixiSbpREl8JyevCFPzXFC9wHTf4\nprph0Y5mThcvEs8vX0JR04WukNJ9q8KwYTn+W5ayfy0odeBBpHAyHj76nHII\n7iFb\r\n=ikeA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEtE+QIdR840OdJa6D4rxzXSlHiNqCjMDOZG5q8UQJuNAiEA0fRn3oqVXw8PdzUpRsB1hbDC5yfS/mrv9lVMaEBm4x0="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.5.7_1561103343716_0.017862799317907907"},"_hasShrinkwrap":false},"1.5.9":{"name":"alife-logger","version":"1.5.9","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"83d77c4322634bd83a44df5d5ecb499ec5de469b","_id":"alife-logger@1.5.9","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-c/XmoS6QQvunTX3YQo5vcS5dhobZZtwcbrlUAmWjIW+K6sVfSWp1ypXpK6OClyJh0/0Y3VX5FSbU2zCZTRd7Cw==","shasum":"f41276326feeb3b91f026602c0889412dca65926","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.5.9.tgz","fileCount":45,"unpackedSize":446904,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdG0YuCRA9TVsSAnZWagAAgpwP/3CUrEkZh9ExaTq3Zvcy\nGaUeuZlOKmMcrL6SLu7lQwm14rglwCK1Zuuc/79Nvoza4PVGFVBqpyLurIIG\nH/NHAGQMI0BMsCq+U54EVAsPUwl5Lrwue++LZhkrsISVMxVXpOMGsMm6C9gs\nR1gBx0Ap+zDZRaaAfvDMioq4+zfxLUrAKiql0esFOOtwzqBev8grJsnHZygU\nSXgykqoBSzLkdj+jCsCoOx0MydvO4g8EonU9gV9HqMSIL3YrZAkCOOHls1Mc\n/bDCooLIyc4zamH93Lm2mmXu6kbVfi7y1lxOu4j6D4ZQDZ4ZhDHOwlt/V6tW\nMZMKtO+qhH5QdKdia+wor31yGt8RMSMAjr5Hj2VqOQ6+JPCRRZ+cwf4v6+SB\n1mYB2oI4CZ5YYv6ngkw/QLN0QfkCQgfJFnjnrUOhEX7ZAZJpz0QVJyZYCv1D\n7OsgPnOeRyWOziYkxrKArIc+W6KNpuPSTfVtFUmBIi9Gzk8df74kWPd2s72A\nzVUPWNk0Vv7+t9EWw/hSe1+t4o6bKPEWkg2YaAiL25eH1xCvHxKLOCwqV3Uv\nMy/d5D23ewcVU+SVDEIE6wQoJMYSv/d9VdT/NSrSf9FLMjT5X0P2sbW0aP4o\nLuVEK7lW54wJSZ6AA+oRj9SMDI1rNvP1VTK2RrNOHmsIStK6RdHF9wjMnKbR\norYz\r\n=XYVW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDRht4wKsaA19Ep5Q7HsOAoEJA6nJyetkJVFzGVvWLp4AiEA1rqE3Cp1QwdMjophxAJDUBFs5aArhIbeHRSYV4mspYU="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.5.9_1562068525849_0.6709292192574405"},"_hasShrinkwrap":false},"1.5.10-alpha":{"name":"alife-logger","version":"1.5.10-alpha","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"3d65a1bf31513c61099c4e361af5ed7b572cebee","_id":"alife-logger@1.5.10-alpha","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-bHQ+UVvhbSOi8KgyrkjrBANMcmRUA0UiVUlw2MZtowIB4OqpCM0TaaMQ+ywRpr+3y6vjmHZKWvvtQU6/5i9RoA==","shasum":"a56b915af0b4d615b89541461ed477cfd9151921","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.5.10-alpha.tgz","fileCount":45,"unpackedSize":456336,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdHvBrCRA9TVsSAnZWagAAbokP/3XDHuRAr2Zu49jlB3rn\nzRYeC5RnfL/NHhxzl34bjwaDMVjxfYgxsrNlW+4op1X9Lo1clhv5chi16pF0\nvTnucqYs8xr5FRzPtsQDchDXY1m6Jl2Y1ZfbEkumOudtL/5lXWwnJ+kYN1Jg\nGkLU/SegnAM4uFgLTHx+JZPUx8vxlSPSy1iCqWfp338Z6hAt7rGNlxi/Ff2f\nSlTw745l4E0nr7w9KWQPtyZ6ZJLckT6ms+pZhx8UJycjcbv5Wev/BDJn8eIB\nydelBhwRPn21hVKy+HbJ4HVPDWfBk5Ls+rHxQme/HcHdIn7XXnBLjjYt5K7g\nHkhzwgMtoPVnvOSMPKdj8puJlDHYoorepm2oVQXiDRgrcSlpS94QtMmt8fJR\n2q6haEBmCoCIfhfLMOH8O1ZiICsbTjQacRyht6Zuhv1GHm/31Q16zyQBSONN\na1j7GcHw0scZVyvH87rfOCLdsn+8GaV3pjYo572QO6ItSUXpBPXTRBGGqGCU\nO6GYPkP8CZGbj3pYqeJRu7LXg1jSopXKy7cnB8q00z6rmMU76UnYFvbvMwlG\nQ9g6VJ/UTYY+PZsu5Mof3OBKy+IZJ+6FusZpzDtUHxUC39gKuXWq51ZWlAnt\nZsUz8u9tLooSyPiMqC7K9s15h9chpATkBoPX493QB9/onKn9/eRQ9LSgQVvl\njfnc\r\n=lnmT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGWCubI+nELM+j9xFimCC0esbktk4eOqu1i8bYZObQj+AiEA1CXmIyUh3yK/YaRMTLLMrVWEDUY0Y7RbOq3WkzrGxtc="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.5.10-alpha_1562308714448_0.7358308014087145"},"_hasShrinkwrap":false},"1.5.10":{"name":"alife-logger","version":"1.5.10","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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 yufeng.wjj --apikey 1e61b90a0b3c4450a689b267ff30f012","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"f77a729e76f45db66fcfc81ef921ae388706facb","_id":"alife-logger@1.5.10","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-OIi2YEGDC9v0iENqmJh2yrolHoBwEyyRai7k8F+I6fnx3HO0Hi010qCcnICQNw3wRZlw1UCtO7XSiFvEqtklKw==","shasum":"a2621059c99c55f9e3d810ae5b0ddb8cb7213d9a","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.5.10.tgz","fileCount":46,"unpackedSize":549723,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdHyLOCRA9TVsSAnZWagAArZEP/169PvgeOQOYCr4jkBK+\naHrrIgXwEFQdX0k1eAuQgP2Oqu1Uq2l9tiJJ4u6G11sxV2l1oOLK4/3iLySV\ne/2Ja26yltcLLfwMRDKLtcJLrAEp/P8zU2oR5WMzWzdNP7X38IK0M866j1Fn\nbveYBzOE0vjMWo+7A9XOvWOKSCZHXNnejXiQhmrdbSZ7A4kGkZlhSH1leKwt\noHtV1SNwP+7vC+nx2oyp/gSoljthiTlxDqD4ncDQJzuaGRdAVJbXMv4Kyn1m\niIkgO06g+p8q5daODASq8z4CT4z12gTeWM7ZU7Jc4xYXpab2gzvaxaVKJzXa\nqA2NLv+d2huALtGnNTAPFu1SkOGra4Z83XsGyvSWVFR3zlV+EnQxshSqLAnP\nnNiS9EhY+kgG/Ket4lY9lRt2eqxCJgAioOjvAyS6x09M3VVgIxTPCIUxobhD\nq4GcSWz2LtPdXOjOkjSgAul2blkPeTPFAA+MwObpAnu+9LFgXPbXJN2xu3Ao\nrlQ0c6tzi8Kmlxv+qicM0PEuvC9zWgZt+1LC9w1JGISugNSA5cDW8JAJAaUC\nF2JnfGkwmxKWx7GIEh16UhEEuI7mu9R8+kEbFNa7zWioFRdUlaVz4cP0cBXb\nqh9lONuSqdlNC2K7KwVD4dvx3yWggRkYMU8/Q0VvWM8amaPR0I14BS+GecEb\n8KW2\r\n=Dwbb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNxMWi7+DyiaqbB3NN5Lb3Zoxsh64WLqI5oHSQj5b/dwIhAI2CUWmmLZB9fQZGXcgHHYwIJi/lXhpTgEtcBriMiuuN"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.5.10_1562321611876_0.5863101240607258"},"_hasShrinkwrap":false},"1.5.11":{"name":"alife-logger","version":"1.5.11","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"8269287cd7199e910886c44309a1d7472f7359de","_id":"alife-logger@1.5.11","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-mvKERnrsLWAEsV1PKuLMRvPo26+V1yxNzqu3r/zP3+8CQhpYGWrHfRbPEHc9f36uW9f7rwypcBmMBcVeZ36lSQ==","shasum":"cf1c199ec0aa6cd6502d374813a01d74f471d8ae","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.5.11.tgz","fileCount":47,"unpackedSize":567180,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdHymkCRA9TVsSAnZWagAAmHsP/R6mYYrFxCazTQMOS9ta\naS8Aqpf9jkzF6vO/zK3bIEVP+lwh0OwddmG/l44p+nXyku6GrlWk2IFoNmEW\n4Dc6iSVarvdWtQHngzx7tff1sJHQqpUHFYSALRbVr5er0wpabL/czTzLmM/q\nu8e8WkprYxCUykvu0wTbXzN5pQvAX213wpIzYu8d1TMpqLjMuoYccqzQ2Bgs\nOpV+OPenO4MJTnEvso0VcAaBXXtSrPH97gl0Di8ns/DQF+tl3RYJ+iageJ+U\nfYSm2vX5CZsUx8TvntpnkU1nP7BuTae+jNQ3cJsGwTHyvWDgP+sgXqlRZOCW\naBmuXxNfqOTYgTklw7qOiziU0xVp018QLqZcNG0DARo8fYbnN3/aXdNVifUb\nFPoUfpvKTWSy29LYbwqA8LgMLdor3rdz0d9Ce37GchH7W+fIwPzPEOK1YIpm\njCRs5JhsiVUR8bKEDBO5fa7XS0p+9K0oLYboUPW9b8oe6TuAJUmedVm3D9Lr\nt1uFpgr63Gam2EPHcHKayeo0d2A/TWW9aJSVKL+5QOmIWeSW13KA+za+nQ45\nLd5WtQ61+YtJg1ygbnooZ24UXvN4S43/ts1cAbU+LAVrXwMYSoytf4OaIE+Z\nib9sZrL8vzzJqbsglQsl9g8T/T8MY79AGQAL2bTY+N04zlX6AXaLMZMXl9Kk\nN67H\r\n=EjdQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDVaMHl/wqIIn0azqN4H5pc7iFTvldeuAf9UhAF4M8BBQIgMoKTlTifYaItMuPCaIsWRC5iKTjGgCAsD/xRZNTX6ao="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.5.11_1562323363132_0.34002801649184056"},"_hasShrinkwrap":false},"1.6.0":{"name":"alife-logger","version":"1.6.0","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"0183c1c2f10968639b5b35d0957f9a8752dc9f26","_id":"alife-logger@1.6.0","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-QunNE7Hqbjfsl07ddzIGPCocU7hXwv5SokfziNQZdl1mve/49QfR++T94O1ISW+DN4ZDXmcJGKbhrzCyRdBjIQ==","shasum":"93f7baff569e2d9f50cecc30887fe03629dab988","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.6.0.tgz","fileCount":47,"unpackedSize":569364,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdH0hUCRA9TVsSAnZWagAACGQP/0cwmeFtHujLFvVLuQcC\nbZ7gBKtYPoTjtFwcaGtKxMrgcvrLEjlDGyFH7q2U6bWkcO7ESFnYKdGWu1Ir\n4qs3MTYGzPkicQd4Y/Wkx1KZ5KKlreRE2UggkkNJdfPojAoHyKIeQJZkVqRD\nZyqIwigK96j8YPaU9d+FjuFwbHBxv2gqbuZDPqqozW1n0+ugTOs3dvEfbUu+\nbbur+b+Auauf1Fo/kz+k6vOpNP++t/RvERY1vHNxwqmkDG6HyjiW4uxtBITT\nds5QLwrkvUPYqfILWZdnlVf2iZ7p5Q23Kd+vg3i6Cyd47tkZtB3MKrQH65w4\nounvqLj0507L5hlg5DSHeXFhU/o3ADtjUTpnWVyhI4jILGOC19LG6caTW5C+\nBmHEobkIVZxWiaYM35Q7pdnREEa9yCsn79jgJac+rO9eUk1wY3m9vSkzicKo\nzz6lR8GL46qABaO9liz4vzJ4s5zpfw42AgfjFhJxePW6Mftf8VDNGcNGuthC\n38A80jXS8FInHT+LFl0SyPH3i4uI7thydw8NzTbXnu9k89HH4wUAOAMM3sTT\nT/4oskLiclnF6oNcg4LUQGzN9sYeP5JZ5BjM9PSjUU9bt6EVxq2yacYoaBr/\nhPpRMHl+x9AGJXFFPXfsNJusOIp9IDYIBPAKW254A4Tv8IrJS02XlGaaAIBP\nsYnh\r\n=pqi1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEN3ob/3llL04jHpLl+EqxFcHBmfaE1NQ5+EC5nlEoXmAiEA9aRE/ZifFmWea6YsCGKnuE1zRgN6xU+FD+poMhRKBBo="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.6.0_1562331219599_0.8407764442676884"},"_hasShrinkwrap":false},"1.6.1":{"name":"alife-logger","version":"1.6.1","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"7e533b9810af2c1fae9e89e8ba76ebd58be8b43d","_id":"alife-logger@1.6.1","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-1ibWi8kK7l0YaZub5qGXujB9xXOQC87sQjgtzfIB209T3n/al7NITsT4DX4AmSlP2hqTl6dwmCUTJnPGINnqtw==","shasum":"79215238a6aef0ececd684ca2e0bef8614ef7513","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.6.1.tgz","fileCount":45,"unpackedSize":456172,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdJYvsCRA9TVsSAnZWagAAE+sQAIFTpsKBG4QO+k1hK+M5\nvXaBYq7jefT37LxPZ2hCqLr//Gfa5Xg0mVR4vDH4jyha1mzbv4rqnGc1vApa\n0B0urB+iuqEPaM7CB+f8KLevAmEsOJ4VOIcbQ1F2Vvttj8ZIOAmQrgIqzoZ4\n7QvqEIuaX2/9N0ktM1srmCUDbchEdKr0Gwab8MdBntsPEY9pDxYw8hYwfsnw\nyrgNiVEjExNd0bjNOKdnQXTnQSCrBMi/DVFKVjuEQmQ1IAiTCyikYlKbXEDR\n9yIXnz5rTqvsnV+4nk3stEKDjiA0He2zpBxAlTRnSP0NGla0V5MX557mUvZo\nqXtfSedvEbYAq/PsIOd4ZkU63S6uqPu8Lmb117LLTgc7lwd9ubArdst7LYaf\n0cNd17+7jnyCwcO9f3SjcGee1J/T5u4jv4vJjpNveeOTZKrbwyHwHKyin3KO\nhWOttezEPhYn3p2dJdnyOyvkWvXdaLjyfLs5Fi0gHagRcqf79Ybe0evJKvlP\nHLFuG3K7Z8gjJPTdngp08ZyYN6K9YkZkd/b8hG+zgdiAa+ytNpfb0NsD2B9k\nCpBuBNCR5toDQpLhYH3SHCRTRw69M913XEV0D27Vq7rx5bg641iKkLmv6RHK\nE/lvWvEmEhIgxt4pRBZzNtO88t6We6hmwUycdEsL/545VDOZfqP4liCghIb1\nQ6gR\r\n=RSTp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCgvfpqUnZN7ZNXG5wFkuHx+VrjnZDfh0hYo5lWahvpNQIhAM6g2PQ1rsbu5ciQFEHaDtMq55WjHsZwwkS+ljxtxFYu"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.6.1_1562741739951_0.6561295608593001"},"_hasShrinkwrap":false},"1.6.2":{"name":"alife-logger","version":"1.6.2","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"2fc8a6416b2d9da0a7e0f1cd4550c5b9bab721cc","_id":"alife-logger@1.6.2","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-I2FxZCLTqHy0mWSjpX6M+gz8lV1phjCd/4nM6nQa0SsgIv0OpJgNndhvRr2oQ0kccsusWMhSn8uFzCj8dEXa7w==","shasum":"1abb0a6d5ecdac3712a180049a2eddb7d147bc52","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.6.2.tgz","fileCount":43,"unpackedSize":501618,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLEqaCRA9TVsSAnZWagAAXrAP/03eMZOuJuCsYAewySnJ\nYVXpiV/Jm8EaOPY1u2rWmFHuK2bavN7lpI1lJJjxyQXie0D1wiTyEML4dejc\nejwfFx87g4Z4Fottu++nlkSTMSC+MXCh2UhHRRFc/loCqmOlOMv/zcKoclfL\nQEr37EfHqxB69ovF9LFNyscvU1tj9nrd+2DNYwE22izwNIIknghQsq+okJQe\nyDtjhVRhCsxdJEBn3HBAM0TMOv0Ru6leFM+f2sUuGw+rq0TRRaYeRJHPPXfV\nAARsdrxoM7yTB0+5FBKwEU6TawUgnAHZ7Dmz3/MLgb+UbSSv8tI0ydyEpwlE\n7u0L48/4Vsd3IeLt2V6ILJreWMhD2mHmvrcvlnpfrXfwGdAVFwEIibP0C3rq\nzI83n1XFVqCLp8Qn/t9CIdIw4YbRUFMQCC+D8bPmYim/dH/y3iVpZ6PwEtLh\nM3KoKzSyieYPoLlxQw9GlIATg86ZhKeBmTLPh/gvIec484ePm22gqzvTQtQY\na1mKGV3SQLB7Y8fTBg6jkW+zvMwTewJbvg6JDNmGbeoVP/4kFFdK2kL5wF5j\n1tETfofMHUUem/ame66DC9VyhpSVVmQHZd1bBkd/jAxCInl6SOzvWIYM3HmY\nFH4vElCsI0X9X7nonXgEnv9QByaRIMixeMGpF4KSpGuSW/H8+7RXiZ8xgnsn\nhCOD\r\n=2QWU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC6Pq/bRDegUPSPUSo0wyC/aPwnQV5dWj7dEBa5SFiHIAIhAPolZst1kgaB61MRG28oF9srntAMAQhqLgj/mp9ACqEH"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.6.2_1563183769868_0.24055653320972747"},"_hasShrinkwrap":false},"1.6.3":{"name":"alife-logger","version":"1.6.3","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"5f80d1ca00a72bf569198e42ee38a5f372e549ac","_id":"alife-logger@1.6.3","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-qbpx5o+1EhlRF6amWN3z/rRhMBzdDbdnpAZXnm45MeH8hP9SxWhbcxxAp1rWlSqEf6ezwyLcB4f7CK5Ms6brbA==","shasum":"d41cb48af6989d90e2b30847421fce9b8841c738","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.6.3.tgz","fileCount":43,"unpackedSize":501619,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLVkXCRA9TVsSAnZWagAAEjIP/0D/3zYPrsForgBlugvw\nbjtoDmNADpDcEY6FbWZ0TyXCBqF/HtFC1YI/6Wtv+wfhM79abqimM/cEn+YV\nGUSM6yHLMU7QqVoTaKcFiQrQQ3CasJ1taI/fQqd6baXN6j6In3fyQlXNMbfd\nIl1VHl8ds504HmWV+MX7l2L7agsIMgIGJj9DioeDIoB1Wvsscf9oBwD8E5j7\nELfST09sZH6YwOdRiXMJqUlJn6s4v3x3sL6B68J5P87+pQ580fSjjPGMg5j1\nqbAM0zflAj465tiNhwS0kg4FsPKuhLY2TAMnrnTHepzndH/JIzGComMme1gp\n6KlRkErahmP/Fq6F9A2Y32NBsKeh5ZvjZZlifeFJ66qwc1QHBBqHLkwzBcfw\nKNCaBU8anzArzrn80saGh4KYhga4H6LvzUANanxLuQa84v6I54nautTRUjxY\nmW+JwGvNoEgm/XC/8WlBJ6L9j4GA1wvWYPu0nz+6hoH7wS7O8eIFFOZ5KwH3\nF2ZEjQMa16FIvbkfeBnJED7hz8DJFmbDCclC4T92nDOkqTDC3jg7MmdUcYSA\n5BeE+X82TyCU6YNVdcj8ifF7NCA+Ky/oOdN33eXwK9IPQPPytK5O9WbQdB+B\nqnlB6XFRHEcVnYsM7/W1PPgktNiUJcemHY2oZ5rBGNpGVzVJ/bnQ7H5Uw830\nvDtI\r\n=yy1V\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE4PeEo/zcMKiYd8RpQJEsuZRo1E09SWiqQ7dcr7ztNTAiEAkDTTYflMueAa364TsanWYwquDEi35rAMClMoLNY9xko="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.6.3_1563253014699_0.3265709331707354"},"_hasShrinkwrap":false},"1.6.4":{"name":"alife-logger","version":"1.6.4","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"7a603d9f8c7b3dff4cebd73e95c9deb80c02ac60","_id":"alife-logger@1.6.4","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-7uIxqF5yQ9tBB1DrNcZzYklpX1oQ8c7/RsoPIBcuedjpxdsnGFcE/gFvie5f0kIqlVePXrtAdzy+0gCxUaOvyA==","shasum":"128d4cdf44114ac99f7026c5b63d6089718c5999","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.6.4.tgz","fileCount":45,"unpackedSize":441818,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLV/iCRA9TVsSAnZWagAAYLYP/3SrsQZ/YYDB9HUOCkZ1\npDAbPKjE8CUk+RGq6l6bp1CTq3lWSqz31mvdhf7fa+IZxQvFFfMDn0KwMI+w\naG6FeODRGeFA0gpAkM9iHZEIJpODPXKgABGc2AdD4QkA/ukeIGASk/Vc7GLv\nkQTwZIsAfUehV8yeCNyVf6xykzezaLxz0h5Hhfb7Lqilljco7fuZVr56O9co\n4gRgCO7JyuKF/gnIuHb7BjG3dDIKvrpsHPUkTvJodwiFvFy3o+lie73v/3LR\nqwz5WrqqVCDUF1V02GuXIx8S/x+KWJnALWzBoxHizkD9p8zs+h42UMKLmB2D\nMQWy9JinoY3d05dLD2moDJNPBhc2O6DK9rxnugVYRlaJ+NBobaRX1F8Gd3KQ\nbAIXZ+OejZjipuDuK5zajXxPg+Shxd0pofEa2OH5MIRLitcSR97a/Pt2wzk7\nPaZO4ex9UQ5ZFRbDWhYrzxS5hfL9oNJEC5xhWWSqC26udvgT0nLNQ6Von2zq\nEbbWYBrR0aEzEP3VRMOI8kdr3rrVrrpctHaUzIfkDCwNO2zTQDBIBju1g1EA\nGwn35L45qnhE0BGIOW69uAEIiCZElrjg8Su2jysotETTnCDCiKbvD7pplzsq\nGEmc8riyX8UnzvCUPthpCBfZ+jt9ASMMIEpHzzDXC1dp0f5lZE4z7QgMeFTy\nU83p\r\n=Rj4c\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA8NYOzUVGyYpvxo7H5559kaGG9BuStEA+bYqg16ajEWAiBnDyClo6q2PVXBoZmbx+pZ/cPHuMK6HgnqBTkSSwu/cw=="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.6.4_1563254753156_0.5578134820806868"},"_hasShrinkwrap":false},"1.6.6":{"name":"alife-logger","version":"1.6.6","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"bd7704ad54fc00190703695a3d3dea4d7f79e307","_id":"alife-logger@1.6.6","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-qj4ttVcV4rZEe8VdVoID5CJJXcK1YSxQ378q5Hp9UZy4Gws3YAZQLAz+jbpfXAxHTMDCtdIT+cA4gJV5A+2uBw==","shasum":"e68fb6b647d7e3faa43741ab579c617ef75e769a","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.6.6.tgz","fileCount":45,"unpackedSize":413576,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdMFBvCRA9TVsSAnZWagAAYkAP/29B5KukXHWyN1AzLmOM\ngwId7rwUdQHyYbb8/www/09cnt2kMbsggbpG+TXHqUbpqx/h+cwcpkkHUhKL\n5XGaLATpZcHO5AadTyQOW8h0St3428k+J+pfResODpitAWoVV/KefRjQZu7M\njmzUNCqgNcEfqcU4k7esJEQVKGj0od2zhRdtlmmoVEYfg/4PB2TXnBbcCACN\n4INZO/rLqWItcVd5JmhP+N3l3OQu+1s1fr0DKfrt4SfJ1D0d0dk6NFb5exIu\nylfLsdCXx6okmNgFHMdQ+CGtLMqkfUf6bMqjvH3+ZbNVxukbe1crm+AzqpBU\nNxArSq995itofQeNsgXYp9aELNy8dWKgdPGoClZD4TPT/msGzijFdut8g2Ks\nl3k3qOdYXLW6yKWJFjEIqCitaxbdE+HkFNOgaojXKFZBjqtpY+pwkBtqJleN\nD+tBttXe1sPMJ/+bmCRTVkRU4lgOAeaSHhvSCZAD+3n7yf79Gn8VqHhJjzvO\nZnV6bcPy3IoqRMIOSBAI6jFyStTMYhcynnWgsCqUUfO5wK4BOp7MAJGJdEum\n6bSquw1pm34ajHceAM+h+H8mC1YB/A7HmrQa3pMdtM/V/TVJTr9n+B60UzHC\nI5EAch/u0Dj/j/appat9ZLP320GfRSdkmJ44AgjPrWSf+yohhe0iJHpZ7/+M\nws4H\r\n=uci+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDXn+4/iqXAXBMCUT/THu2/KxGKtZSsL9LLbNI8mmX8TgIhAMT9PRr3Wx0Rt/SSac8WtN6m7Qu//9NMi2Mq4SHjymjF"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.6.6_1563447406541_0.9803614816806308"},"_hasShrinkwrap":false},"1.6.7":{"name":"alife-logger","version":"1.6.7","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"5c9789ad12c0963ba92a133b776771aba591fca4","_id":"alife-logger@1.6.7","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-qdtJ6OmZ2qUCggtepVB1kaGdQZbpxgAQHrLL1n2YOO/ZtfDzpHuHvN6v0t8J1KEqaXrNJIH9kyBecdYSgRFwoA==","shasum":"3d40115dbcc38edd484763b8e19d8b84ddff800b","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.6.7.tgz","fileCount":46,"unpackedSize":420773,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdNxl3CRA9TVsSAnZWagAAJ4YP/R5BwmeC4kJnSbAuveQB\n1x0wa1k5dG1HKqUxpOPV0Vwz5tR0GD81UXZ+28TGn0wnqfw42xZD9gfSP8CK\nBd9bNYOete3x66PMPsTPL2yOLua+bynmBwmXwVXDPN46W/PxuK3XmiC8ZDFt\nhdgY/RqVFXJ3/GNJxW3kTy59f4j2sXixjfWa0OIQ2Aggbm95bdMbs8yQKx+n\nH9kyQv1re+LlWFaKH+ybKLi/8Pn3m2yRrReQp0zhYhfzdGdyiJid/B8nlIbA\n8XymXDOGdKc5x02YAfQJQTSM8LxMGpnIT0Fj3d/dEnH/sOVB3/g/jFrvl9ov\nBYIVcbW1GxnmY1zS+ZXhwHdCqhOGjKKxQb/6msgZHDBkDltfZcVfFD4tRqoa\nCDMPvJ0hvUNQ2End6nm9kSwamGGpEbP0su4vqHIU4HYwhUKY7EakhRZCPVNe\noOScZgZQ0fGsxqv9h+grXvcRxiw+xaPpEvWzClyzIlgXO1nRb8QLIfywdXus\nYktg5KPNy/vByt/7Udk3NtzbQAL03jMrjrmHYVyrJ4RQal1XNSqdHKOa4JD5\nablfPJLmjGyBkP0KruSIMX4TudixCjIzRO6MC1/bQuy2jAJAbcBi6jxnIHlc\nBFGKAP3WelNmZVFPw+usR8LFT1cXC2GgNkJ4Wa0sYTMqF75IIGwCFloxVEBt\nRXnh\r\n=qQ9Y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCCVXYh3d1DxBMZfadKFCk6/KPRCZAZnXGE23Aovej15wIhAL18ARfIw7jtBskgOHb5+IN6WJyIb7omGIWgDgRFdLE2"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.6.7_1563892086951_0.7049184316850143"},"_hasShrinkwrap":false},"1.6.9-beta":{"name":"alife-logger","version":"1.6.9-beta","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"21955e7b992b29e2c42136ba712f614c6431a7f0","readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","_id":"alife-logger@1.6.9-beta","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-+dgT+cl2v1kpsTtZcBZtkZ9x71c3Mw344Cs6QRz14swMfX18HJt275FqjwZ/0aulrr0xOuAf43g8YJLAa/TmqQ==","shasum":"e222ce0656c94e37c93a89cfc1d30bc543e1f277","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.6.9-beta.tgz","fileCount":49,"unpackedSize":477899,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdTV7UCRA9TVsSAnZWagAAO/IQAJVb61HrhDkHo2FRmour\ngJ3qVVMRX2e+QhdM9mVqz0ILutU8JXodfQfjV3WKgxgUITrErkajI/W8vITn\nJc+k5kjfBENuOXOUfc5fCX3CIOr6MpdvL8PeKOt89ifRai+aYr+xNvRfX2Gq\nMMo5Ngcb1y8i0viiaLVo1uE+PZC1mXfHhKnpqireQ3ruvPs+4unGO1RSMXJx\nJtFQ9/tbCMFrmUDd4g2isO33l74NQH+RJJMg6U00ZAFXn30MOMAi7SUicATi\n9V8uvln9yQmSNKLxHsX2el8UvyPQyJLQ+5mnm689BXzmeqyxR4ookelbAmZI\n7ezosJ7E8hdGO06ToP9Jg3WVkH2HzKL4cMZaM+Emv9hAUE7WDAOHk0SqOf6p\nCVGLmd/lonE57VLdNSXbnd0A8cY3I3R5MRPEBGT17rUFUanC+YGGnyK9PfOM\nss12zVL0WoJKy0rLyXovdINr5POKZ+2huNDZ8evBJIdIN4uNJ3MgukrWu92T\n+39AtG0ldoLeWBftQ06lSj+10KSY75uFSImhAIT72K+CPx1VjxvCUBHvBI2E\n1EkYMzeRnSQVZNj1lLw8Z2T91Mcz//S+AuW5kYSSVpkVuVCKqgZUbCsfh5+Z\nxpfyShe1svTYWQv3gJZSMkvs5prpY7AJBiIgJSSfavJa1Wn62xlJEUaXP0fC\n+Fyy\r\n=AZt1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDU0MJfvEu+6yuxPbvGiBoJ6+NtmV/P5T3rHtOa9OaQNAIhAL18CXclb5yr8ZASYuzGIXMFnDDU/S/1LlHDTdeBHCKZ"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.6.9-beta_1565351635894_0.4297759575901676"},"_hasShrinkwrap":false},"1.7.1":{"name":"alife-logger","version":"1.7.1","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"79a4425f837979ea6d4772b025265d91459f8aca","_id":"alife-logger@1.7.1","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-SqQqh1vSeqzimf+pG1PcGTyGjNM49xVm1YP9cs+g/SzSHjSfSRUadDBq65bD/BJGmKuXQJLuSwhGsa72UmtjYw==","shasum":"ef873011c79023ceb50eb8c343fd210742b9991c","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.7.1.tgz","fileCount":46,"unpackedSize":450436,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdW6dcCRA9TVsSAnZWagAAwFoP/ifZtKge9NVzJLGL/3NP\n20My0cFE0U7Aq+NSmRghq2a5bmYVnmfZ79pF9J+4ntoP23MUamwhHA0Ydu8r\n5E4TXfeVAPHnbwvPjgNtPweUbDpSy5J0uN5MqtXY1/OhfbjWJwpGMIFmX6KP\nFguOZpgkmJSIltOfxp7NAV6W6XgJU0V5tFBTNcGBZGpcwq4SdPrzpJ3yajba\nweNwe9pN07rsjJLVzcz7ttvmevinoP37+AA5u+uJjWVQrPpYbuy1Ov+Ss6dU\n47V/nKufZMrWqDsAvElNjpOp4W87LjM3uHIIbp3wdhLT2uCkNCq3dKBWXCws\nW1/gndbwWD/shu3eU5nIeXznzJzSYWVp9blVrvBrgioGI3sU6/vitzAIUVhU\nLepCZRwG2IIe2H3v3c+0IHhSkKICLPNcgnMvw0NpeLA7dHbCsGkhKD+mVFkf\noMjlJ+YPPPImKJxDOLYyYxlAY0RDyUal49Rp+TgpiAbUwYOe7faUi4/xGq5U\nLzmDzojjKIOOTnktoJ/UcafYb3yBEcyhhs821f1xVX7I/w955ROUZcUEiAHn\ncRtXtxvJS9YynqrdNS5pwhjvTgwAUDWyRcYeT1JqgiIhQX1FjvApr6Z0t76o\nd2fRqP0sUNWPsb24lDVfpdFMbRAlFgNPRIrcoJCup6ZiKnVIgNZ6h4ULNd/J\nbiEF\r\n=Qhwm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGOnD1KaP6ek3dkQkImyA/AObRzZoLKnWhUiEZBWT8NrAiEA/4W5TyLRAENtdFTx3rmIw1eSPuw1ZriWMjWJC3YdJ9Y="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.7.1_1566287707422_0.4289845133853649"},"_hasShrinkwrap":false},"1.7.3-alpha":{"name":"alife-logger","version":"1.7.3-alpha","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"1fa91210eeba792c4c2c2191600010b363ba4f4a","_id":"alife-logger@1.7.3-alpha","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-1e32TuOc0nAafeZiZ25fgg5SDcDTbXfH/usJV/SvYWX+RS45Fsn7GWT9rspkkeBoMpCNvQUR/NZ+/vpVExplSA==","shasum":"c5c02ea7dc6c3871314e9d3a6dabbcff85c8284b","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.7.3-alpha.tgz","fileCount":46,"unpackedSize":408220,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdb1XuCRA9TVsSAnZWagAA6c8P/3oqFDfOlczxH7AzR35S\nlIC/B9jwqOiEQU6rahJQNoenImlLFTz+qA9FZz+MHeIUTL/6i9A2Z9IrTOp+\ngqNonnxlPbcSm3YI2H1At6QmGYx0rn/eB0x6KJHEEHtpvMaPkRIKCgIiY8Cy\nupcLeMiseZeKNMeY+9Eo6dGKCuDATs2tS8CT4inDVjtOfG8Qf2EuayKhGOLs\nnuUrJczmQ9WnoRyRfNxVTcZyAevG6hfQa8tBCVFlgdo5tQFv7DOpEU5054qC\nSEHTGu4tyxsihRMZO/KICWGK9/6+buFu0fOKKngzXHVQ4wYUy/st0NFSu+z4\nmE48nLy7yzJj8lzmykBwQ6wvY04CYisgRdBNYY8bH6tBCngTuFW+g35JCt6e\nNNZFXa5efYVpcxMW+PAwBL3pRpivMyN59cicjjrH8mMWL91nWtnuN0UZEFsM\nI1qLNQg7tugIVla9RPRTDWxm3j23J1sx9yR8MbKRA1eeVGsd+IE18cMtmRww\nEjr1P6GuRiXkt4Ic3MhmjLBPmrLudgf+qjrCHC6AI+sjZE1DpYAoL846tJFM\nUnXNxmt8feKWj67ubcna16jsOcoZRxkWnY4dUfeTkjxEU3QzAKyD//ckTORP\njch5S8W+5tpVq/Ee5TwCGV7vDBAk7JmhhyCeC1UuSZGI04zheTu4ctKHscDh\nTzXi\r\n=DOis\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/7cHfo5sMZ7iQ78uyRTP6f2Jf9OhOAjnXee3+AZIbFwIgMQJx0s2OAw6Uy7skgdG77aLrR9iFE2GODjMEJUIwwXk="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.7.3-alpha_1567577582013_0.8870735282676463"},"_hasShrinkwrap":false},"1.7.2":{"name":"alife-logger","version":"1.7.2","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","browserify-istanbul":"~3.0.1","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","jwebdriver":"^2.2.5","karma":"~1.7.1","karma-browserify":"~5.2.0","karma-chrome-launcher":"~2.2.0","karma-coverage":"~1.1.1","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~5.1.1","node-fetch":"^2.1.2","nyc":"^13.1.0","power-assert":"~1.4.4","rollup":"~1.1.0","rollup-plugin-commonjs":"~9.2.0","rollup-plugin-node-resolve":"~4.0.0","rollup-plugin-uglify":"~6.0.0","strip-comments":"^1.0.2","uglify-es":"^3.3.9","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"51cc7c0d477ee4871de312f37ffee8d51f86363d","_id":"alife-logger@1.7.2","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-XX/dCdNNaSJf7IIh1pbiZH/2/Co8ITJnLRYa8bftlM8tl3EgEz3Yj6Vt8eXYb/jkcD4ebYGUQgw0ARHhj5TvCA==","shasum":"134de45b804467479470563660e48eb696240bef","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.7.2.tgz","fileCount":46,"unpackedSize":410428,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdf45qCRA9TVsSAnZWagAA6m0P/iEBLH4a4GG7jAmr2AOu\niLudHyRRE7xOaFyDcCWnpwfR0MtNZ7BP7laafQxv4Nu5QVIerKUFRPT75DZF\nBIiyDWTl5C7sffDf8vL+IlDJXCFLGt32WbOSJ3RNaUVINCO5k0sbVkwqb3xP\nP8m5I06p3UXxh2kFlykdQNW629/Pd7vuM+XJk3uumtf8BW10OD80MVhNJ+iU\nj8iqoNpVnl89HqNTpPYZbSg7c4Y73L5yfa87QbcLeKlh96HAZ5kru8CaoQiD\niU+fumwacnVrbgQwO47cgEmQLvPlfT6hYOPIrYlvPlT9J5Uv7/bbvNRBDzpO\n6QgLKRP13Rmvh7K2HGJc0WBrf2OdN7FDzQgCRvSiOWqPr1Sq0I1Kg26Y2yTY\nGO1/uvKf6URsJaA+qy80soKCkNPi+P2ZxU6hfjKZbhXXweA+Ba+gqQ0cU2+g\n0YhNa2uaf6GFgEvyBsmcKWEvEtpjsaMKTMMOlZQu07kYR4m5rmi5LWarcDob\nA3XdbgBycg2RghalhYy93++dPT/H1FGcIipPaLtBn2/zvVcnsupxtmmsIKdp\n60ID6DMtpQGWCcylqSNc8F5VNCb9koiwE3xGUOZkXAP2usQzDBfhkekR0Sh2\n/WIU6YP1RPODiTFLOaHO/cdkoTDwQMvoaYPtYvgvm+Qe/0PZPI+haW90QNLP\nvGU0\r\n=bnC5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC+bfBRamgueGZINF7cya2sHbDNbjS//pGQ/urQ2qt4KAiBvNBOfxil2Xvu/fq8B9q/Rt5uVDf5LQ23uzuajKfLkbQ=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.7.2_1568640617427_0.22988496873890107"},"_hasShrinkwrap":false},"1.7.4":{"name":"alife-logger","version":"1.7.4","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"license":"ISC","dependencies":{},"devDependencies":{"aliyun-sdk":"~1.10.11","browserify":"~16.2.0","browserify-istanbul":"~3.0.1","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","jwebdriver":"^2.2.5","karma":"~1.7.1","karma-browserify":"~5.2.0","karma-chrome-launcher":"~2.2.0","karma-coverage":"~1.1.1","karma-mocha":"~1.3.0","karma-webdriver-launcher":"^1.0.5","mocha":"~5.1.1","node-fetch":"^2.1.2","nyc":"^13.1.0","power-assert":"~1.4.4","rollup":"~1.1.0","rollup-plugin-commonjs":"~9.2.0","rollup-plugin-node-resolve":"~4.0.0","rollup-plugin-uglify":"~6.0.0","strip-comments":"^1.0.2","uglify-es":"^3.3.9","uglify-js":"~3.1.7","watchify":"~3.9.0"},"keyword":["retcode","log"],"gitHead":"9f59d04703f453f286b96c0ab4c390d38eb2e9e2","_id":"alife-logger@1.7.4","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-7lyFN4aLdA4FxxXGK2dlrrWYLLWWm1Bpi0TdGQPwUb9faGB7B6NU64I5d+rqHCKrYOyfofSmWHzn766vEqBUow==","shasum":"d1c57928059cddd79fcd166cbcfa9ea2d5dbc974","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.7.4.tgz","fileCount":46,"unpackedSize":410636,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdf6SrCRA9TVsSAnZWagAABVgP/jmAtbkC0LzVSBlXvcZz\nigIknqXXfRlABCBz64a5vUi4hK+8VM49kjbbDrkX57PCMIl5LpRfJ51w5Mv9\nhG9xeU0MatCPI6LXY38tYE6qwxVoLWfd8+0xArgcsRyjIQBHOWmCzFVPJ58u\nqH8OA+LPi6VR9SaWebxp4wXfOo7YO+w8ZWR/R/VP3SwV83xsAH8g4HejiWmh\nXSm80yMB9MaMpUw8XH8DjOQyh+BhtYljxlBXixkaMzyRU9sRQ3L+0w7kMOrm\nQO0YOmOTRLOQLs1igRk0w92yKuJ+8beDt0MZTCvSp0JZVhREJDpjRBxFBRmM\n5pAiGMr/n7Ri+v93Pk+k8FivviZf1KGOlrENj3JgeBxWJwuSFX9e5PdkpuiQ\nRt3WSDEQJv5X7eXIfyiRT2dv3Cdz/Fb2l2A3eGWaH5RY8bKOoq+7M/ENPS59\ns5z0VqD00GRrRAVAc2tMIT8WZM9gb+t0IuVoBrRTncQi6qj9FlCe4iJW4Iks\nmD3McWS4QHR1Bz1GosKbOuPVULQxpa7WOn4lDdb1qhTRAXDsiCcr/69tTv/R\n6DrAAx37wqhQVdndf/RHHHC+srRohW+HrGS33oK1qZhrXe3cZpj6y8qJjVOD\nAeAX/u9in76Onx3h0Np9Q6i3gJhRTwxLBLR5zxrv0IIFoeUoZLbXogt42Igl\nx255\r\n=dDLL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB5LcRsqJTnoZd9dZZpBN18cmEOb6eAZd6U/ZCqusVWgAiABlWJRs6GSb73dAzSzQ3ccjQIjz0dMD/8TuBvqTQdT8A=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.7.4_1568646314500_0.3876972024876044"},"_hasShrinkwrap":false},"1.7.5":{"name":"alife-logger","version":"1.7.5","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"805fefbf5807386cb2a54b140878180109833e47","_id":"alife-logger@1.7.5","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-HmUAiRJuBeRquEgGFVVJKKF04ge7riHsbTFiHb5zE4wvXrz60D1QBrqYYR1B82dvNQCzRn7nJXvOvqGZB8XOgg==","shasum":"8c0854bf17a297ee5d67e953a0ff16d3599ce7ce","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.7.5.tgz","fileCount":46,"unpackedSize":450437,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdgI84CRA9TVsSAnZWagAA6CoP/iXa6FW2j28PQnbnzi2l\nMgd0Pjv0WHmihZxzqBzlqqO2VAEaUWi5Wj7GmzynJTIf2jOHmcPxFJV9gtKO\n8DqVykxClkyIWP3Q9rEDKrwNMSjEQBQmi1mHvCJ3g2Bb03WGHrVCPFWfwNYG\nCwBoKDi2+ZkK3mH7b+YJJEodxTvE1ZPfeA6kNM7sIhe3Yf0ecW1xrri687Ob\n9IDNKLcei0oSdpMA2aBTluJ5IYHXhl/y0aGlTWCtEFHUfomFiS6jKKcjLc3+\n0eohMysaMq2F3+g1q/p7Cvo0O33zitlUouSiVCA7CSw5JZGs+a//W3Bh4QkA\nHiM33o+LhpK8cw5KhkP5smfV3tyZXA8IwV8uuHbZFCWN5OLaHWp14rgUJRXZ\nBNePY0FuGNKrvbjuLIp6Wuh/AeLPTeQ0s/K7/4DRkXLe1UxAC7395jseB5CO\nM8tEt4hIg5MFTMkj/4s3dnlzXMCdCxfAJWZAk0+kfHkkVKuKrFeW4ksLq3sh\nJr2P5/hsuhitUPgQMNor8CJPza70BM/i6k66UP+SwcaK7KIbwSymH9JIunBF\niLyWxkZ2OJ2tkQvcMzvhS8md9uyREKKIh2cm0fem+nISp6T7IPin7NgOw33f\nyT5vfqeESn1yWTKqMuii4kfLGZx047z61N2FBzTapO0MHlvTV+9zY13cr/Id\nky5m\r\n=IWFS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH0navfVaFc1E3aQ7P7RsYPhgW7obBcAJIqsZR7SdAjhAiBvmudDAKVV3PrAndUCB4Rm79nadYASOqteHnaS19WXpA=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.7.5_1568706359937_0.08461041701406091"},"_hasShrinkwrap":false},"1.7.6":{"name":"alife-logger","version":"1.7.6","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"f3dc8ee976095920478001f58c7cff850a047885","_id":"alife-logger@1.7.6","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-1AE5lt9s7lpw2faNXaCwxBbAmX41MqxMFMJJEtVBKeW9NyUjMn3vGaCcIBLLRFG3P7BMzEn2fNsrzNzw8wSXDg==","shasum":"97b921213118be831d2b7108561944e1578f5e02","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.7.6.tgz","fileCount":46,"unpackedSize":379138,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdg12NCRA9TVsSAnZWagAAIUMQAI73kl8SXUyCZ+0SqjnD\n87AiDCCCuRe7B0o+WGYAFjyMovjmPHprUzAYVKQOKxDw/cuXnYBVePupJura\n6cXcsQBrCbRDG0yG2cUPt9MwLybvPdpBR2U8lJ+AaS4iQy6lG/YInmSvs4mE\ni+31Qn4Sor1P9TLjaaHwk2VJefWYS2IPj/tfzwpDJ8rxmBFAQ2un3jMZySsu\njT/lKEiVpk1cUOYBnE5pyxxRObracJnLB1Ay//7WszMQ1rJY3KeBUDSllShl\n5rJLkpEsVOj+eqgCwQr9JkpjT1huKWfDcEe6tELpU3URBT9eWRz8thuU51dp\nvLAvsDzoxOGQndP5IueKCwA/tQmIlG3I8JNnf2VE+PNtSptwZ7Os/leO01yN\nlfN3vFL29JYFzkuiniFit0PKsx1Q5H5uJ8ah5buj7LdSgrcboGl0bmhdAijp\nQ4jJ1DUsSslgYJCemWiOecq/3FClvccEdMh5UX3Qgiu78xH8sQTCnvp3vuLP\n9pxC2JEPLSlRtZCt+Xoq92jWSr/fOXnE8QY93uH2odvuQAqTQJ+uToihwec9\nGSwC6dJmjHtzHjt6sa2zM8Wza36HPWrfNIzqYNau8NzgXv8Z73IJurH3Yc/y\nOY6a49QyqGsgeYGwCPm8fy/O2hPwUs4jiKY3BKPFBarJ309b8AEnDzdk2Jyb\nyfft\r\n=tkqs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAWj68n2ZpknWpzPqTCOeGYAG/gERf38aQnOEhGeYo2/AiEAnYY7ult4sMjA7BMwQuOq3c683Hh3JW0+lEeAfml1Q0I="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.7.6_1568890252524_0.08963287675616693"},"_hasShrinkwrap":false},"1.7.7":{"name":"alife-logger","version":"1.7.7","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","build":"node ./bin/pack.js","postbuild":"npm run lint && npm run test-miniapp && npm run test --once && npm run f2etest","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"8aeeee9f637019c377dfcda54f5bef0ae6d3abfc","_id":"alife-logger@1.7.7","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-ZTtKKmLeZXbipwm89Ilz6f7uFIcVbLJi8zLY7wQRzLK1QbhSRDMfy3MG1UFWnsEC3cBsbcDXckZHPUlbLhGS7w==","shasum":"50c15bd670996c3b92a831fa439e0b0755030b3b","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.7.7.tgz","fileCount":50,"unpackedSize":495317,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdiLTNCRA9TVsSAnZWagAAFWYP/1caAun02Isko9/wC+rZ\nLdQLeYC9WsH95bKwpEy6WFIl1b2GprLoBq9LokH7aHP6TIswfMPzdCy+chrK\nKkm996/Pjv+h1jcDWdTePKIc6/N6xW30E27T3m/ObPjKjL2uTx/1NB5knaSu\n/gs+1d31MkuAN6+wkbEe2vQf/tRlbjvFNNQEfYWkziWYnFtSm/Omcs9NsBxd\nI606fVOw6wAhfJufCVIRUqJYMW0Ro8jI558cR5teA60GmVsM2lZ3HcbRcXI/\nFJpx8ZZfoYjCZQ5Ay69yOHMdz/rH4md6o+fLVGcZ9jMmZ0KaZnJe+ow8PEgc\ngcFOo/7lxrBKEX6lPzsMPQ/PVU6QrfbxLcL7JNahZzGXfKczLMaHORhlxRCf\nRPzJXoGp82i3MOHtyopbsBNP7gl4yNa1JOAywF6cbzk9qhNJo0c0Mp4XW1tA\nPWAvDe3so2xRfqXNroCH4x7M4ec7za3NOHLT7HOZbNmUi6hbdCysrPccKRrI\njzO0jzvsvwd/eL6Fv2ea06ovYVAyrDWkO8P5FeVuqqY7saH7IxdgbdPzqv29\nGwLhznciwtMxuiFWRjhU5n8vWZwuCCgvGKAxFTS9RxA8ZaVA68dFDZ7n+Fmv\ndXvp8y4ArYyxjiN/jhmizspkqQZS2Gi0/p/UNIg1QIuWwriEA69INXNA6HPI\n4EbD\r\n=470F\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAzPJuc4osiR+W20ApdCWjb7PeAZDVD6lJp4BjvgUw3QAiEA2rzOUDc9pRQCKM55zJ7V1uvTKeTs/+6LJGPzIH7c2sk="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.7.7_1569240268318_0.4200975644803828"},"_hasShrinkwrap":false},"1.7.8":{"name":"alife-logger","version":"1.7.8","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"b6c435f70e5bbf6312cca6bd9ea18f760b52f002","_id":"alife-logger@1.7.8","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-o6nVbECmzcAtjzwDFseyt0vqpKsSFVru9Cr2dI3BQtvLr0NayYjxCx/xtoDRvZJ25wYc89JdXDJYVuUmo52ckg==","shasum":"9619280c065f93dbba7ebf0baff69f68b5f8ffe5","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.7.8.tgz","fileCount":50,"unpackedSize":461196,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdptbwCRA9TVsSAnZWagAAbdIP/2LzNtL1epECPicKM3gc\nun1OAbsR+QgRpdE+pc26QOlCMi+zOGTBVnLpigB9jsL5YJds873EFzfw/wjE\nqnXnLSkmNNrZcQQPsBQalyCrIs/naB6+e9gNeqle5Y/EtoGEpIAB2y63Up1Q\n+rgELd8vvg9CMMLvNF8nVmgM2XQDRlNrhQf+F+OnKqsx8gPi5aogQwRtXxlt\nONxAPnTxRoYoW0rdbrZNAJD9QOb2jTpfOQN1dXvQW8/Mwk04lp9tUmsH8BHD\nX1MlYbT/pW5A5i0JVpJY1rso84zI5nrsZvoyAuyLxaRoSjHhUx5Irq35GLE5\nBeZTpWgK0QfnaQ1U6PLTH9DQBF6OGbTIwIK19N/VkSNSE29WdmMkAiDFzd1W\n9HcP1XQ/s6ZTf67XtwFl2TzlubJPsg51s9eUZ+x5yWghTyH0OeVpFedpyZWR\nLpDpz34UCfA/+LTtXyT4ptXkJgQv5PtXbFh1ldNZbvNtij0SgGDRCzbUdIk1\nbEGrQL5gJENgUgiOdybF67/ig1l+vHdwPR30cbTl1HqOcYaYzrW4vOWa1x90\nuAafWGXbmTL65Cj+YPIoRT2idE+JPykoQkOXCZYA8ElsfqJgJ4pKXQV9P9mJ\nU9u/oATnyeHmc5lpAEFZcodYcGjUPEpYyax/E/N8mpGE3CMF/L8c1anj0bl/\nqdeZ\r\n=wZrf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCqXx/71Gfmc/f4UcXElKabVbFfnPQK/yl6w0taNHZBigIhAI/t4ohwjD1nYtj34nyJ9J660SOhej/CY5+69L14kIkE"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.7.8_1571215087578_0.9338917300757694"},"_hasShrinkwrap":false},"1.7.9":{"name":"alife-logger","version":"1.7.9","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.js","scripts":{"dev":"DEV=1 node ./bin/pack","lint":"eslint --fix ./src","test":"node ./bin/spec.js","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"8844d8780e11fa187ac6316a2700763779b467a4","_id":"alife-logger@1.7.9","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-h6H0AQQHzI7wUR1Dhz66tHeoHlv89Sl/V9/0oW/jnUBwZsiNHgzimQq5L4OlediIsZnzxAc14BNEEkm/eZb2Wg==","shasum":"b0aab6ec545a0ec7ef739e9ad9a9839d7179d1e7","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.7.9.tgz","fileCount":48,"unpackedSize":572354,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdrvULCRA9TVsSAnZWagAA/+8P/3oy3DFTFU7+IMxCD//F\nE8vMgiPBgu82Ai+prVeba22uvjd+/1o6DkwnjEFWCPm9f+lLrW2GdCPU591u\nnZN5Z8q0jS3VOsVz998X+yBp5Eo6pjxByipUdWGU29vxzHoBEr07JPUSYUIS\ns8apzUWME/coxLUhmzjRn56YljvBSQ2DQwjkzWmZGAnu5rtWyOq50shyP+3b\nfgOoFMVVCRZ1f2NulB9PynxhKdMGzWdmgBaNiw3pCjGZUMdYZUUK5vSII8T/\nxCRlNYmVtbGqqA/qzpm0L1G3BBOiq44oZ3Xg2IPvbn8dkA7aocOpi3mky3UC\nQHE9yO3Lz3IXSKGBekLNoOmPZ40Slqe14hK6WUDYzXLHfmx5snmzllbML9sW\nro1rCKrsuwIEn5x3WL6nObk6wQfsYEilLJOYLQ8cTAuLOXKZWojEAYAbmiPp\nlWKEafnhLtaDsXhU9Fg79IQqi6Z9SUFJmmfwicXJfY6674pq5DlZPPCzWxBv\nhd3VLlRGUemAXhuz+YMydCcopgevDs165yDUohK3PGv+BB4lr4sBhOjMwjqo\nDM04YeZ0d+ieztRTuxjXTe1npplKvZDilXeAEa/CfWsH6xFTk9J+DJ+PRV/D\ntem3SkmJ9TG793K9rKxYmYyAUiLYexPxwby4kchk0OMJNLRz+CulhWscpD9S\nfhJ5\r\n=AlEk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBeLL2ynUmPTjrLYl1OFb7m0COXsaxoXfCr93XOKu54LAiEApBpq3lbjIZuRBPWV7t2teUeTy+KOXD+W5PT4m70AH+o="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.7.9_1571747082647_0.7849716195380436"},"_hasShrinkwrap":false},"1.7.10":{"name":"alife-logger","version":"1.7.10","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"1d827bd5edd3f8220e58858efef88527d8c0928f","_id":"alife-logger@1.7.10","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-twsJzvKDLv+HTUAiFOCeW3KRAG0B1HcAyWLV6TkXuiMQjseJI9tn3WPHRFGdpAe/Of3mGKB7EdwppSLhofxi2Q==","shasum":"d9ffd027f9d8785ac8f5863f591ccf32de916489","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.7.10.tgz","fileCount":50,"unpackedSize":431497,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdznKaCRA9TVsSAnZWagAACGcP+QBcNMcV0gHbbn/EcP7z\nClsFtEhtPwpGJ8q9y92Lrj2t39PGH0TvNM/n+nYejthql2V9w1rmBTE5ZRqw\nDgiCSsFVNrWnplm2IEGSAaXGUbjNam7Wn2JSzPNTBqh8t3MAn1cmAEhAQuKP\nhWx2Guic23soaUnWOIaHfVkuaiXK1dvW9oZcdkCBy5n+046/PeilIvrU75P0\nS7Fhry7cxItIgTHN7CVPOG0kMyapxiiVycDsuzHJ5jVJ/BYlmGOWxZfSqi+P\n/9ZpO//yw2L84eI9JBrCEN0PX9XXTHo6Fe+NSHAr/43tFetlh811S6DpcwiN\nnSIbx5RQ/tdoyMEp/xt23h9vaR0vGOhFGfPDhVlBvR5BEzWJ/sFUUGeqnlgb\nGCap0R1R5S1SlPLbAcKLBUQyvCdLlMJE9Fcw6aYySchiGicaysKeJ73b0RDM\nMQ+4lFX+WOcHhGRXvdON0gpZ+MyuTkzLYFLxtJuJTkAfLNdi42eILeVyDjyI\nI5XTYp6NUJ1FXD6OFlxnknxEhj8+FhIafEDUsvXvDDrVKyskRb5A/mkf32i8\nocwRZhRYwl1sdksBQQaTFTTvWPK7i/lbZPltbcwLFGkMapiOsRuWa0MyPIx6\nugTX9aNHAmX86OVJeUuSZsgOa0+At8HE7fxemeHyMvdFatxelYWqk6RC1RuL\nGTPI\r\n=5tIq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCKFfWcO/r5LA0ABMYpQ1MaQYuIXWxelaMk8LcCTZ9U1gIgRDPMYN4pyu/lhe2L2kwBb18EoNHwYdOVVsQ/vQ6IHOA="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.7.10_1573810841384_0.6684513332680333"},"_hasShrinkwrap":false},"1.8.0":{"name":"alife-logger","version":"1.8.0","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"65470ffd8c0522d339c82d48d110ad1363e2b199","_id":"alife-logger@1.8.0","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-j44KqT5Wj8ahPrJmTm+ouCozpignxlskA8lzPwLPw6mLyuaAMV2KxKcSk0TYQPo2lrkkDjP9wxH0Qlf4zxyaxg==","shasum":"8259eb41fff4284f756f5a26d313fe85de4a4b4e","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.0.tgz","fileCount":50,"unpackedSize":543544,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd1SJUCRA9TVsSAnZWagAAKu8P/Rzwa7jXt/FGgqGuEAvy\n9vHY+50rH7ipx4yaDpmRXUXat5u3gMEd3hR8w2Rb2aGUiYxqf9GWwSjqVTpM\nH3le3F4IlCHSgl0fblZ0ooSGUjsDzjr/f86ROZA6a0XG4RnqqVkCd4MmnLyk\nS2TbD+ZB8r1Q3AKmqhIyrYJnfpBuxIM2j2eWyk8xs7DHQU/itbeE9DGTnh/k\n8QdvxhHlgOKvpuSDRSKjRaRPjZnweJFMqpb4x671R70Cp1UEXYApLcxgBrXO\noNMWQJG0kwtOiKg9iO6X3CNgbLRlcx28H+7tD6fJgw29BTcAQpHFHaHAgfOy\n1Pu5XOYlOeeC95hTpuGjwvGGeeCLjbNCRKB3jyrGHpt/JXhr9nA0H2x8Ws59\nuhIwloyUdUttOTdVIQrp4MXhy37OLTxH++opar2bmBoJ2PLOP9ZJsAgMMxuF\nOSuvvpJ8dVUP9detxOFnTXNC1a5b0F1VtRuvxW8ZJULCaJwFuvtI9T37q/Mc\njabYTYs4ef0FhzYWn0NSqcyy7JItS8tz330HTBilpmbwR2TVclx+t1E2ZVHD\nygRoh3Qit2D3IzCk+AY2c5r8YOVymEU5FVT3UXfxJ7vPlbTXWGr/mGNd+/we\nrFHRMaP+CQY38024tYBST4GWXw9dZphzUhDTtC2viOCQkTGD6umsPh/QT3io\nBDWm\r\n=yWZM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCRln1ZYN/oi5EsMiarSouqzxaJjkFY8LwEqrUXLgn4hgIhAJwheAbfU2Ek9qzdx1ToUEUHSUrDx4WtaIhxuPYueWsB"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.0_1574249043936_0.769819465385746"},"_hasShrinkwrap":false},"1.8.1":{"name":"alife-logger","version":"1.8.1","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"5c4edd90de3c86fb02002505c78cee5a9ed1fe78","_id":"alife-logger@1.8.1","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-RJCWiEGS7nyHaNj8J97j9GInbp/VzbCzPT52Uho6Sm0NxGUxZ0YyKIyGrEUHYMk/dll7o0dGLkXKt0ldJS7ZlQ==","shasum":"a2a9007370c4d65a033ab176a679c8fcf72a7991","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.1.tgz","fileCount":50,"unpackedSize":543544,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd1UZeCRA9TVsSAnZWagAAJsYP/3at5F/bauGmMrbPhR5Z\ncyH5fCzU/7g9ivDUCha/GbX3yCT+hk63H+yTGQGg+0Jsu9ans5S2Ee84fhoo\niLHRPWoLuf8oLDYHFjnRGYH2gXOcUwvPExMIcuLMhRFd5xMylQiqXucUut2a\nOh1QjlKjfUtJRfFaLresDkJcj+OGYDmXW/QsuMHS7uzln4rWkCpJTjoQXbPf\nkFsuKLQehtwanBwJjTuqbwBmqrKqZASKGFsSlaDTAXLEpgldZvA58GNmjxEy\n943qUumgD481AxnePClNn2H8+/GsVeZ8uOBLxNFNhZzOglyfi0qqBuLjPU4q\nRIGlpnOYCZyXhZwgT017dwcC5eOlBHiqqV0lAHyH4ReS7N5ig7ncHq7I/K+G\ntQO2Ndd4DpT+XAcMFiGxXZuvtFdHmHGJ+73cYyq8bkNsOWZmWmbJC5M+E3pR\nOND60PVr14LpDpuct21IW1wO9Rj6c+B1CZlu+tAH+a/j/rIx9c+RSy2LX05u\n2keHKT3YchUaIgSVP9efOc3e6fF8Ximgrpztc10ZsXOdv7wh8Ehj9FA7iHf0\n+oRSVUPGnds25tarUp2OfkejgsvA5c7F6OdkDgXV1bCoICPPwwY6g/S1ymA1\nSLFiZHlIDzTgKS44V6q2FKnQAEMW1oGLq0DWm/q5nQWbsStdUFVkZlyUkV9K\nCufQ\r\n=zWZE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCfm+jZECaMqmRQc+WLtrzk/9Dcyti1MPs8AkY8ueg3XAIhAKQtm+ga4dED2GNPgmW6lLIJO7L3Cu3UYrVMoveuVQ6B"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.1_1574258270259_0.37672371450040276"},"_hasShrinkwrap":false},"1.8.3":{"name":"alife-logger","version":"1.8.3","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"ef3e937dff65a60563db31a06c16c886fc7e8a89","_id":"alife-logger@1.8.3","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-n4Pofv2jXtnXW2iNRntSOl8GSC9y3Vou3XHQ4oQCRRhw1EVuKEWX3DD5BFhwPm3pgU39KOnHKkcZ1+w9L0huPQ==","shasum":"1e7743ebeb3992e9a078ca57a26638ba4546c487","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.3.tgz","fileCount":50,"unpackedSize":433372,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd+5+QCRA9TVsSAnZWagAAHx4P/2JSyCwWse17VjSfWM70\nuxrjMkCqQaez+yxDc5DagrWkvnvAyjXnv8bz88Lhyq6IeFxEuzCOTUs+hhMw\nNPEdmYQYaVjN8xsIMqU3wUezek00fu1AGC4XJv9jUW9nwEh3fKFz3r3wC2Vi\nJBiPQDdTnSYhoq6PTxyg0gSylBPj2PWc8991rpe2UpNkfmYqFzt3xQmYyW2e\nSHmWlT/hN5o7vKb8+C+jls0n1npKBCpmDFFPVwk47o90xSYZwNj73jIaw4To\nPjbyKYvPMK8NVkP+tl2IVkWIGul4PGLphWgZBN2iIxJN7eiXh7q1xMgfsnJj\nx+3mZzRfcIKYGEllvF3lmuYb+oK4L1KhU59njo2FVFtxxNgkEt3rWQugxnTy\nQJfIfZuBwBoQ15bfBziIt+jWaiuIGUa7ERZrandNAuZNhy6gQiQ1cyI1yAum\nL9g3bVtCXm9ojtCqt+S4G5tFuD2PyWCrtoCIytYzmxYzuIlQe0U/63hF0o9J\nz6SLwhUnBzzyiktnaAhMlOfCdgF6gbTvEYcl5BLKEOEc+ZbjRDFK0eoDGs64\na4poFP4QuI9wW0ho7C4qb/v8wjSkVQIyYRSdse0ToD/mylAshFvwxni/Lbeg\nAbfwTX7nk/6LPIdKj9cpvS0+uTLUmPxpGclb04jW6AJ65CB9qIhrFJyzeu+U\n3NTR\r\n=udAx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQ4rSWZr3vZsToZXXMnkaEevcULcRW/pHbRiCfcfM0CAIhANuBK8A2UJSDjgdU46q76QTC33XtE2uXG+bMRhwU7+px"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.3_1576771471622_0.5025638988898573"},"_hasShrinkwrap":false},"1.8.4-alpha":{"name":"alife-logger","version":"1.8.4-alpha","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"0c9399cc0625cf961b0162b5337e9b41fc4c3277","_id":"alife-logger@1.8.4-alpha","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-GDWMDfUG2hRvOP7wroXgMx1aZqn8KyGAEyGXk9TMsC4CEY2gK0C4n+I0K6gQ0qKbe1MWPmzW0xVSVXYhUiCySw==","shasum":"1a5f25f36225c4bebe996c56a1b4309442066495","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.4-alpha.tgz","fileCount":52,"unpackedSize":480283,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeAC1RCRA9TVsSAnZWagAA2xkP/3UrjyHanVman2+e+7kQ\nweVtrT2twKe3fE6DVQRWjII6mRenE+Z3yGs9Do+eJ1tG2VrpDtpHH/bAGgFg\n2BfcxUq0F9WLLNi7rTWyusy2EAt8glUp2PeT/+HR+eg3UbJMKqBx/n//jzfG\n07cJZIGHmlOmfVwwkUJqgIGK0xg11ZnaXQuEJytUo8syUgqiXAy5xIti8ymH\n1F5zkoA6zMXzMeD8bzb4zVSi7NgQIyX4Z0lmP7UODM+9GQcWoaPsD8r/i0Qi\nZU3LrGJShLLWaKulvGsGD+MhY65RmGNwbVHknjAsLD6MNYHWqIHGvzvOdKPE\nvZDE5p1LnP9lwvJ3YP1jl7NW/YzJpMWDe9PN6miark9LQahim1kAckIQOTKl\nvmYhMDGuPXHZGqsUKJ5kZd1lXnK35RgHTIJDFgRni1c6BhltZwBeufuK0yik\nqH7j6icWvBYc8E/aRc7ayXb7GKT8XsPj7YdandELgG9QTZ1jkt26dAE5v9mv\nir+Zq7tXkHbi413XbNNIzgfgpdamFtoHnyeQCZRknvj3/cwiHCAAw1iyrxA5\nCfz/Nr/7PyuMyAKsHMNsHzCvdWXlEpwZMCy7hqNuB5cG9ZSV+Bv4dz2QEFXd\nLT/pjZAtITW7xXBqNvSsQCWFMpdKyi7j7gCUfcT293f+NLbS6JruGKRtBzcU\nd7Nz\r\n=VfH4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICcCrgy4QGSUfqMcbmHPKauOCs6chwhOTw8SJJZ7QP97AiEAyyCr0gduoiq43LwaEU8ccEYThMXBaiEFjZpxjoiSKdk="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.4-alpha_1577069905194_0.28220160136005057"},"_hasShrinkwrap":false},"1.8.5":{"name":"alife-logger","version":"1.8.5","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"00aa2a6ec97894da0af535c586dee1f58632a962","_id":"alife-logger@1.8.5","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-tTDeNmM1Sm0Lt6MR1SprmfxFrtMhJIsVY2gzKDFDZaS0hyOreGb/uXpuyAWJSR0CmM88266SjPS7QIw5CqPvgg==","shasum":"0582e2b83a6cd1df636fdf0da0584e04d79b7477","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.5.tgz","fileCount":50,"unpackedSize":473832,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeHdwaCRA9TVsSAnZWagAAsA0P/A42ijxHFidzyuBuO0Gx\n6vSJgSohjWu7kRBwEwcKypmVQm9VjpJAhfeVOyLKIHMT9RbzCGl4Vi5qhdqv\nZG8W4MN3mFItctgPCkq/u2pxmbdP9btQsuJrhj5nMeYPGxOkq2oq5p8SyyNL\nV9Us/+1zW1h/kFSkMoXKIAK5wYTqjtALzFQkyf8+Hv48k3jMmVa/o7kttemO\nOm81qlKo0+uC9W8u/p8SRJ8ofxbDceG786ORAoU2FDg1DUTRRjwcntwdp4rq\nwaoIJGUgHpyI12/grp+eqGdVNxgfEUPMo0+AT6LEwksk2SUu8nG2Gw+7xfqG\nXgGtkjHuVleeFx8MwNpHFGdd9zPrf18wTsJecL3Vbr8J9n9dXUL1Rjx9EC2N\nTtiXx18dcHYpzyn/mJZ/xQVULcWesyw2dDj3odeAHzAn0QZOZUh+MERldFCf\nxGUKuJvJaJh+ZepBVt0Lzg+F/OYedB0qZCdn1D7axQ95elxKjSyuwzZc/KPA\nPOlISHfuk3oMQoetKFECLEUfCPtvrTfP4KE2eA4oCMJxJqUcN+N945rzuZ6E\nYZzJYDto0SWhVkQEOH/f1yDamVHhdcXt9ShxIULr0AEXZOAUmcWpW4mgAkzm\nwgdP6D3+6C/Ccz/83uUw5p11boyDsOYWQvO8mqC7am2BFXm3tCM3nf8xCJPL\nqU5h\r\n=Xwfs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD4xJIe8gS+k4TMSnfPeGI0CKVAdXt74V1F3Vo1Km6qyQIgIzhvJqGwUtqHRpdCClSCELFtnlJbMm4UV3LGHAGcy4U="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.5_1579015194478_0.8865631741730282"},"_hasShrinkwrap":false},"1.8.6":{"name":"alife-logger","version":"1.8.6","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"23e7f8f7722d242012e5666229cebaebbf67f50a","_id":"alife-logger@1.8.6","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-rrwKXTSrZMcIOwuwS9qzpePCaJrDOeBwVj0JcLJJ9sVnrkgZY/iYFiH8GzNa+jyi28EsZFSURbeuDUizlCGGLA==","shasum":"717b9dddbb1f5b071f6733d4787ebb1c7a4b13a1","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.6.tgz","fileCount":50,"unpackedSize":445561,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJePC7aCRA9TVsSAnZWagAAY1cP/R+Sgr2T+4N46ehjygNI\n6vxf69FGxU1rAz1EaRf3GPVI+tRuvS6i8X0Nw9DHR6bLgLzSL14Udpb2syLk\nX53kcWBJMm/nPaWDXbfD9CV7+bKSDpGulpFBH68R8eQWFErpO3ezEotJxeIa\n/3OCKEgrLf/hgHziTcbggEZUH9A55O0FFbGyIKLc8HtJGO4yK9LFpPbZcHII\nhwwvX33CNZwC760A9rjJmhXLrm7uQByAN1EhFQa0drApuGdshWl5ocWu4jH7\nzWB6Qc+vv0NWMI476tINAf++U/VVeRQidV7VCsqO1N+/DFM5SYbiIHjP8cAW\nDPI+cNhyvsAbwPCT3h/rEN7Uj9eu7GZX0hm9gcFfJ5tbc7+YS+UdDyXf3i1S\na3yRXhjPUPU2P1BPPYLzDinX+RCVgXj8QiAkVE/Ew56ZZXwzA49v6rVQWhVE\nA/nbp9ClgZ4y9YyTdRj/Om6+8INUsQRddv604qDoG4QcN05aiV06icVbtZ4e\nXSoi0mKGwecFLENn9rpbBVTAVIUlmHT0UYFRAXCyq7kBP8rG2xFsNLpFgxPY\nG6kAeoxY24wc9OsUeAuvKq07dqCGvPCEYVXFTDDo3dGNM5SHedw9ipgcppdv\neiVK/wUbDxhPYj4SnnwHhi2QdW7miCBkm/S9yC7gRSAur/4tbX150LuyFbRZ\nqN88\r\n=zc3d\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDrMaZj6H2TfroLvqDzOr2KcH+G9peRoL0S9+0hIWulSAiAHRAa0SudmZmo17X6wKiswY6mSzewKK2sRqS58KVYYeA=="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.6_1581002458225_0.26293226705748896"},"_hasShrinkwrap":false},"1.8.9":{"name":"alife-logger","version":"1.8.9","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"5af7edfb730e1ccf678be1eb2b85795f882c0051","_id":"alife-logger@1.8.9","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"weichunpeng","email":"holdenwei@qq.com"},"dist":{"integrity":"sha512-yy4Wc3n3av2kkXa+oZWUMLQBxjWkSNmQJIU3KAfjDdq2ge9XfpI5fvelQIg6Dm14Q2U6tt+s7xWlMnkygAFjvA==","shasum":"915192f435dfe32151bf83ce3259fb5d67c2e4dd","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.9.tgz","fileCount":50,"unpackedSize":558916,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeV+V4CRA9TVsSAnZWagAAAgIP/2BxGuSsBcOnm0nR/ixq\nsxjOqgvjYHuWUOilrjt9cEslngs2tC8RcL0V2vA+JamVTPJW3Km70k+ZS+f+\nvdnSshGgrJTztOYWeDgYczPgC4MAL6k9bFlu+UoQyImHP4UdIv0SX/BPugUh\nuFLJiR6taqztMp7dCgyFzVOuALbMmocA1prRTgSKevIrA+rvGBfTk2Mu5ajn\nmoGqPfcHDr3EUfhnhJiTsHSZXqP+5rogmDGJ4UUn4kaJC6wIdCO21U7HOh8U\nQWVQ6aGAnVLYEAAOYmJ0yLfJhrKwcT6UxzRI+b3gBuY9yqsf+23yBmC9RumS\not4z9Mwt/9uISd+AFRPgGbYebaNWxbdr03zuXEfJSXO8qVJx4IdrshsueMvw\nmxGT9IEdclv6jOEs9HcvF1xlwMAs/P0aFkVF35FZnxAje5Ln65UcL3dq988j\nrJyX1d0JL6yLVRZn3hE0pocoH3oRXWYVAakEXm3mJhrjUnALOmV7O1gEHgFI\nZb9Rkqyx3vvf+qxhiHnJ9DQTY8IcdtWDMoicvFHx4PWs2jgqJlgf+DbdO2TB\nU0ygu4qjMznJbzOKsDq8/fyQGFHkVCJ3LZoxObdE5Wq0dG9yYeiQOs+Kgk6P\nn2Wj/DvXValebkMtvcETyZPHrEX64RXTSbboUWTNEl8Ka65M4/pLq4aWW7XB\nKH4w\r\n=v27t\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDEl78+1ry/0Oy6j7xAkyskodA57b+akq3uqTNybbjB6AiBOhXvTAPGo6mjM9arzJ9D0AUgiRBxRyditNCkJ11tCoQ=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.9_1582818679814_0.6077124760775447"},"_hasShrinkwrap":false},"1.8.10":{"name":"alife-logger","version":"1.8.10","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"7028c4a72223fdf3f8b432aaa187722dbf56911b","_id":"alife-logger@1.8.10","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-PCDrzxapCAWQjvhqOPwtjHOok8V+jwEo6eRu1v09x28rLRmuMLRVMkwyExzfidcGLPZQUDc5YEKnCp0lVvopZg==","shasum":"e1dfeabc101787fa65acb411ae75d510ffb0aa36","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.10.tgz","fileCount":52,"unpackedSize":456578,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeb5TMCRA9TVsSAnZWagAAz1oP/2IGC2cOBPzu+Oni2Onu\n3Cy/wxiY/4Pgg1g9YTKnJhtIWnFQPo1eFvog/jW19NCh+yh7WxN7C05Bn2rH\nP9Dlv45ROTq4Gl9f8eAiKr9uvsFCIfcBJRddDGGr0lJ/jBtcEzNdCF3IzJxH\nuWpaGFU58Z7LI9Xd0Kc41MnDzP6OtFK7kM74ux421Syl0uclbyp0PrgU+qEj\neCfNMRKG023z21qJvCggIImDRLU1jlecl3yikfMEdiImoJwKcR3U0cqAGa69\n9CdiIgfoqJqn67aTxqKh079Dem968R2Ay4dPqlwX2dBKIlKdA+LcY4VPvQ9u\nFluWz/WNtyVnGvGdvQCUhhzoXZHLQHeDWvYawWDC4dU3QvY2Uxr94SY7nBqf\ns4MlbN396A1ybJ9f6jmWl7XYng48g8hI/PZVQ50YVi8BXpx4MIA51a3nWBdG\nzi0+cLA7s23WUjqSCH2/7Vdzt2k2KSmDw4wQub+pnGc8BY7NX0P+tehpRrmj\nx4FIu4/+LPARYn3yGr32g9Y0/BWsYqshrQptAylUwQlPWpgJLsWcccwTuOYP\neh9oVrF8jJUa8oJMweXMCgbSY9oGxu73qsUWCA2ZF1arh7wThVkA4zOVfLQc\nu9WHNQZQVblDeWvuglxVWidIsLt4PGk53CitbKquzC9ivC2u+9ZIPe7qF8hG\n5V2D\r\n=N9R0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEtfrc0P7KJohUMxSRILAR+vgnBLya4iwyzrNAdr5COGAiBXP4XKoYa+obS4fy25KWWEPmzdcVzwgRjbO8Dc7VbYfQ=="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.10_1584370891514_0.5850225869814929"},"_hasShrinkwrap":false},"1.8.11":{"name":"alife-logger","version":"1.8.11","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"13e0c870de660b32597715fa1cc0e7495a803c39","_id":"alife-logger@1.8.11","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-s5Da16RyMX4mWX/deptf31Q/cWxCLjBwjxMzPqlxIiIZQJkeuTzKCN4t1offVbsPGrrl5J6kenOhxf2cXJ6LAQ==","shasum":"92d17862380a602f9ab712772df44e99483c4369","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.11.tgz","fileCount":52,"unpackedSize":461175,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJecOkWCRA9TVsSAnZWagAAqnAP/07IkX5FxzFstrDQWPRd\nCrmO4o7OXXp6hEdAPFrNjY7p6m/9DEKy5vII2bKBKlQBfIuVQ9tfHllmGcvJ\ng7m/oLq7ljn9pySDK9uG8Sc+zadvCfHWMHw50LYVDqSiX3wxPZ7/is8hhGFy\ncp4GCTR+wzaZDvrK6YvoitEXJLp4R+RlNFWI8hQBqhXGbmH6OzOTdlTZrIq9\n9SBBXeBfmLhsk95zjcyKdh9FLz806CVmk9B5LVcWDNCp27XR8jlRNedToehK\nlag+nHxq6hwpp1qmu+vzuQoqd6FMe1S6XXkkeZEvMQCYGLK4VhXUnsuhYKR6\nkclV1e4PPE4bLpGuvgXeP85H1gq5eEGNn4e8MFqqyvigUyxrL9d+RbGBpwsz\ngG6+5649IAlouJ5SkYLWTX/iCBMOYJzhtkEaF/gT6VxQUizvgtJQzp8M1hTH\n4CbN/x4o4qH5I3SOVL79J86UjOQhtmAvGxVl1jK1jv18/jVhLhUyemibIAFZ\ne4OUNmdhZCkOYob1h8m7uZZGRzqWBwcHN4/4lPzzMqXYvC7kcIrCH0J4KE4F\ncDbZNIn0jScYONlTXOrperqAqefFRJ5M4AamZHP+llqTArsjvUNX4JFx7ozC\n3HSmFeBSGsSMLCplq39HeuK+WJLMLQejUoKh/fNtiZU/L5EwlVEiQjLZaOkA\nDz5O\r\n=6c3g\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDyDZQxcw+kj8KgCXhjqtXBf0yOzzl9HXWZbZs/diPeBwIgBN83guUVFzAV5mP2Y6VAYVwm9le/+/y4bvXafGGTR/A="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.11_1584458005856_0.4718211436754518"},"_hasShrinkwrap":false},"1.8.12-alpha":{"name":"alife-logger","version":"1.8.12-alpha","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"7c43119d3354c0328c4e5060169d6504ca536891","_id":"alife-logger@1.8.12-alpha","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-xsmiOMGXjJEL2YMaC1U7eJIkRNWVXaY99PQ565pk14ohS2xcFde7EogUNXTTm+Ic9bfAgod1vzIeuJc2ELhImA==","shasum":"f5e95f121c7d64a1e7a6ce569c60eda536560c6b","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.12-alpha.tgz","fileCount":52,"unpackedSize":405651,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJehvkNCRA9TVsSAnZWagAAuFIP/3q6pKHuUKB/4bH0gP6s\nbeWssZHxTGuv0O90YLv55SjdNunga9+HM3lm1//Bx/mAKnqHfJIXDUb+Chw6\nS5dYNmB7dz5KDt2gyboA5o5ci9ZBFRsoScBdpIJpfPothh3tKoSqrkoBH/0D\nxUki+efdlYecPl1xXk3vgKnVkO/mqQFGB4hUWWziTy6A88E2lboi7pm63ICb\nKBWshQvw3qcmYbi3VXt4sDSD/Lq/MCyQa5Ff1nNAjf9S5+vG04KBN/UpDhPS\nM2I6ZpJ2x8c2QBIG+i2CwQVc+lZwAcDvWqDZMzOMrwm2LJvC9dVsM9Mb2WvE\ncK4oN4EQ3GLMVgoXqKZiaGvcV6A92jXxpZ9AUN25fakixIU/+9zDrFWAJfkS\nFIIvUWlu5GjxUtTQKAVNLvMTHFF7Mq/2iEliuNnCqx5Cy550zZ14FJ+LjwlF\nqk3OArXgV2KjfvVd90aQoZm0c4e6bHbBstsvV+b02+2NNLZxQuKg+mL7G4Dy\n/hTpnPUyU0NMvoB+EgREbTuqWHxNCOVAYaSpNxs16P1bVkpZkfixJXj3fUnv\nM1l6dO+dgU+RrTHn8p8KFXi6GJK85vzyV7bR9xSdZzoEahSFGcatHImbQ1D3\nY8YR0iiN+LkxZVfKj0qI5p/SmJvfDniVHAhItMVotHFSV4j0B7bVTlmCayiZ\nPUtl\r\n=5Zw+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGq2iHCym7uXUuCLK2T5djrSoIGB0rmfsB1IVctoRc50AiEAsSpA4oMyIRfNqcTiY2lAJCsjf2GwY+zDC90vfiKUXo8="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.12-alpha_1585903885058_0.026508052358987788"},"_hasShrinkwrap":false},"1.8.13":{"name":"alife-logger","version":"1.8.13","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"c0765300cbfd8ae0680ae2cb85136e5f6d250d34","_id":"alife-logger@1.8.13","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-KcDGL3F9xN+Bx8bcR5NtWZEVhYn6HI+U1UQnKHn+Jfp45gfvDy4OF6OfMw8E7vzCbtZga1ryAXkTwWFAt29ykg==","shasum":"3ea71ab4819cc71d10f1c42aef0320a5b9347c40","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.13.tgz","fileCount":52,"unpackedSize":427846,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJejKcqCRA9TVsSAnZWagAAXisP/Ai0wqDX1hZ+6sel+ukX\n/OeSOpcRwfHLly1ISOzO2IpTDBH9Xn/69Kr2HVQUnd06GwEUE9mHFX3igEQA\ng4L9ixOFzKv9coUiKIPcOFWvl3U8YhoWUZXNXYUmkx5hSpj6vUglOcZqrmCQ\nNlq6BuIRV1hbQoPbd4f4oOsGv0vBZww7EwVszMXA03HHtH1eMISISn7tQPOs\nekRBuIXG5F3aXum4BQWwXAyI7AwahEfiowWJzSwjLdUIw1zMNs30ZOQ7rjby\npKRRgmytpEU8WZfa08pF8ISJgVpUSO/wUKJLT/cPaHliK/k4XcR4TGSVZLQQ\nxGRNFte7FlLQxQEfi3e1Wqps/lXWAlg7JGUOe44ylFAhTduCEgK2SVKlqoQ5\nYG6P57FZ+OOKWGfPmt6RsR7T4nnVTlWBxxrABlKMRc5ZUKii1JitNYvAKISO\n5r7QD78U2EjwmdfZsirs3d0IAFCr6LzsfgkAqADEFOtba+mWpP8OHiT9m80U\nTDXvMFgi64+MNar6Zk4QJFwy+6U6AdAwpCICGmBYp6kkAjsUaA4vIJfJZtOx\n0oey1UGAvZAj8g2KzLB1J9H1bISQtF8aHwoS4murBlCvsI9hLbZig8wl0C1f\nWphVNE8FJayl2YmGYUxnkU6FvbS5XvtZcEpOhWr9kELN+Vkm4KYK3dJVK9jE\nhISt\r\n=w5MX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBYBChSYx/emsLEFidU71imtfA6l5B06xX35mLwtS+YpAiEAxhYvQEbEVQSb7mWtTOrWwg86Y5evnJzKDahesLmPzjM="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.13_1586276138305_0.848069626966929"},"_hasShrinkwrap":false},"1.8.13-alpha":{"name":"alife-logger","version":"1.8.13-alpha","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"6dae54a0d182c50a98dd161974f0fb7dccf2ea15","_id":"alife-logger@1.8.13-alpha","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-LchrzGr5ZrNfwylgJzqzYAfkVnm/deAheZeMuaD0N17ITFZe+xw+rFiltIOXqR/UcYgljGVHX439gjgO5HOj9Q==","shasum":"441025409bdf7a162fce0424ede2aad608bb115a","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.13-alpha.tgz","fileCount":52,"unpackedSize":438860,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJejZriCRA9TVsSAnZWagAACRYP/jbTNyHCItVdf0g+Va22\nyxzR6huLcK55rSc3ls/zRr44trwzhxdIxvpwMaMiUuxizFGWmBkrlRMELHHw\nkLk0QD3iWn/v9YEZnj9r7jYwGqdDKHmpxPB8le2WZn4K4g0xlv8GgzL2ktzy\nqt6vNfeDtNmARWhp8xuXRwHl2jLa0t6+sv1zNyRcUsZ+CAWr8vvdND1zPerc\nIa9zxdVwb0fnKS3XmTr8IZmLYxh0Qf9LBM+ugY0JcQjeaZTuf2gJF9dwcMI3\n95zFLrSblWKNDmPE/9Uk9UKrhSgZwOJn8RMOgJdGb7ED2p/pTAOGml/uUUVK\nJcWR+smlIOqmA8W4Tqu+QCo0NFhYhrYrzf9YV0IyjvPilusHNW6izYvqd+t4\nSQSeSX4x2ivUIzbjsbqFRzfkNbMcrK40M1i2q3CVBGwldKdJAJlZFFJXtaEp\n36BtTFXREnhBx7IoDednRyHRLMpsDdEdXdhwIGTLGWzAvKf+fRTo9ikEjrzQ\nDdu9IP7soe2zvQnpMi6P0hDZvritQep9Nx9LqrnTFDHUqBaJnlZ98Z1FhTs6\nU+ZCkOJsJFtgPaWkydJ9f1/bEyXebFC0N/cul37EnUGyf+GrLAfOODLFzl8c\nwKWXmGrZT7MxTPteuPQuNwAJnTGy8lCtYuuE6CUEWhrLeBIICi4t4wWZu97O\nEn+K\r\n=KpLE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIARWgEUw4BfNbTYj7D3NpDr2EafMaI8X9LS6FqEXUY6cAiEApWygRerBy/es3vmMG7SlYGwTSNswZ4qinNjFdKCbz3U="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.13-alpha_1586338530388_0.6772923266911313"},"_hasShrinkwrap":false},"1.8.14":{"name":"alife-logger","version":"1.8.14","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"52f48a9c6ccc22449e90633c0007c775a802fb74","_id":"alife-logger@1.8.14","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-pEIwB0tJ+hICmE1S3zwB09U6UvltJ/kPKJOTfRBroZV2SFT5etcM3lznme4HdXS10UZjNRtEW0tDgQocMyAwoQ==","shasum":"53dfc438f080b0c53284e7fa622c9b772b983af1","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.14.tgz","fileCount":52,"unpackedSize":439043,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJemF/3CRA9TVsSAnZWagAAOKQP/0e9ALrMqqJeGWvhB4rM\nTYuOlsDrITdqYIisljpUJ41D/I/7YDj1/NP0pScNTIa12FSSeKwvf09tknuo\njKMZCRBr9xQNVdojzTtZmlhOs0WgCoah1JAetXLvGO+8yumuMKXOPB2ANokY\n0syXwrj2BBRHDXcx2Bac6QpX1aiZdtpHByd+NNP83QhQYImN10ZNLy1KzAFw\n+ZFu6DK3cnHHy+mV2mTwK/R90Qq+wsz7+hwHbak4SmjkEk/MFmQ8vHB8I+zt\nCpsgvXfw7VY/liOAFOr/3Qh3bN1FP/qjeMHCbCv6JFsbGmgniIzYdbCWPyoU\nJtbI+ocQffnTbD1QrjZwCH1uS4DNgrmpgejV9oYmJX28P7qVwgD2cXg5v0RQ\n5z6qRg4BgZxCU8QAL3A1KvR/5ud2QqYVTw2q4mNW2z3UZuDvT6nJHk/eXlWT\nwbKEO4MQ8gG1VCLfB8FMkYJd9IiqXJBG+1zTUKL494jYJBApbVHr9lZ+jdCs\nbZaQgh8RTaRKm1O2fcvIMdKZ2mU9ZATBa306GWzjKaIhAFssRfsw9o7Xwlr/\nTPZ0hldSk50ubIjo/pnLQBtX5H1O8yzUZXSCfKSjqxFrQP78R3GWSTCZvzeS\nV6qVqKIOTHaE8hxP7mVvgrI967hDLwHc7EzbX4WxeQkjNkufR6uR/h8gaMol\nL0ih\r\n=TtL/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7xM2Az8HIwaRHoBP/yA99qMKiiNwvdARH3uvs8KrqQQIgccd6gMh/UpcqJ4E6C/tDM9tBrjWqPn3kvmXcsqjsbCU="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.14_1587044343287_0.1785009829630957"},"_hasShrinkwrap":false},"1.8.15":{"name":"alife-logger","version":"1.8.15","description":"retcode cloud sdk","exports":"__bl","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"6470258625cc778f7d1160825e34ca92368fe2ab","_id":"alife-logger@1.8.15","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-RvGOn2vk9EoVRuRla46V9xgY2UkBh5bPrZIdbvSwmEAgYbyOjtuHcPySCASukVtKfZNoTCqliCiYwO6nTCxSbQ==","shasum":"8b528129ecb3331735178ebe727734c1f0dc2d0b","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.15.tgz","fileCount":52,"unpackedSize":472111,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJepvPMCRA9TVsSAnZWagAA+FgP/iOBqb4cpkVQoMPaRxef\nINGWz9XvsHiZUYe2/pDMbQFfby8/6c3Ynq4QuwQAsfH3q6fphp6XrAlGPgvp\nEPhxgl2l/lfXAIJp8O3relu0tK1pruLFm1VsZr7MG9SjJvUtUCBYFYtd90p5\nZlfJQcQc5DCv/L0qVG8N6uDZXWsYlg9uRopeegrYV1N5MQw0LzYuFCm7IxpK\nlZSvdCVNLjDL11jEOiEXCvky0OfBIc/dlkbQ9VAQN8OAJzWVazKRDCcSGPh4\nNuQselP4NxGwuPMAp/2xpzLBAWeIR3xW+dALkU0TygiWdCoPKiyAsRbG/7Af\n6/2NG6UDofID2G+vBKitoXwMW++7NPhtwelCyu5uy0XOphqD+xaJpBvMx7Fc\n1fds7lw+qJUvpS4TaYqMZL3p5oqO6231v4x+FErHE3k070K7iDqOiOrxLllk\nMKM+eYlwG0wedMO9kNw78vTZ0IiwdTpJwZZvzAsKy63taq8aGB3mISmNoNF9\nMty8Kkgc7C5noQO7CIDUxvhFwMo3Do3o/YeCpZTZCOMMG8dVzeDjsETKYBBy\ncGGB5sWZ+T2HI8+z3dUdEE7V7pCm2QKbMamEDR9G04m/YhYg2AzL5wyZndut\nO5JK05XUzsPsWmGqKDZtShl/vDfHJvx3CR+qUWHfOyi+zCYEm1f0n1kbqFB6\nrBJl\r\n=Skwt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE9gJ8i8iHkgrJzEeQmRHwu94CqG48Y5oUXmelMLbakzAiEAolCSmarYzFFc1LnEKepuGt767Gn0W+pcTDebDDCIgK0="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.15_1587999692024_0.5016416391662821"},"_hasShrinkwrap":false},"1.8.16-beta":{"name":"alife-logger","version":"1.8.16-beta","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"75b19e905dc0018d41a56e4c747796a1db657fa5","_id":"alife-logger@1.8.16-beta","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-Z51md83zCKOWyLs7HCdFAHcIgSKJdVhcwluhlQdSFDbEp9Ay785kS5WSGyAOzd72q1VzV2M140TXiYRkXXaFCg==","shasum":"a5caf45dc11bf6f424f82fb8ae66647e5ff58329","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.16-beta.tgz","fileCount":52,"unpackedSize":472159,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevV49CRA9TVsSAnZWagAA+2wP/1QHFlRgvu5koBrtqmty\nYbnKuugYNmnXDqMyXHHxXKOjoQ4eEguzXU2j4w9Sgt5ReYkkWdQHv52QvVxG\nBJdH8pQEag1rX1ZGn2wRS/6gHHMAwIm3VNRJgn7OWNFmbSzMRtpQoB6Z1AaG\nyH+VttUc+hbEOV7mfAClXaCWs1jbW202worpcDRDppzkKvaxbyjEX5R+e5X8\n0vLwW53AmGnCef73H3of7O3BrYhmmBkXwnHi27uQlshrFS1eDuPgP6oex9vX\n7u+QRa1HEb4rex1fAHIL/nRYFfvoajqkiyrKAPqHDz1er0VPF/Z5jPB7gQIe\nUQm6zcmmvakbsrIXubR29sZoL7U+WZYFfBfSo3IUREpgoJXGOcAkdlKjDD6l\nWTb5gFy4lrEb0uqoJnDZElfFvMtsiw3L7xF7rtWpEdIwT2j4tL7FUYCzrDJL\nywB7gQF1qbITtKyHqTfJpU2+zaRxYnAhrhN3sXUQ7FfywO942jznmlWkUWbw\n9obhTyfK8Cxz0IG9eja9XnMleLlhRoqYxcsZl7iysAZq1VvEyLjNI6E1V3T3\n4gpv2P31jvh1t53xP0VOXFesuuflY/4oVqaMbWToSQm2SMvL35Mquwyc85Yu\n25uZej9LYFOoOTMRW6+FL2hkYQTSvkX26ch1JscQriaRRXa/Fj2Aj2g8mZJ7\n2Jlc\r\n=DOYb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwHrprkxtH7mJGDo/I3sCl+UX8qTV7fijYLM1igSXVMAIhALkQWsYbFjqjZ24MPXdxjsWyXyU4ByYeMW/ekRfqNJQ9"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.16-beta_1589468732911_0.8744739789335534"},"_hasShrinkwrap":false},"1.8.16":{"name":"alife-logger","version":"1.8.16","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"c8d871eaad0a4bdf810cbbf695d0c8406b5cbde8","_id":"alife-logger@1.8.16","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-/EgHs1JqqlPxpSeu7pVo6atSzg1NR3P4Mcfgt62UwL8x0P4Pkwt4w9kZwWsww6FA4viMTpZMV//iZLxWnEy0wQ==","shasum":"fadd2d4f6f6f53b8c80bfa80aeba7ab57b1952bc","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.16.tgz","fileCount":52,"unpackedSize":472154,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJexUYgCRA9TVsSAnZWagAAUAsP/RnAbN16q9+BwIpt1uuv\nvFd/mcb3VZsSeOCk5T5TPt8tealfBsG5TFYJsejMiE9J+wPUQQg2IZZwvNFw\nte+g0/mQCNItNlIuPQTV6NqBya3HaA69mEfSKt8z6OBJGFzBQWBR9N6Hrazz\nV5W1MSXI21AX/GF3i0XRnP4RbjBw370oYdUYI+3A7STtk0eYuVThCwmqHNPQ\nkiNnCz9BhhsKmKs9D2jcqpmTU1ZgcavZPqSlov2UqB9fzaHYtGVWiPpjRQkO\n1JGD1cckLl9UuP38XUQUiYseKG/qPfi+6YOVCDi8U08AqbGPBvlNL4Xu41jW\nmnPeRrFo6P3lKKXgQaUpmsk5ENQw0ew55INOYCeEV0y5NEimeYz4NAf5m/cW\nonngLAgQ8sk2GWVC7y3DAcHRItKsYQzC/sBeW899XKgwcni45MHpjx+XAoB2\ndl8iL9f+TPMfddhN619KjNIP0YKdWcliSoD/2wsEf8If4kWX0Xujv+FwluPc\nqz+sYGcO4OT3fuYtoW7PTD+fsSYtO55vkeAJb9MXQCUcRWm8/qC6/NrNTBns\npyYaelveg1xWv4WYdDxoUPAE2lWoCPhuuJSP0I6eYhef/M3Q9UZ3R/kavW3+\nFzirBemuUOStbr7hu+BDdpktlGPRdkMqSzb31ozWcyEk0DRYz7d7fbh5Du7C\nySdD\r\n=k/cM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCS4sXj5kO/uZJgs1ggrOVyyyk9rVUNmijG8kVC3zgZ/gIgeNlR6vsFtPm0v2ctJCLKHFnUbxH5IPoBl6FfHKnQwqI="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.16_1589986848062_0.25142333045189535"},"_hasShrinkwrap":false},"1.8.17-beta":{"name":"alife-logger","version":"1.8.17-beta","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"b5683eeac12935e8fcfe88f2ad520aee15545d86","readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","_id":"alife-logger@1.8.17-beta","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-GAeOA9yxj8yUKktQao2uj0oBtXCZ6pF/ujJYPKU8K58r5yUU84ByKTbuJebUjiy1SqijhQrn5Udv9KQf/K1deA==","shasum":"f757ce2cb4f61aedc69c7cf39e1fadff8de4f29f","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.17-beta.tgz","fileCount":52,"unpackedSize":474215,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe3iqhCRA9TVsSAnZWagAASagP/1YB8vaf+3dQwgTnOY9Y\njdtLqjEvbP2m+YvFw4xQCrSX7GPpgT1Ca46WG9EMQpl83qLeTZnEYTw7gZjr\n6dH8K43DCcKgHTWztzZCOMOhrVq6ASjEQkrEC2HLD6P7qixwoOKNhz4GjZLl\nlbPawZfquTQPbQy5AuP/LBKd3OYxx68x/C8188jZSubHyaZ0N+LfcYp3FC+l\nm0u6Zim0fDkqnXkk6CLolgZiXw2/0OshX14muLoFBpbFBI0G+6VTxIh6mISt\n4QgwVbGKhmveyreY09YhTHpyNb8EQ+6cp7G5VGUd+W0QuEByPTzLOaGDPWbU\nCvMd5KUEEIxBUUH0kMzZhA0IZhGBEW4+NT37gFnhMnph2LCm2kdT/4m+XOC8\n3gfu3aOV0elKYp5h/X87hYA13Ky7uRuI2AZbuxEN+67T63Z61uhg8u3ifsG1\n9X5lw7/RbiTTJxh2MmOMl5q2a/mEXO39DPu4W5T0gBcu+J7YNAFExxC6Ua/b\nAtk0TCzUIjMigbgWaH7Vrb57g2tVPJtVGluMZHAOBUsN6b2PjGuTbn+sfG1i\nSw6LuNKv0Pdp0jKeEA89u6kCDnKvwD/YP/KgrGU//i/+RKeQ/5drqdtmD4bg\nZCc7GJzrVBCTGK5dYYonzEgytHmuq27rv4gWegbWuXq6ZE7O7u64Itt+RWJN\nGAz5\r\n=oWSK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBeEHVBwRbKrxnGWxzxVFK7G0xVUiRwHroChUiay1Z8BAiAt9DPtjXP2gRGbw2ExajlhYgPUc3ssdzOMkhrOXLiiQQ=="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.17-beta_1591618209345_0.8399829265571792"},"_hasShrinkwrap":false},"1.8.17":{"name":"alife-logger","version":"1.8.17","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"e8dd547fffde0fb86692f8986918f89136a44fe4","_id":"alife-logger@1.8.17","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-hIZ9GxzOgNwbP+QihLxrvL8Kg2yRSJWCvmi8DKdreYMVn5K9iAxRukxz9Ia/W2UvC05HzbhJGARr//E+sdBjSg==","shasum":"61577369ebb475f79d8855661c995ebe4473695f","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.17.tgz","fileCount":52,"unpackedSize":474185,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe4lHeCRA9TVsSAnZWagAAAZQQAJx4cF3Br+cw85Gn/HCW\nifOlfw6WNCTc8RjJtINLHgBZYpsp/7GgdnXY+dOQlKn1UCi7CoH1p5H+VyhI\n39qyNSsngtu1wAO51oyfEQMDlpjv/nXt7HRwA3YWouaox1p0D+aqN5W3jIwP\nNOZZmJY0yr/p3ajJ8j6JUQ9jux0PPoGTHftdW0v+dQy8DDofAnxRxpnlnsan\ngR6ilbxMws8DkUmYX3Ay4KwfJ+hcChd+Oteq0J3xj7Cic97B//TAAm1fRjuw\ng4tl0eMdsUyNUnRcZRwAPjwMcs8edOgv0zS+DeVsfVSYwdZ5dYgczsWRXms8\nKxmsfPzKpeAp8Zf8aQ/X6+82yxOIolvx4iEpz9aO6t38XJ7v8lwKiKChihOu\nw3FAkSrB0nxkLkKXniBiDPd8LEUoWS0i5WkWEOR86cLrmh1/GoZ0fR+GXUGM\n38S5UpwMOLx5+zzqMHDEoWXS62lFft9Ccb+IlCiVP+uXbV8KSiP0D73SX9ZK\n0YT7K4JBmeDqG0bgFsyg1l34GdZS9ADVT5PfZzpEHW7syVzNwAQgG4Asac8F\no/EvBDSyN9rLqvWBqHQ7qE9lu47dKRyweMgyO7TLiC1ROQ5ccILyYLd9PXxZ\n6zhSv1vdw/6ameoPXfJjfI+hf/HPhl4vAAm2XqZ3vQ8Na0qetrjpbLBGbdpU\n8ZEe\r\n=DAMB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAmlm21h5PV4totPc+TIGcIBveGyZpmKvHT/TH4LfMQuAiAEsVks/A3blqdzK3rp7kClkSvXBAAtT24G+4y1QSEkTg=="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.17_1591890397737_0.9846769588430995"},"_hasShrinkwrap":false},"1.8.18":{"name":"alife-logger","version":"1.8.18","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"2350819a527507037f692e404f3f058682ae8f55","_id":"alife-logger@1.8.18","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-ZK12uoXEFDGuP0JL27NJiaWG5thNEis1sei8uGEtDfaAi87KKelnBP2F4Sqccs7wwEl2GI5Jj+8g3iL8MIh2YQ==","shasum":"695fa254026a3ee2f89dcda8b25c86cde5240991","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.18.tgz","fileCount":52,"unpackedSize":479265,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfBaytCRA9TVsSAnZWagAAfX4P/3PJwpNz7qDwBGIXplJJ\neJQo1SoPfLPJzNtubH2Q4aMuwUnIE2vsiEDOqJCJrBH6lpZ7Zf1Z/gdLPjJ9\najQpqAZMToem+ARJrF1Bw0cvJkbsOqQ0DLn3tE99SSe6U5lwMMSg/qzBuZrH\nUhY9WtRkohVRQ1ph2342aFge7Ze92yL/Yl6sJKuzT+pj/X8t/hDaT0aossCQ\nMXL9Y+kQT/gXPZrYGu3t+BhangYCWwhxukF7d1x9vjYnpFEe6/Mm4/W9NYUM\nSwzbVrVjwo37xRfkbPyHtfDEBmauismyJvvm1X9yqcqAQ9xzprvUMPR4RL+u\n2oZXJDkK+hLqKRaURw/UAxn8rWMaBdCyw9iNenplei6rGI+l0XOqpZVkohGn\nVkWRtld6Ep8WROwYk3Bl26S4q+KW5Lc3CwnntdQet3d6KY3Svx3FWNddHS5X\nPVTLhHnVglLvOm6djKTAGBcTGu5BnYSYpaDwTqqycGVvYZQvLSfotvbVzcMy\nQd8kvBubXi6MEvd1VeJDRZO+ZulfAd0f8mwG2fKBnwatpKvpFvkdfPe243XJ\nDnfHtVZVp5Xitw5SM3C96KKBM4UidDFmirE44OKpIAq0fh2B9LjAMNN42tLl\n+YS/1Q4U+CkIZi87iPv36XM0HwTSNgwAIcSoQcnUeU9b3xvTD/V/oI3LN+nz\nWMzk\r\n=YWcc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCezFzjItVyIhKLmnbSlhiWiGYi0FenRG3MfCRJLEv99AIhAJQ6c8iMJig/B8OG9LHoBS9URGEpH/GSDJRIZSv+eNN1"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.18_1594207405180_0.4101522978524075"},"_hasShrinkwrap":false},"1.8.20":{"name":"alife-logger","version":"1.8.20","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"email":"orchid.fumeng@gmail.com","name":"fumeng.mufei"},{"email":"funlin2333@163.com","name":"funlin"},{"email":"jawnkuin@gmail.com","name":"josephku"},{"email":"holdenwei@qq.com","name":"weichunpeng"}],"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"],"gitHead":"955d6f8211d700804a8797ef4d9e543da2c5381c","_id":"alife-logger@1.8.20","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-f0V0PMVkfnvBnMC1+7faxs4COaMxRkLcKw0QRfDnx6gvxyvXG/hGV+xrAytfQ/vkQe1WZER5ufm+/qe2uy4XLA==","shasum":"8e0abc2c8c0733ed943ff48d5b29eb17425f6526","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.20.tgz","fileCount":52,"unpackedSize":452445,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfM1HNCRA9TVsSAnZWagAAhyUP/RTHGUSf4zfUBqUaDg0U\nZqvaaq6SSC9yT7dGoxTeVX5M8w9TGlnkYQStRFxlk2V9VM18NlAWdWiMrGHx\n9vHktMTHIntB6AZQdF0ambbr0ALFd2dKi9uLJKDM8EDussiO9sf72FMUmIUh\nB3uhwE2PUccwf6h6En5QxQJ5MHKb6EmBkbwjla7zY+N0MSDt4gUA3+emcLRi\nIKGVlPngMLDiVPZZmbr4ws/qHZnYNaAolTbIEbxhZ4tnmbweCo1f+UUvmPPG\nr8eWVlKw2IQ/LSv4/xyfK8+a+kcbAbsEJ0gcwFRJNMYrlMwRaW4ri5Zp1ZNR\n/65MA2LEzE9X7KRFQdalackxkGa6drcYL53LPgZmV0VJfgtQfs5SkGAJwFAL\nur6miXfAnFIZGdVoCIvUir7uNeSmziCQb7xhconk/nBWGxmNLAoCumYpeVps\n3ZVeiCXDmtOR6QVQ5Xpe/mZgiKlvyro3YXJsfSGcw3Iw/fhgJvAaopceONJg\nknEAuiUVe3iUqhgMOKsdOMnyHq+ko67RBpM6bY0cKRqIRLIyKDSX27qoYCHU\n0XsDku/rlMtFDPHpA8hUB+NB3MmfAs8ZVUlCDBG47uC1iblWW1OxnTBUqCvo\n/FQaH5z4K+DWXStd+ZT8eSfWJlF4CjAZCCo8ZgWjE00jtuiTrFzkQZ7JH9r+\nfP0N\r\n=8+oF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDqsSRoGjMV6M8HuQU/6vveRLgTBuERpTDqForI4+OSvAIgTOhQTfGV98tlJGeJroh+42ebD8mZvixidH/xfmq1vjE="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.20_1597198797276_0.5499552095753768"},"_hasShrinkwrap":false},"1.8.22":{"name":"alife-logger","version":"1.8.22","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"ad2d96d2961b618ae9a778bd61be22c1fcaf2734","_id":"alife-logger@1.8.22","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-Wl3qosknglxa6+6LAgchTwY8tjv9mfyLeE+bCPTI411ghtcxQHdhNMHejqEpiRwXTESqrmi41C3RKONrexLbWg==","shasum":"c1d9adf443ac6f56ba5d64af0775a2d046c1f244","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.22.tgz","fileCount":52,"unpackedSize":480027,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfa3NECRA9TVsSAnZWagAAsMAP/jmjb2Jlojltg37TodMC\nVfCVzgju3cGVmj1GidTSxb3yobQrXabsMHSX6fgg8cOm0DrLwmZ3uSiARTcH\nVKLagYwQjyxeuF2ucTTFysCOszIx+J8uyNprYDeSNX7XX/OswaEjD9IqBoKu\nSopz0lHetyuH1qT9+mLEAVjNcJAYKm3KzJLqfg2ah9Y+BTjJa2oYGf1KWQNU\nYNLciE5NIC2prMDgB0fPA/DOGlN272TxocU4cD81xWgZLhWmow2pwkACOfK3\ntIK60LpnwigV+aSAsGRXSOlAIC78nuSA3A7F+ZSXY2DA8SM8Hpm110Wa9Rh9\n7R7UsuLoRO2QqtqYc36pP2iYA48Rpo19g96t+tPFUT6lkDJSsq4RbDK1/d3m\nHmkW8yBJN5DFKpvH62ygxDh6VfaRTSNiJI0OOhY1P0SJew6ugGT1CPf9Qc/+\nJkzYy28ksOnsK8uf/A6PRFqkUOBGL9NI463M0CRC93nxfm6FWYxddItCBvk/\ncKpfhxfRqFBjAiFd986Kbu34XmjEBIoZpm2t/FfAy1vybma6MtDQHLY5tBq5\nmro9St7kgoa0egFA875X6XbAMklQ8utTWlAUxXEsR8ibeFWPPAMcD+7lXcQw\nzEBzcfTnouBzcH1+on2ZcTDI9+Aur4r5IhaigNK0J+GKGM4No63ccSezAOfW\nOZIo\r\n=OkMH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAuXCu9jTr8/Y8gGn3gIk8mpVYfZZoeUZrGAbZaYczv4AiA7jWsa/GjeC9ouGa0fpTXE3l0HrzNnnIRAEu0yV+UMQQ=="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.22_1600877379415_0.5503834091136202"},"_hasShrinkwrap":false},"1.8.23":{"name":"alife-logger","version":"1.8.23","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"41748eda36528946d3ef22276836ca2129f929d4","_id":"alife-logger@1.8.23","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-irGvoCx3l7QYPsSDIKBQC1hDQSAmJgvLGCWADVzX+KHpz2z0ZaA6NcBdBav5RQQc9FJ5ECXMrJrzedzDkmsklw==","shasum":"53c99b51bbc2b205f12ad0aed6e1600ab2375548","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.23.tgz","fileCount":52,"unpackedSize":453662,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfhEWNCRA9TVsSAnZWagAAcnYP/ipkZvYh2U68sZXo24mB\n9yTa/2GgRYWUiuA06jm9BPsgYtqx2gm4Pt0ra5hoCyfQw+BzholhQzcHkTI7\npmz/iN/98GvjeJe/0YXboqVJnu85ed8Pejz8dEZynHojQu2HrGIm5larj/64\nX4OqTyzIlmSZEQudVEkmOXQGK2XECz4KlKhyAcHHJ2OowCLuNIvfzE6pxHlC\nUHqiALVVzOWwuYrYUqD2ESz7E+SPa5N63IMwu1K2qSqTSmT76VeY6TVRzuY9\ndHeCWlCDt4NqFPobelcLbyZ4uESbtDYhkkd1WBGrXmYn6QYP7pJIMGlR2nen\nWSAuLIFEYlYqwLy8wrvtAirlE3O6rExbDRrdJ74wN3Ny6eppdi6GqvbytO4C\neX4dG0JPYpk9tzt55UXaxxNfym5FyvkeJuAlnO3+OMzFfYzWjRaRLvIqtujH\nGBcgB1y6lWyM4ORDhyapmt39dDcsO/RStYvLx5leeQecwV8GFb1luL9yOZNp\n/SRhaukChqnpsOwoKfNg+xFZBipt/Sss0y6iJ9/1ecCmfCBSyy3hHw0LwJhI\nKKEkOOoNhEdxpihnk9hv98OCypMnL2LQ6x3qUSvZoc0qT+dy8F1Nq1LsMr9s\n+oYsdg36RbfgbMhLaypUmPhmLhRYzuWyjbIjVPD7D+S4ylJK1PucWkEUT149\n5jUi\r\n=IETd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDcA/vzEATrAGIkqOweGWAqHKOppKn7QWgOkdcHbGnUKgIhAP8q2EbSyR3KOgrHor1hxeuX0EjXXZP5YPyqO5FqE1dq"}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.23_1602504076754_0.870278756185553"},"_hasShrinkwrap":false},"1.8.24":{"name":"alife-logger","version":"1.8.24","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"1a63496fdbe1ff0b9a9d10ef3dcb215e7249f71c","_id":"alife-logger@1.8.24","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},"dist":{"integrity":"sha512-v5kj+fpa8iUUT9vsFQ6AJBlKTdkOOhRqF0l3BLxCvaJf184n09F2VVzksQWVYHl/DG4RRU0IoMP8f2JanfE9Rw==","shasum":"6eb2bc1708b1a2120f088a16fd6202bf7677444d","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.24.tgz","fileCount":52,"unpackedSize":412141,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfh0alCRA9TVsSAnZWagAAKPwP/A9adD2gwe/0ukw40zb8\ne9gmwlBwuoHSQTmHMY8wUIzdTdTeWELmeKBlHhdW9JKjxXHDtBFpqkMR4Mxh\nNcC/uQ/6zFEAd4pbrDY96pgkrAFExzuBeq3ZFTjCH7+ULNF9u/MbaTMrNiYY\nR0q5+1AKklTpdG68+8LRz3j9KQ33A/a1dTsx4wMusdmp1o10k6ElSlIYKl8h\nQpYyco3XoDslmc5Y/v1yZMvJEpr2336UNqo5L1BQIFmZlNpTbrxO76AoP6lz\nuiHalndTwTPL8CrynAGLAGjlh4iFi2POUr8jK7CU5B6l+y3C6TRChrevUlJQ\nxiUT7+/X+LQL8nVHF+JNb4LYL9jZRJxUkhami7kWVrEyGKYp9nCsjajDpQp2\nyOuCjp57QLdLvb3s1Zh158fvwZrnPf/BGUHtJfseK29xIKkAZgjtGxpCdV/n\navspaVIM0PrMLBqJQ5oOCOxLTf29occp5S1eMelSRcSruoT2DT2gXDcrtxN/\naq5tTi2mE2IzeTbSgcy6G9aDdQRw0UYwjDali5/qSkqAl/FZMM1oHrJuxi6M\n2jMBhTXfAr/0BmAxlpLAErK5W9WiqRUsWcL3v2nB/PsXVTB+ZnEc7cbocBLV\nWN5vtzpxoTgEApNbOp4XIihohc2yMPAUO87CWTylAmWqZcbB0NpJO4YFfk03\nZcgp\r\n=+q50\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC+px+YL2CdxxE0JzvEeXOtANLMhnsaKOlhDjP9oCU17AiEAtuYSPrs54j8rx5vhadR1AX7OoRg5UrxOcZcs95ZHW0M="}]},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.24_1602700964918_0.6612168922835577"},"_hasShrinkwrap":false},"1.8.25-beta":{"name":"alife-logger","version":"1.8.25-beta","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"c0229121a5a7313a63d141955b2736170aeb211f","readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","_id":"alife-logger@1.8.25-beta","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-5fGvMKhkqCzYMr2X1QO2jYlafAq2MUEyL74F+YQ8/XkKeJvoGKqkE8Q2q36W2k24O0SdqgdopkCnCFYqAnNbLA==","shasum":"ecc1e61a8d7c1c5cd4da05d42fa597e377d2b32d","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.25-beta.tgz","fileCount":52,"unpackedSize":524398,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfuy18CRA9TVsSAnZWagAAz+QP/3mYOr4qXBcIDNYuciCO\n+zXdrZDK4TUtQsIgEw6LdvFsmhTEAPjITeFoc7kYu4CYzEYUQgS2sdE7bqis\niXY0slKod8+Ut2eTFgLmF8d2H1IZwzZgkyDs5yKK+qmFpcHekhWkChAo/x9F\nIo4qS/dh/t9ZRgFj/2keJ6lC0sWeBPnPuXfNpxP6DADfSH2yGSSP9FXSeWh3\nyIr02q0Cz1jec/7rkQ6hgTn7BFlbMZ2i/hjVXLB4G/RPl1f7V2j8gD4wbHpo\n8zadJlHZjBujS18ubnLUp/n7JCFLWbCadsGMEnwAP5uRJuYdY7MLRqNDnM9p\n9rtiTD7C64zOP5qon52Wn63Lzb7kcHVLk3f72abXjjGU6eD0aMLyfmbxTzfp\nQ/ceUrh3ah7cbdtd055I5o4v8uAVTqIJS19LH/UsYD14wyN9fPUeEaMtkyFl\n1Awr5ZKhP8TiWa/cbK1ows2U4EERBkIyLksk2zZ4JVTlXtI5re+Ut11FZ9Jm\na7acibHf3PYNltGvEq1nTP2ZMgqsNAdVDCNNgKrxbCwWZrx1/8aEy1NONqqu\nr+FgMl5a/tUN94URwZE4P18OgHzPUTxh7jDvcWLkD9VSXOsEt4TQ4upSzCMR\nLlPFBlN5K7qye68CAcaKsd29mkc8eXSqek7Xl2Yb38/w6fvRVSt0KGxi0aCR\n6PbQ\r\n=z+q8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG7u7oV0xOr1Au4vTeTTsTXAjpccy7SB6jfCuTN43P6BAiEAtgMJU0nKj0POVZEWyUKvNZMcJ5ygySftTHVKkG2XB4I="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.25-beta_1606102395869_0.5555713768332984"},"_hasShrinkwrap":false},"1.8.25-beta.1":{"name":"alife-logger","version":"1.8.25-beta.1","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"c177fb5acc5666658b1ad7e03b336bb43881ef30","readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","_id":"alife-logger@1.8.25-beta.1","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-ktlgM3pjw84ivcoQIjqHiN7CwLEjNqm/kvR3PS0wiDuyky0qNcBWxd6VPgkn5i7ATI8WxcekLF5Gyc1Iz10GMg==","shasum":"a0d4185297034dcba72bd5a80746d0b7c0e9b5f1","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.25-beta.1.tgz","fileCount":52,"unpackedSize":524441,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfvKF6CRA9TVsSAnZWagAAuEcP+gKDz9Tjcaq7Hjm3+q0m\nQtAHAn9Hr5YzhWXC6u4O1md/12N7DMglLaBki4G8b9C/Z5szUJmUQvcahJv/\nfjd8gB6DUKa/JmBrsFM1gwesBQqzdL6Rirdln7bbODEsRvYuRgRg+5hspnYK\n2jnds2s1yqc+ZNVFUpLyaJtO2B1NSwOOaX9jsB6boVoYFlFR+naLTipEfM6h\nAOTDejiRoIcjgfDtWz6L90FR8lYBVDPdGlU5ipwZ/Uv5C4w4MEKNcY5v/EGK\necw1YhObqmkJFJoKS/99mdw/QeV2xDAuR5nJzUvGhGUjLjRL7mQtUmdzvTpb\nPmD3eGNJk56g+29gBFnZD9X9FgGmkfv/hPmgac+U17RN7kVi3wpF+myAvYWa\nZ6DA1cLMS/vmvx71m7NicVFPTMyXwSZAYJ25kxuSYlfDIg+U4qnfnvft87yX\nfiinHrPPJK+tgUOmD2LS9Mwi21SR7FJaGh4r+ywwj55FX5cIuaI6W2X1cKfJ\nv09ITzniFrteLYPrMx+I7HpTgLRxOEPsCdj3Aom9hK04jvPZtX12vioVQ38t\nsH7Bl9oLRXvGkIGXQIcI63WvSvcFryJ/2r9QmtzUIOlRS3QMpxwtSWm1wNBQ\noN/lFTdygkk035nH3inLyU14n73yskCOPSAO3kQtRDk536Sl7L8ZBPxbtEAh\n9OAy\r\n=y1Y+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH0hvm74kSlh8rsuVYQS9cBJWyvjTJx9u8Mv17K0QTh3AiBQRuck3iD1q0I4rvdXHjIQ0C8p3E27J8dUKkYn75NaZA=="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.25-beta.1_1606197626404_0.7371189853391515"},"_hasShrinkwrap":false},"1.8.25-beta.2":{"name":"alife-logger","version":"1.8.25-beta.2","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"c177fb5acc5666658b1ad7e03b336bb43881ef30","_id":"alife-logger@1.8.25-beta.2","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-Ni/kJsZbDVRCA/d/YqyqYYmRncUfk4+VRUY3FudnTM62pA9wrIfM82lXQmos6tz9gi6uKqCInnZbghCBTZe8XA==","shasum":"095c058d3b63020bea87e54839beeae6bebdfc2c","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.25-beta.2.tgz","fileCount":52,"unpackedSize":524602,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfvMAHCRA9TVsSAnZWagAA6rEP/RbO6dE4TBl6WYCcnQqs\nTCvKADCRJcwrxvCHAKmSGjif/Sl5DgLm9NuaDIR9d5nSTvP2x2nPTvtiQUeh\nqHwEy/z4azyTXle8DTqcc1O9PyVZTa1FPLAvdKC2dEqqLex0BG9NfIthlx4q\ndNvI9KehzxISwo85fkLKUbDS9lViYwxxCb2vcLHOvCIpF1SYPXUhUXn3jAW8\nEjsaB8C754yPQQwjiFJh10+fV795NOTsssvpypYdacZFOCOKeU4MQozLH4FY\nYWd648X5VsNLlimqBBvpY7jrLxYLRYJkBwl9bQ+vfKjVhUGdD4HkJ1AcZey8\nQ19Mr2OWDjvWZRrwoOy3w/ENfcNC1uaRAmF4yMKVA0Z/wLOoZpWtNW++GxuR\n2mTRobgrFOnd8EvHYAWj/cIIIrwNv1nrZZvJusaBouOqaHdJ9IkAPf21m3rh\nd39kwCcGtisaMwJsvgp+ASXQRUHNRIYEgyr9r7nZBX9PH2UMACrk5jRYEW7/\n0qnioAsTq61Y3TqNJmg0QLognyOgHK9feFY/w1oRJKO70bOdxDPnAxcyUZt6\nIwq+Psej6RAaFrCsn9gL7mXp+nZCIlCpatydvaIjN1hBuvLCUhUfgOeH3is+\nMYXqQoHOqlz7VxzgPnrdqkTnl6PBHc+jE44Fyfxs5H2N2g1g2LEa7o24Fj+G\ntZi+\r\n=VRnZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCOzhpj6DuAxp1BgRSZoq9UooL4XP/6cWjZoDCKH1lPQAIhAJIifxUadnqx1ZCD1NHtPH2nX0iFk3DniHIMLlRyMXJp"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.25-beta.2_1606205447306_0.45005156894166465"},"_hasShrinkwrap":false},"1.8.25-beta.3":{"name":"alife-logger","version":"1.8.25-beta.3","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"c177fb5acc5666658b1ad7e03b336bb43881ef30","_id":"alife-logger@1.8.25-beta.3","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-XbR4iFG/Xk0sfVTyo4OpjvswDPsAH1kmZHHgK7/a1n0rS72e/uDm46oiV8rhdrX2w3Vrm8/RVibLbt84hXoCzA==","shasum":"6056673f57c115f76aa23c4c1d1d9a4f5a0979e0","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.25-beta.3.tgz","fileCount":52,"unpackedSize":524863,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfvNkQCRA9TVsSAnZWagAAm38P/2LxTgIzkl4fDXzcpHpQ\n3jABZUBk14UqEzn2MJvGtmYhfHYBLucK7H0eiroZhRl+sev9q1FBwLU/DdC1\n49OXEc5dup0ShK4znWO7JVvglQafjvzUYguGx3GTeZWBKoQH/pof3FpS6nbC\nfolq0s/JVOSuDc/bOh6JZz+tNuLFVUuYURXXkRZ8w/pey4jCVr1UBOFqYeFx\nwdUsWPM/fDjzM5NM+pt3a9KBwK5c2n7o9x8H/Vof41xrfNKxBzQXM91vU9/R\nXvXlWy2UUbqpB52kcu02rwTSjc714yaq0JIOqphrAzPojeU92w+FtRbLrQ9Q\nYBWCNeBl4WmQcZe1CiALgtSTpRSjRGfKhheMB987uptgR/i2P2BoQbi4esrr\nyCenP8R6VL9SGPmabNmD3J9C8YuH4QXUhSScalwan7dsh2GOW5NNrdR1ne+H\nm7JYwHZq6ArQcRIJLLe/ELXjLRoDE/tq3n08WtnvKEaCkcClFZhn5r2vmQHw\n7h7dULwHZG/ls28Zn0TBGyFsj+GA1TdUhyapSQ7EPcbsSNlxfVy1sXenRQyY\nsErLCNLw+mxyN3nD9gJuUg38/+smClkOCfqjAcbnJQu+qsnrPft+CFsnV6C/\nmMzwHWEeJtR8uYlvx/JXmjc9TQYN4S+dHhfUrs2yzMFWZu4tT+rLBBXlieW+\nNpJp\r\n=hszD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLZgp1VTFbpBHhd/cXwg0A9ywdib/xdzGokfx373eVuAIgYVOonlFR4evkumzTqWWmqdM3I8XeS/8hSrSBZqoom0U="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.25-beta.3_1606211855945_0.30654964166191556"},"_hasShrinkwrap":false},"1.8.25":{"name":"alife-logger","version":"1.8.25","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"4d7afb535b5bcf58563ba10d1a13b7f69c4f9515","_id":"alife-logger@1.8.25","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-qYhkBkONPsQIxqVGR7vVrPBszA6Rutofvgo0+jOVBnP/kMn0OOt8McgMxWg/kXHRAMnhLMTetJ3wi+x8d6WeAg==","shasum":"b3793b0cc535e7238c6d6225bd07ed9cfc33bad6","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.25.tgz","fileCount":52,"unpackedSize":525177,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfvyAoCRA9TVsSAnZWagAAU+QP/3nJMoCEPCJXB1EBYu65\nKoF3OepvZCUfAY6n0F93VMuTKNvd7iko/jUYju1j64Dar+sS6pxEHdRaGMGD\nvMHVIfiEedRQj/BoW6Ls7sYaxpXe6NiSb9GmWrir5tRCJMm/UNb902kIol5h\nsYRPph56qCsLRCDo+rGlFMMXu0qiP2GieZclUpT9dY3WJGOIKSKcrTszpGN6\nvfURUh/6mxkSHSnLiXXgWM/RZXm9zuGurq87V/+VNi0a0GQzoxtelFs+i6ri\nupBxRwzn2ZdX4ijT+M/akR+hf6CTmOxX5yGPtz9Lng1nc+HDJIbNkOTgHCG6\n54s2zbTYdYxaRSGYYr0MF1OSmsNVZyvDXtMcx709sam+wpbDppD1KOtfK18E\nc51N/y+yhgt2zHFRi2AAWR1guiXPGvKDuPYfILInBKoCOxFLu062eZkzIJ0N\nIj0srELKR/C3qYuk1/y9VGQ65FcGdflvMR/PsEWhUG51d1y3ZGbNjpcdT/sH\njrgnbAYELU8EjG/kdi7gXZPscKHBwCy5OfLiqvPWLAohxpfAmdWei1SjdU3G\n8fwsofHk8TKSjwUkE52UhSsd0aWQ9pTziHDpqP6xL6ncmj5leWJRHY1qSvUD\nh2Km9iBekyY48Pn1diy79v1e7pRRvIP0RgeOOc0mkIAbW/hs59iP41QVSXaE\n/6h2\r\n=B9Dc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHiBiKtR2giR0Lm1SH4cf1jWetA4doe4WEC3zYitY4DqAiEA3qEA+baqKbDkGIKIRnfRtyihHlNw/+gh3j3DqYRzTmg="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.25_1606361128241_0.5406742155902748"},"_hasShrinkwrap":false},"1.8.26-beta":{"name":"alife-logger","version":"1.8.26-beta","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"c858d094748107c5afd5f458780248caf531c071","_id":"alife-logger@1.8.26-beta","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-C4jvbuk2aSzIn085XHodtvlbmMGOsxFW8sJN+Y/WCOZ6u8Mllxt/yDJSBRfC8G2pIydeH4CDOvu3Mf2JzILD1g==","shasum":"4cfe7a70d57c6e38b86b129cf2714dd8951bfa69","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.26-beta.tgz","fileCount":52,"unpackedSize":525310,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfwGyfCRA9TVsSAnZWagAAId0P/A23tkTiv0pxGhTYsfsA\na5zLfHwyFwMjYfWDTfMuCPHknU3FjCO+Ax0muqrV2K+ohvR56hzw18pa+QYb\nei6bQwTzcrWLAGjz4rNOKuJBhiYdFZaTd/RkTqu0Id2jbGf+DeOPqbeooZ/q\nAltsjcfoj1+7umL6TOPfIwgKuKzhxLlFTTvmbo+mSie+PbgGVfSs6PPl8mkX\n4Pnbj01SrRZd88ruY9l1Y7Eu1rly49TwNBlnfwtYjTzEQTXMqFGto7rL+OSy\ngFZXZybIxzYaH9GI7jszwu0i5d2V3MT06RyqiPb6njHZr8mcKhBV7vOtV16q\norTPMiHS+lU6Jw5jMsXFXB3UvXNEe7pcn5jdyLb4yT6nGqHplm04mXMsEnkr\nOTYy7+aHFbzOxwEGLoTItl2WZg1RWNKM6z3NPqpAoqPhBDrQkIPygohryvhe\n3+JErxHNpzUErx3xrtSByt5vCHdpgn/ytl2O+zQExwtMKO106siE0er03sVj\n2pc1vZOpdFYGC/Eecmca9XezrTvdAY7BaKdAGes+AhJR6HrxczWiStvIwzEP\nAR77FfaFvqptof8o9OPV9zxUsJbwqTuVUJu5Q0yWsysx5/54L/0Mr79x4vpb\nuBJvWNzDxA0Ed+1no6GBjPCSe5H66wN4oaDZwPGMym9H4omRUBYPm1jRfvol\nS0Cf\r\n=zfp2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDbX0jeI0J/ETqByJUJLPvYIQOtuEwPal5pR4OT6DZDAQIgK7R+xU9aBs6PLmmEa2SVzQb7CupocVBeeqPvfbKT4QY="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.26-beta_1606446239128_0.12397580163595157"},"_hasShrinkwrap":false},"1.8.26-beta.1":{"name":"alife-logger","version":"1.8.26-beta.1","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"1b44a2dbe2ec1bd08ee842054975e5fb4eb75d03","_id":"alife-logger@1.8.26-beta.1","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-dnAgM93e7SKQMl4yntBOiYJnlC7/aSUDSnjdRcd+gpBApu2zCwFZrfF4YGYKFQYgtdimy82sL1078zjGU0KNNA==","shasum":"26a0d2e095950487740c503cfac1d847e8456e90","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.26-beta.1.tgz","fileCount":52,"unpackedSize":525325,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfwLl0CRA9TVsSAnZWagAAIGEQAIopo52BXLC4E+eL68E0\nZSYkR8Ul8Ij8nH62j1grOcYBG66K+f/4pL2W9Qt5jcsz3d1b6VJq7Fpjidxk\nIP5KYgMOqzME/My/OZP44rcDlVOzKt+n8J9ACbYr0tMg1LOcbCeEqrfjBDeg\nc3OlEgyOm4m87E6K4gLTTHcABAuoPUjnSg2WEDqibVPoMF1q8ltFvfWcrUCT\nJwfpCqSfcwft/t1gu40QRY2VKk7vOx2QHXHGZA3y3mFqOIa8Mm0r4iIddhH4\nymj/AQAD5myyUIS+K0mZSfzX02MRoSddhgUUkzWnwgFn5Tbr7OJv2jQf4aPf\ngLBBYCuSelv7FFi8PTP+Q29AXSFltf8UUawwqEX5i6ZUsVJFEG1uXdltPam0\n4ebgCbW35E+HKyWlF3tiNVAtftLFPXlg42B9X8oVuFN2XbWIkjuzlc2atsm6\nEGsz8T8shvKuRl03t9WHexo00Bkalb9fCYuHsoUDJc/OkhikrZN7htUcr+0g\nxLUS3xUBVsXUnlIlpBPJq+LFYD7gKHHK/DE1bWjDCnXj5wNF/TrgQ1jlaLLk\nPREOlx3Ck+ZueRyvWiWYoaaBmmtNOxIwrncD8fU/e/UzDG6POjAWi7YjDyaU\n2bHtiwJCdhn/D+czQVxp9/tnyd7sXhyR1ttgR/vK4YDs/9tZX9srS/MHynTX\ncWZI\r\n=7i7W\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIATV9N/P0rz8bKd7NFyjr46AOFn774wahBbhc7TdLrEHAiEA4i6zzmZP7n8tNJh6wvHNLlypAMOE4AeEl/lN3PRy86c="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.26-beta.1_1606465907822_0.4404173625805585"},"_hasShrinkwrap":false},"1.8.26-beta.2":{"name":"alife-logger","version":"1.8.26-beta.2","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"9db87b7b1fa838d9f1b3c1f6771184a982346931","_id":"alife-logger@1.8.26-beta.2","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-gnYGMB9Y7ztc/JbkX3SpFy4rR+JaEVL5smlm/eZDtHSXNei8NJMRVsezJg2vcWYWozv3iKPkLGLlG8CGWXq1Ug==","shasum":"ee0ec680c618a0bd737c0c3ed02b5ffc9cc0fc2a","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.26-beta.2.tgz","fileCount":52,"unpackedSize":525315,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfwMOFCRA9TVsSAnZWagAANbsP/0RGGitHo5LiL/gHCGt/\nwdF/15epEc2FfcZX9lu7TZayGZ0BpRjsafH7RC/e2Lq6XohcQ4Qz6S8eFsp9\nmIeMGWRiiXDow5HLfyaz91yNYGXSE24c3gbp/lzhAQorM4vuyGyUxNYAA4rI\nRoLGWXelSPfyJR6EppjYBxyrFXYAsQGjGQzOs/GvqscPCC2aRDctvLFUZ68k\nm0pT0nLDwaCdizoHLeKbHuSvZWBcqdgwSc/lURIuIpkkBHEmWG4MyoBr34VW\neCZe5F2SwDuh0o3S0q0teiwIlKtqP1Moi4NQC4NlZw9DIYVqiJ3ceSX76nVa\nRsHYYvRF41qSls8lfs7lLaYrlSuaFttb1m8Z99Q3pAFhL0ZhZq9v2K1U29ka\nCDr5X0o7nRZA1qnfnfTR5xQo16LY1JKp2Sd0oYzk9I7poKlQQroTDHd/H2H7\nZZAYu+UAQfhy1vh/ISQaTKd2q5Uusr5cKKIlIisAqNm9QkKo8Xkw+Q+oAfcE\nEzbyMzSr1KzyOqKfYOL8KuMh8IRhGHbOywT5NT9izVEOrPLXqz0BwUG3LPNg\nFl9KmKdQHALkM6WvyOn1mKzuFo9GZHN2TQ9A6bOVa/8aonA7wS+d95xzBj2u\nKCLKG/MJ3R2tf/qby92DMi3DNQhRZoG5LKFuyPxfSe0qo/gNmCrQbIqHq4xt\ngPE9\r\n=QgBN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCUyqo5363VFxapHrtQcunV15I/JGXlmYh9Ng16s8roWwIhANec0TAHH0ryaUXYBJRV8wy0L1hOJk0yUC33gRzeLgew"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.26-beta.2_1606468485023_0.8104210630724447"},"_hasShrinkwrap":false},"1.8.26":{"name":"alife-logger","version":"1.8.26","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"9ddabb70226ed2057ae072971228bc6ec9f34243","_id":"alife-logger@1.8.26","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-2LTh2eewUur5QfJE+RtyzNFcMXHn4jhzmh331Dfs89X8zUjfkfZywgq4GjePRdiuKy94XpuTQvNy8CegVT+1Lw==","shasum":"ad6ba0f20616f88818293cc44682a7ad3359742b","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.26.tgz","fileCount":52,"unpackedSize":525273,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf22Q8CRA9TVsSAnZWagAA7N0P/iE02j/MoYY9wnWJTdv5\nf1dp5kgidCMdUmdYUDZ+sLM7gKvqbNykLkbmWPqsugMeDCiQBNmMM6nmuxP8\nFA7UvHp3tE3Wty0neCBcTZHjR9/fDGtmW99HiuMIC+axKSJjJUw/eZWRB05K\nkkcuDRP+Xu17nf/cZZwE+YolrhDVJWBGHsRfgi/KvPMPnmR4SlAXp4tBGLrA\ny91fVxu+0dApauOMvsRKuVSDA08+iewem8Vrh3YF/mXJRtY80Rpt/EJrt9Uo\nIVq2oa0R9+TVkXVFyLUTO1TViESYEksOjDKW1CEwn9++DPk/VjMaFa/vczZC\nJhv9zP5L/H67t7KzOERjMih3HQSoOXPvqBX2R2amtcv1NuhvkS+97SBeRffM\nTp5SoN7yn2E9tBxbN5/FEifsZOwADvID+GFGOK0iEd2O1czxCqitMjxzi347\n60pFkbrRVjuTB/gqDeloEGegfVB7DE5oegab1Fqlyi/IBmgRhk9IteWXI59B\nDe+ThycRIq3rnxjHrgmZ+8Jq7Qlpw0j8ZCygOl6RMLNPCyZ0C11ZDAewRjDT\ntYJ98mWJZG/cW43DfdFvkSdVa62t8+UpXJFj+8utbEdWAlEul5/f5dszsd5n\nGsFkmnMb0itlARmwh0aRmQfVXH2Xf0LKCxCUk8k1/7+cJEvF8HgJkvJ+vObt\nvWQt\r\n=HU89\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDXbpRwq3+zNmxc+48hP+Q3w9C4MOeZeuCACXsIki/zrwIgV5125tWX54eudIDwikg/DHKzzHCwvKkfWkuZ1DnhvKE="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.26_1608213564147_0.5569668768444711"},"_hasShrinkwrap":false},"1.8.27-beta":{"name":"alife-logger","version":"1.8.27-beta","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"4dbbcd099cb34b04112295b1b3665b8778c076ba","_id":"alife-logger@1.8.27-beta","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-GQHknUnf+oDj9BYEkcfCTqrBqzZ+CSX9PLiVK4lpIliDZbcAu0RJcfmlGBFoVAFjuLpKz0Ji/9+jJwjj7tsdcQ==","shasum":"267fb706f2276af96aea7a6fe8ea089baff86bd8","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.27-beta.tgz","fileCount":52,"unpackedSize":493137,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgF+gpCRA9TVsSAnZWagAAHZgP/RV8UxmQUqsZbw1OfyV3\n8WpbfCXGOB/MHp/egYFupYHV0nnvugyIWH1G2uuTh7H+9p5Qum22qgmTQd/W\nkIzF9rJ6a3IUNLPir6hMqqbwVfDFi2eaYk9iYPvwu2V2i0z8/pCwc8czZjdd\nRuQ5EQ+pA/rjUzBKZINlpA7fbd4MHyU1jiPWKatNIuRpSu3j6+GYd5xLwY6o\n5y5JKaPcY6wsdtVXLXpMIz0nWogqc6jv/sXmM0Yc1S6SyBl16WgO5H/nN0Kv\nnwQbO8M1VgBGKwqP1eMqRvffBrTw9yrWUm/TfZe19XP/wR3bH2IjUmVHPwuE\nZ5npGyjx+k5CTYX86bsSy92fQwbIXZqWmPzBEe9cLe5e52dghPUF5bPNmM1Q\nQeG9C5bCCJ80NqNs0c29lw7AjmLpw6wLDrSlRNMJCB5LAwh6WUnuebTcgPhU\nXZYs+Qo4TzZ2Fx+360twyokNm/5HhVr5VUz6WchBP1mnMD3tpg8aLhDwwrnY\nT5DiQLl043EZwypr1pyNqPi9NlveaJjGXoOXgMH+o2PalRT/phh+mdBiJqOK\nBktwdAuk+j49QJnRKu7b2FTl1LyBNeNbIkex/zK5NQHesQqJlqmT3UBeW682\nndaffdkJ+aGGPV9z0lKZfTc4N9Qr4sQlKoQHgDE2IhYDa1h4eqZUL5t2NAF8\nUCi/\r\n=UK32\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCm53oYU/N+w6FpBbQ411GfhfMzaJnUuOwwdynCqC3dpQIhAJp+25SkL2d+WoR0S96cHp80yUrb0Z5+NHo0U/oa70W5"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.27-beta_1612179497378_0.2582704658021602"},"_hasShrinkwrap":false},"1.8.27":{"name":"alife-logger","version":"1.8.27","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"922b0abc65105b608453a6fe5eda6c26acebccab","_id":"alife-logger@1.8.27","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-ivJ6VL9wIx5JdjysYVwIZ1bXHOTOTN9l6zgq2Cx5rET2iel96RkEqHaUayIEWg+zkTvrLVF+Ly1xNnuts2asOg==","shasum":"66e107e0f339fd3201d316e4b5c256c21a94c4f0","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.27.tgz","fileCount":52,"unpackedSize":453875,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgR4+iCRA9TVsSAnZWagAAWr8P/A4naTSGP6KwIbGt6Vre\nAhv1MSzHfxIbG+qL+EkyYtShxl6LiwUokyAWPww65dIIpEJVsaoW0dXKF5DL\nEY0BTIZYIxIx83ORsQx0HKmfBMPOiKBQu62SNaNAszNwyPXsz/8z6PV8mOX8\nc7CZrgPcC9JF0YoIlLg3bYxOYUHheo8gvkH6iw97egzABNoaQ75T9+mKNPGZ\nS/RYN5WV8CEYVGAGT9r1dmt1AL1DMGg6ag7Xi1ZhqP2xus1q7vaSJDPOf7fi\nSSwBRnKiK/SUiUdn5fE6gIxtGLveSuBIikb3nKTTv5G1PSyVGdMsuRtq2HrK\nYsGEiRibvKYrv1B56orE8DOh4Vwm+GjZszyJojyWXKw4U+FYDW8zGqhu55CC\nx4rF/+yjfqKu7yAC8wm5ydS6X46WLtjmfXt4zHXKtx7Lm+xjaL7GUKR3efHi\nxPk3F9wVt6ECngs2gYW2JD9gJfygXqD7K6J/BZ5MRz9EMJdK5kcgTAGBbFKM\n1ezovB+sf/dHNAsLKeSbdVDfsgeZR4RFCZfizTcUZC+antrcr1PgukQ5DNZu\n9kKdTUpJE51oiQ0NvRO1I6U9Li/XBxzWYqUVAXbCe7h2lnEdDqtQuK6EqGJx\nZZ1V5P9nmy6TQOUZvlTnqPmAOnHbrQDIMjzObrg3dPD1Iw5lFTFKqxvlZPXp\nMjdr\r\n=UJPf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB7EpcRBDqTQsTldRmXWEAdmqkbUm+AFNDRNDz6XMFcHAiBAn5la7gMlPJ6DeQsZ+q2ZtiZORAJj2NZTzUMJzeMdnA=="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.27_1615302561718_0.6575654494572116"},"_hasShrinkwrap":false},"1.8.28":{"name":"alife-logger","version":"1.8.28","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"8b0503de0667fbf2b310fde09a2ddbe87ab2dd7c","_id":"alife-logger@1.8.28","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-KTihLNn7wPF4U6U53r8FESZo4vkLbveAfZKmFzs4+OSnSSshozeT/6L4iQj/V8WeOEQOtSjzeO0J5LIyhqy8zA==","shasum":"d56600e54e69d0b7b994ae98621bba96ab4deddd","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.28.tgz","fileCount":52,"unpackedSize":453910,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgWckgCRA9TVsSAnZWagAAS/cP/AiP6I8OdIzcQ1exITzB\nHB0sjCYgjjqZYUqdSWWHK4Zb4Ld9xuQ4NlnC4aT68PFGx9I/kpm8iOCx8gav\nmITXoZGu7ybAMh2kXa9ThZ6ZPysCEH+aUXJVvpViGiDRw0EUK8MkOQpSdiWl\nM/XBJWc4VCYCJDZdSDuwWM/CupBwiV6NUJ6kUOl2FlgDXq6A6TGxVegUPtKN\nFvD9jrmnnXQlfodMMHMZyNID7Ua7XmYQbfD+x3neK7276rwsf8gPO0jnPmze\nCYA6csVpZR9om0AQ68N9pQlhc39fcN9cgiLJf4+7dObPGiOQmMULEHQrZNpR\nw5MXZpdXc8uupXL8uBX93ReL9zaptaXWQ/Jf1sZ7cNwC9vhu7vPkS7Xg1kbg\nrhwG2H34QwBU5AEpBfSY9pt/vyUVgK2nRvcD5k+FXxq44lvFviEZHNqh8fdH\nSHCJxcBhrAemdLyBGgDt+wmh4qJ3l2gt1nHMMnQdZzNZMv+t/o+WGZgZF2ep\nZdekzew7IRChuij1eRUftKsSInGZLEXNf4OlO+qtyLdWH+sfpZcamjKWe/KX\nS2rKYuZPaTEGq7IHgjhj4FgSnhXTfmflhf3K1+8Ijs9gKZnz01l4SBkSdueH\n/tskjqJG8jLapehX+mGT7XNSj8pyCeIu202n+wGOeCKcnqcmPxYzwy8+gQLE\nHiM5\r\n=6oCO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCF/21t2wWTaGJjDem3ZT8Vaj6UAZ5PR+g+mTftdfB6XQIhAIORfIcEN4KEZVAxpNxHOMMc80G8yEd0PQnM858k0FvV"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.28_1616496927490_0.28321355053596275"},"_hasShrinkwrap":false},"1.8.28-beta":{"name":"alife-logger","version":"1.8.28-beta","description":"retcode cloud sdk","main":".","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","gitHead":"98408bae1fdacc9a7074fb2a2baa5b29c1564fb1","_id":"alife-logger@1.8.28-beta","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-m+oeC3Eso22wtPRw0rso7lEG2npJRqK7nWah4/HnT/c9yARhEqJ9MfRyQn/nhYDwVDXiSv6PhVxtjZRVNUaGgQ==","shasum":"b218793abb36cb1bff7399254408fd2404937bc7","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.28-beta.tgz","fileCount":52,"unpackedSize":454197,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgfO3QCRA9TVsSAnZWagAAeB8QAJc8S5Q8Qv9D99My1PP0\nd1qc6tFdJKqZBV1rP+JGlZnT7EvcS2Wr0CzxYDWhXjMKOQhUROoF0LwCaKNO\nOm76KZA9+V/FOMTgDE8jyH0PmjJkmY2FDoUjGj1uLtSC7YICtd4V5vgpsTqH\nBJveRoTISX6Z9oGCgowMF1eiAsTL6jxALjMjvAlbTNXBMC91qem3BL+lsc3V\nWigd4GzxXac+ri8pgKOHvqd+GISv1XnsHTEODjJFH3svGMyu3FHeEYmF5k7m\nIgWEs8FPt+ijedVAG7NKmn5Un5wJl3JBbS+lk+AnopbLf++GXfC7FA5HXmys\noOMpH3sW+LvxK0mR1PsqPLvtvmlE8l4IqyPrP49kneeipkkQmIMPziW9iDw6\nl+0+A+uZ3/69oF3kpg/CAOKsaXX0a9reycNJyKnj5QwScof4RVYCGS2GMbcH\nZbY4o10bezbqZBieNGVxQzxO7+V9+UimQO7k5DcDlugd35Ah7BRmVUK6Xzm0\nanztbggejFrAfvB9+qNN4EsG/V/hTbOgO/BkwEGmsOd/90BZ14e4mkPz/uSK\nik3p8iWpgcryDBGnfFXLJGLplGzLHGIxYKkrAIshC5YveONeKXWzAk/2HKX5\nTMlEGCiB23vRZ/NJgb1PCi6ywSfFAb0lGMjqkczcuClzT45ruhqMvD14raBa\nNeer\r\n=Jkhv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDVWS7V+kVme/OLv/zusQoHemN5mq0X8/lLUCLHzQi80AIgHrO4Kpf2eWOTrg2DsiDX8OZWLA1FKYFxgMiEHKl3NdU="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.28-beta_1618800079965_0.4489602214351307"},"_hasShrinkwrap":false},"1.8.28-beta.1":{"name":"alife-logger","version":"1.8.28-beta.1","description":"retcode cloud sdk","main":"./lib/index.js","miniprogram":"./lib","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"98408bae1fdacc9a7074fb2a2baa5b29c1564fb1","readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","_id":"alife-logger@1.8.28-beta.1","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-Hd1WLJdCCdglP6eBeadI+Bwm/0vhWHykbUufATK4E1cUOcEFGEAArzVYnoHcEoYnFk36+pd8XVG58a78ggfuCw==","shasum":"e72085b099862356dc54fe46ce65fdfb950ea882","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.28-beta.1.tgz","fileCount":52,"unpackedSize":454240,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgfPGxCRA9TVsSAnZWagAABxgP/1tXbhnGigIgXP2Ypqbk\nLFGZo174VXd/1TkZTMuQp1Hm5yZhgKCMPqYCQZ3NusT+Fe201ZOhry5SAvLV\n+UHiXbrIDLH8p8QZ/huoM00vSPXDDf1IKNXxT0/miW7W+YAl9scFAO1GojJZ\nb4N8bZ0koSnyYI+E1tW7bkp9653ueJZONGZULyo1/h695R+z2QunGBxRaeq8\noNMomDvavMhVZcFjjaoXK8hD9kkjIbXyjBLXNJEomAtUFZflOhBlHHcqV4iY\ncGyvucc+0FEgujgB7/BAVpHhgA4DxwSVLSVDO9epqebtNDnyIf5p4kb82Wsu\nm13zfuDYZNbj5/7JyWzgFbcdcIY2HN39OVRnn5hQrqK4le40kkw+o9jpsrF4\nKcSPoy8cvTUqJtlMXrPaPutPWVmzc4dUHOXfQ3bbzF9yxtb+pVfjctVxyAl+\nIQMCOmB0We50eZamGvgejT8p978VSECWbA/0oP0R11LE6oVMW+Q8E6ZgLS3w\nt7My/y8Irlt5sglF7Vy84o0dyvLFMe8SVY+CP1l7Gt03zB7CBaDhye0q+iSX\nn44pyM0NJHCcFLY2vYvb9nlf2gjb9F/UeR7je8XwCQ/J1f/yEBZvXrMBqLTM\nlVPiuDvYhsfg88Dl7V3/DqBE2F7tRYse4HGl2+T1KgonjhTXuX99ZlU+1cXb\nydZ1\r\n=ptSm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC6IItevHZycHgGGKNxU+rTLJo4C4ID8h+Rd26pJp2ZAgIgI76WZJmFcj7hJk4ocdQ0eom2bWCoWij/4USxC4aFdnw="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.28-beta.1_1618801072992_0.561575857346426"},"_hasShrinkwrap":false},"1.8.28-beta.2":{"name":"alife-logger","version":"1.8.28-beta.2","description":"retcode cloud sdk","main":"./lib/index.js","miniprogram":".","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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"98408bae1fdacc9a7074fb2a2baa5b29c1564fb1","readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","readmeFilename":"README.md","_id":"alife-logger@1.8.28-beta.2","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-rzkREEG1qtX5Wg8Sk8p4G0f7C/KTIqERYmPmvB5RYubz2T04oanUM9ATGr5vjDjJ2Iah8PZo5dsFX72qvOsIAQ==","shasum":"f18140500330deb4196aa285d0b13f5bfc06afe9","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.28-beta.2.tgz","fileCount":52,"unpackedSize":454236,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgfPd/CRA9TVsSAnZWagAAxCsQAJN/xDL30ZxZbSvSp/cf\nUArOIxVLMJbXmhQ/h8tFumKam/4Ixxm5TdfxsJQthgn6xB7IFUsqPAhaqQi5\nFPvNJy5P4UjguDYkaCyhkeFsq/62qHGUhBjW/rLKfaqXz7P/no9+f8CPM5SJ\nMr3zZm8rx8GemmO1Vi0vJvyixmZumB12EKzag4HQuhv8Kw1imswrLAraTgOp\nUvnyYU/1ZhVIC1k63g4fUXivDoya4mk5vfO+cGIgoTieBs0TZ08IYCjZDnFY\nA2Ia5+TQafAs7kp+3lk9Tg6Sz2fVfkuRy152/M9mDRL5pBx7foLcb7qxwcyS\nyDBmUz9mcEt1AwrdTCfSK76N1E0SrlVkeKajoYCelTs79gArsvorglYf0pko\nVsHFDYAinhm82ohoX/jrECYsO2N0UUZu9mVpfnzP2J8OnWOa/B9W06sME2Dt\nwna2OD02W1vHELjYeF0Pv4RazIkspeqCG8v5uYV6BWxwm8+HDLDtq8ff8fLG\n76uZ+0v4p/bOOvAVfJArXfEUMVfuZaOnWGkMNNy68GDTCPqxaKuJmjxcaBvz\nQqPrksk9y2L7EQmserxU7uLako2NOR5LIFKekGRnsmnzCK4Qat7WVOd/CtBb\nlhNBvhQJCXCz2hB8MHx0PBgH2qpKXGICv8mSkccqlreX6nzLdlqeKGQ3zzuB\nAO5b\r\n=cTah\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA4hREYgWJcwuspznxUq6k+Nz+QNYY79D6rTg2Yy3DpdAiBSy3iWceumNL4pWMtNc3zpVF00E2Y/ioJT8txMGQevHQ=="}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.28-beta.2_1618802558771_0.5788304528974895"},"_hasShrinkwrap":false},"1.8.29":{"name":"alife-logger","version":"1.8.29","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"e661c570ae9072e77aeccfb10324a8f14b4fd4b0","_id":"alife-logger@1.8.29","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-iBxwz0+HrNNf4tQggXlg089aUhXupqFlykv2/CdEFddYRsSi0DfK2rjfQ4sSh6eTqrObhBzoLDQlAkHoL6N4iA==","shasum":"20973290dbd205f11ffe495b6aea53cec8d98900","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.29.tgz","fileCount":52,"unpackedSize":411721,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgoh3/CRA9TVsSAnZWagAAYsUP/jxs6v6bSixqqqhm1FGP\nV3qMsHi+IiawIZoePADe2rsCMY5lJkvjbnnr48+JUX4OX65o1jACZiXpAhJA\nYRSanFI9foGdXJc3fi7V1EGJyok0IRvS2L6JgjgGw9/gXRhz5ChtjpkS9Ap8\nsyTNc2c8zd8t/due6OqTQ2+jNIVJJVBDMLv4RMLGFTlSLOX9sR44Ki2p0J1W\nlHUxHGQRWKUtBBk8nSTm6LjfatOPHLeVuAFfxSZ4giysA0s5YIAUwY5Tsb/F\n77n+WyLAVspLOgDGyPCeAiX4yOOxoCzh82OJBJWojBtV4QX/GaYqWVFu3QYN\nDB+DqzEGcU3QwHXzUhZjzj03BAK+Z2xSkgKSQkA4y+xGrGhL+3ZBXQqe+awX\n3B3ncZbqT++fBCht90NS4wnNOaXrmMmSY5TZzYRlLGGIZncQD7H6tMO3BCsV\nb3oz1KPVJGC0QTI5D166KG4XdsCnwBSg84aSUzZaitkhACq7kJBPAFkahxHp\n3RTWZ6iO1jm0Gcf4rPO/rds8NCRqhL1mmBKxRjVpje4l9P00H+V8fL8xucN/\nnyHfwweNcxVJtXqaxHvn3Yj72OllnnlJHDOVBqe6skslylFU6JsVO54X99rI\n4ekqomitAIh8EimPurmEuxFSf3CnFyCXq4BCBIzourpxGauWFHQX5c2lrRQM\ncPQJ\r\n=3pgo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCm2SurE/xRKKAWCsF9CX5nHQfV2XyaZL8rosAwPHUb5gIhAOofqWxbf0jGKDu0I63wzT6T7ROSg84dUA6ygX8GUvfq"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.29_1621237246859_0.11000686451049724"},"_hasShrinkwrap":false},"1.8.30":{"name":"alife-logger","version":"1.8.30","description":"retcode cloud sdk","main":"./lib/index.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":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.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"],"gitHead":"01778a29ea5c27f6efaacbea3ef3e9b640c2fc14","_id":"alife-logger@1.8.30","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-uDJP/D5BMfsBZfV72ZeRZzhLCP267SKoilercjxv34wuXpk65ttOO9STNI49XjOZ5TwZtFm+97r3tE4ONMsI4w==","shasum":"08407fce823311356dd963dce54fef5124fcaf45","tarball":"https://registry.npmjs.org/alife-logger/-/alife-logger-1.8.30.tgz","fileCount":52,"unpackedSize":390428,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgsE2SCRA9TVsSAnZWagAAtroP/Al2P4CSbMMNIAbaflzK\n7AhADICvwaTPP0ihUyLqU+cav/Zro3iWlPUUn0Y8MpzEX9xn4YXgUbZ8dfzZ\nzqy0wD8I4BWMgAA/r1ESUhEcVksDOdTKxKsQC3PlhgX5P+P5vC+skEnYvJgX\ngSVwMvek1TbxNwxvGU56e+AOiQZ1HcBkCvMq0SHzjumM8C6CFzt5gwk3YPtg\nyHvOBcGBdQCRQMljJWyAjzwMKampPAX1kVpWPhAjvDlI+vrTMa8E/TfYQiN4\n8oKLUAXfy1mg3EwZH55cXNAZdPEQoSDcaKLuEbqk7589XWjmUp9Xj1FicjFT\nOgYy1JhHY24WigiVdLKJ6J51nhCY3j0NIdcp7J1stBy0uW+Tm2Pda2mzvBK5\nsIprJAvjjtsvodzMp2CBfOfMpW0KHxAh5lpDgSYwNVZ4acRiFOqiTyV3yILD\nZF2NtehiAPqNipQFnkAO8yXqO3AfR1ZFhdRcevpLSa5wuG/0esap6bdUyHWW\nFCUNsSzqsLr7jrY6yRcUB/MvcJIU+1YRels9fQDwa6/DGDTlTN5KwaWcydyd\nB4eSw+VWAKbNw90MbzZ4yk3RFBoPDe3VjqtZXtpgKV4CG/M35MztgPY6qD26\nGP93cYqPlYcglVHg3q4GMDFVWZ9RlZJaCbbgw77ySrO4VOcKiibfyRuIDBg7\nv0/5\r\n=CFNg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQL+CapGW98Y6T75DM8Zr+70fGLiUzeu0Nt2TpVWcqaQIhAL1Emtr4ktp0Uy6o5s4J8KjQBwFF26YInix1BBo7zEFz"}]},"_npmUser":{"name":"funlin","email":"funlin2333@163.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/alife-logger_1.8.30_1622166929610_0.8007827287673202"},"_hasShrinkwrap":false}},"readme":"# ARMS BROSWER LOGGER\n\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('alife-logger');\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__bo.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('alife-logger');\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","maintainers":[{"name":"weichunpeng","email":"holdenwei@qq.com"},{"name":"josephku","email":"jawnkuin@gmail.com"},{"name":"fumeng.mufei","email":"orchid.fumeng@gmail.com"},{"name":"funlin","email":"funlin2333@163.com"}],"time":{"modified":"2022-04-11T13:24:40.206Z","created":"2018-02-01T08:04:32.413Z","1.1.14":"2018-02-01T08:04:32.413Z","1.2.0":"2018-02-01T08:24:41.825Z","1.2.1":"2018-02-11T09:19:48.325Z","1.2.1-alpha":"2018-02-11T11:13:39.266Z","1.2.1-alpha2":"2018-02-11T11:24:04.155Z","1.2.2":"2018-02-11T11:30:37.716Z","1.2.3":"2018-02-12T05:22:08.410Z","1.2.4":"2018-02-23T10:06:47.764Z","1.2.5-alpha":"2018-03-28T08:24:09.045Z","1.2.5-alpha2":"2018-04-03T01:43:25.317Z","1.2.5":"2018-04-08T03:04:32.036Z","1.2.6":"2018-04-17T02:10:29.256Z","1.2.7":"2018-05-07T12:09:14.248Z","1.2.8":"2018-05-10T06:36:39.065Z","1.2.9-alpha":"2018-05-15T07:40:06.668Z","1.2.9":"2018-05-17T02:42:40.232Z","1.3.0":"2018-05-29T13:21:54.968Z","1.3.1":"2018-05-30T03:38:15.664Z","1.3.2":"2018-07-30T08:32:33.268Z","1.3.4":"2018-08-17T05:31:04.180Z","1.3.5":"2018-08-20T02:23:57.468Z","1.3.6":"2018-09-03T02:33:04.336Z","1.3.7":"2018-09-03T03:03:53.764Z","1.4.0":"2018-09-18T02:16:47.501Z","1.4.1":"2018-09-18T03:47:22.053Z","1.4.2":"2018-09-21T07:58:20.529Z","1.4.3":"2018-10-24T11:47:20.573Z","1.4.4":"2018-12-04T08:00:13.875Z","1.4.5":"2018-12-06T05:31:57.608Z","1.4.6":"2018-12-17T02:22:01.957Z","1.4.7-alpha":"2018-12-19T11:26:38.330Z","1.4.7-alpha.1":"2018-12-24T07:32:17.015Z","1.4.7-alpha.2":"2019-01-07T06:49:33.008Z","1.5.0":"2019-01-24T10:13:30.938Z","1.5.1":"2019-02-27T11:38:49.555Z","1.5.4":"2019-05-05T12:39:06.838Z","1.5.5":"2019-05-26T09:00:32.685Z","1.5.7":"2019-06-21T07:49:03.899Z","1.5.9":"2019-07-02T11:55:26.058Z","1.5.10-alpha":"2019-07-05T06:38:34.624Z","1.5.10":"2019-07-05T10:13:32.014Z","1.5.11":"2019-07-05T10:42:43.328Z","1.6.0":"2019-07-05T12:53:39.739Z","1.6.1":"2019-07-10T06:55:40.151Z","1.6.2":"2019-07-15T09:42:50.046Z","1.6.3":"2019-07-16T04:56:54.830Z","1.6.4":"2019-07-16T05:25:53.300Z","1.6.6":"2019-07-18T10:56:46.641Z","1.6.7":"2019-07-23T14:28:07.092Z","1.6.9-beta":"2019-08-09T11:53:56.041Z","1.7.1":"2019-08-20T07:55:07.599Z","1.7.3-alpha":"2019-09-04T06:13:02.260Z","1.7.2":"2019-09-16T13:30:17.563Z","1.7.4":"2019-09-16T15:05:14.656Z","1.7.5":"2019-09-17T07:46:00.096Z","1.7.6":"2019-09-19T10:50:52.760Z","1.7.7":"2019-09-23T12:04:28.507Z","1.7.8":"2019-10-16T08:38:07.730Z","1.7.9":"2019-10-22T12:24:42.787Z","1.7.10":"2019-11-15T09:40:41.625Z","1.8.0":"2019-11-20T11:24:04.132Z","1.8.1":"2019-11-20T13:57:50.460Z","1.8.3":"2019-12-19T16:04:31.770Z","1.8.4-alpha":"2019-12-23T02:58:25.330Z","1.8.5":"2020-01-14T15:19:54.630Z","1.8.6":"2020-02-06T15:20:58.380Z","1.8.9":"2020-02-27T15:51:20.016Z","1.8.10":"2020-03-16T15:01:31.664Z","1.8.11":"2020-03-17T15:13:25.965Z","1.8.12-alpha":"2020-04-03T08:51:25.216Z","1.8.13":"2020-04-07T16:15:38.443Z","1.8.13-alpha":"2020-04-08T09:35:30.497Z","1.8.14":"2020-04-16T13:39:03.429Z","1.8.15":"2020-04-27T15:01:32.204Z","1.8.16-beta":"2020-05-14T15:05:33.019Z","1.8.16":"2020-05-20T15:00:48.234Z","1.8.17-beta":"2020-06-08T12:10:09.474Z","1.8.17":"2020-06-11T15:46:37.898Z","1.8.18":"2020-07-08T11:23:25.349Z","1.8.20":"2020-08-12T02:19:57.452Z","1.8.22":"2020-09-23T16:09:39.580Z","1.8.23":"2020-10-12T12:01:16.865Z","1.8.24":"2020-10-14T18:42:45.035Z","1.8.25-beta":"2020-11-23T03:33:16.044Z","1.8.25-beta.1":"2020-11-24T06:00:26.530Z","1.8.25-beta.2":"2020-11-24T08:10:47.432Z","1.8.25-beta.3":"2020-11-24T09:57:36.085Z","1.8.25":"2020-11-26T03:25:28.410Z","1.8.26-beta":"2020-11-27T03:03:59.245Z","1.8.26-beta.1":"2020-11-27T08:31:47.960Z","1.8.26-beta.2":"2020-11-27T09:14:45.373Z","1.8.26":"2020-12-17T13:59:24.307Z","1.8.27-beta":"2021-02-01T11:38:17.536Z","1.8.27":"2021-03-09T15:09:21.968Z","1.8.28":"2021-03-23T10:55:27.642Z","1.8.28-beta":"2021-04-19T02:41:20.109Z","1.8.28-beta.1":"2021-04-19T02:57:53.163Z","1.8.28-beta.2":"2021-04-19T03:22:38.930Z","1.8.29":"2021-05-17T07:40:46.964Z","1.8.30":"2021-05-28T01:55:29.769Z"},"author":{"name":"huazhi.chz","email":"huazhi.chz@alibaba-inc.com"},"license":"ISC","readmeFilename":"README.md","users":{"flitrue":true}}