Skip to content

Latest commit

 

History

History
161 lines (135 loc) · 15.4 KB

README_SELF.md

File metadata and controls

161 lines (135 loc) · 15.4 KB

web-tracing-next

待处理

  • 用的element-plus框架,好多它都是动态生成的dom,就必须手动上报这一点吧。 - 想办法处理一下,例如tab栏这种的绑定关系的处理

未来方向

会写一套服务端(nest) + 后台查看监控数据平台(vue),有以下几点考量

  • 提供服务端能力(目前只是在采集端发力)
  • 可以在线体验此项目
  • 提供更多示例代码给开发们,再次降低这一套代码在公司的推广难度
  • 作者也想站在业务的角度多思考还能从哪些方面此项目还缺失哪些功能

针对首屏加载的监控做出更多精细化的东西,例如考虑sdk的绝对轻量化

具体计划

  • 2023.8 - 2023.9 完成服务端能力并部署

2023年需要完成的事

  1. 完成服务端能力并部署(docker)
  2. 文档项目移植到服务器并搞个域名
  3. 示例项目移植到服务器以达到在线体验能力
  4. 示例项目支持react17
  5. 评估支持uniapp或者原生小程序的改动

版本迭代

一期(sdk已有能力)

  • 简单支持 vue2 + vue3
  • 自动采集 + 暴露api给用户手动采集上报
  • 采集功能:【用户事件采集、页面跳转采集、请求采集、错误采集、资源加载采集】
  • 采集上传方法:只提供 sendBeacon(内部自动降级为image)

二期已完成功能

  • 整体代码结构更改
  • 文档系统与sdk核心代码融合 (vuepress -> vitepress) 但还未编写文档
  • 所有模块已ts化,下一步添加新功能
  • 解决目前 issues
  • 支持暴露更多变量(例如最大缓存数、延迟上传时间)(dom埋点名称 先不计划自定义,个人认为没多少业务需要)
  • sdk内部的img发送请求不会记录
  • sdk内部的console.error不会记录
  • 支持hook以及自定义hook -【1.放入消息队列的钩子 2.发送时的钩子 3.发送之后的钩子】(1,2返回false会取消放入以及取消发送) (这些钩子目前没有做成动态的,只支持在初始化时挂上去,等做了 exportMethods 后再做)
  • ignoreErrors
  • ignoreErrors 入参格式进行校验,只能是 (string|number|reg)[]
  • ignoreRequest
  • ignoreRequest 入参格式进行校验,只能是 (string|number|reg)[]
  • 支持更多上传方式(此功能放入 beforeSendData 钩子,当返回false则sdk内部不发送请求)
  • 支持抽样发送(tracesSampleRate全局抽样,具体到模块的抽样可以用beforePushEventList来阻止)
  • 支持延迟加载sdk(可后期再init初始化)
  • 防止重复init sdk
  • 设置断网情况下不采集任何元素(个人认为断网了不需要再去采集用户的操作了,除非是特别需要,所以加入此限制)
  • 错误过多自动转区间事件,也就是去重(完成,后续再测一下关闭网页是否会及时发送就ok,如果是批量错误会延长20s再发送,如果是普通单个错误会延长2s发送,如果是无限错误每隔50个会发送一次)
  • 支持暴露更多sdk内部方法(例如使用者想要拿到此时的硬件数据,用户更改入参的方法,一些钩子也要加到这里,例如上传之前的的钩子,然后组成一个数组,为什么这里需要是因为用户想要在每个页面细致化控制是否上传,例如只想在用户打开某个页面才开始采集,不是这个页面则结束采集)- 钩子内不能有异步拦截
  • 关于用户信息的重构 - 【1.分为未登录与已登录的场景,登录后进行绑定,机器与用户id进行多对多绑定(更多方案还在确定中) 2.支持动态修改用户信息】- 使用 fingerprintjs 去实现设备id
  • 获取公网ip - 放在了base信息中
  • 支持区域曝光度采集 - 采用 IntersectionObserver 来实现的,当不兼容时此功能无效(后面会平替为 scroll 来实现,看有木有需求) - 考虑到需要曝光的元素可能在任意页面,所以sdk索性只提供暴露方法供使用者在运行中再去手动调用,目前内部在切换页面时会自动销毁当前页面监听 - 目前需要手动清除监听,后面有需要再根据路由跳转自动清除 - 目前收集契机是必须进入+出去才收集,暂不考虑停留页面直接退出的场景
  • 支持数据临时存储本地的形式减少服务端压力(会设定存储的阈值大小,最大5M,先不支持跨域存储,否则内容太大上传慢或者不兼容导致此功能不稳定) - 需要用户手动发送 - navigator.sendBeacon 发送大小在 2M-4M,如果觉得不稳妥可以 beforeSendData 拦截自己发送
  • 错误录屏 - 完成数据采集,但结果需要配合demo案例看
  • 对入参和出参的ts再次统一化 - eventInfo列表中取消 type 字段
  • 针对资源的异步加载监控,sdk不做是否加载成功判断,但会暴露 responseEnd 和 responseStart,一般失败的资源加载通过这俩个字段能发现端倪 - 只针对支持 PerformanceObserver 的场景下,不支持 PerformanceObserver 会用 MutationObserver 兼容,不同的是 MutationObserver 能判断请求资源是否报错,如果报错则提供 responseStatus: 'error' 字段 (注意:通过标签加载资源如果报错除了资源本身会有错误,错误模块也会暴露一个错误信息,但如果是通过XMR请求则不会额外暴露错误信息)
  • 批量错误时应该隔一段时间就发一次,不能一直在b栈等用户关闭网页才发 - 统一完善了下
  • 将所有 options 变为响应式 - 也就是所有用到了 options 参数时,当动态去改它能实时更新(可能要将所有的变量都变为响应式了) - 也就是支持用户全局动态去改 options - 采用 proxy,如果不兼容则此功能无效
  • performance模块的src url应该改名 (requestUrl triggerPageUrl) - 改文档的时候注意
  • http模块 src 改名为 requestUrl - 改文档的时候注意
  • err模块 url 改名为 triggerPageUrl - 改文档的时候注意
  • event模块 url 改名为 triggerPageUrl - 改文档的时候注意
  • event-dwell模块 url 改名为 triggerPageUrl - 改文档的时候注意
  • pv模块 url 改名为 triggerPageUrl - 改文档的时候注意
  • sdk内部所有主动方法都改为只传 options 一个参数,但所有的属性优先级是低于内部定义的
  • sdk内部发送方式增加至三种,sendbeacon、xml、img,优先 sendBeacon,其次img,最后为xml(因为增加了错误录屏导致数据量较大,xml不限制请求大小)但xml可能会有跨域问题,使用者应该注意这一问题,且sdk内部会将配置的dsn地址加入请求拦截名单(sendBeacon 有64kb限制 img 有2kb限制)
  • beforePushEventList 中的data参数设置为数组
  • 兼容 vue2、vue3(错误处理机制已兼容去重)(react以及小程序优先级靠后一些)(vue3的demo项目的err模块会报警告,分别是:rrweb-player初始加载警告、执行 codeError 方法会报警告;均不影响正常调试)
  • 实现参数动态更改,目前所有的都可更改,没加限制,所以得提醒注意改的场景不要啥都改
  • error 检测那边,应该再加一个属性标识错误类型,例如 console.error 还是 Error 或者 reject - 完成

二期重构 - 技术层面关键点

  1. options参数集中管理 - 完成
  2. 事件注册以及事件改写集中管理,其他模块需要的则会去模块存放/获取 - 完成
  3. 后面可以用 proxy 来自动化一些东西 - 完成
  4. 数据结构不够直观,再优化下 - 完成

二期未完成功能

  • 首次首屏数据更精确化 - 这个放在最后研究插件化的时候再搞上去
  • 后面可以考虑把错误录屏单独拎出来,毕竟数据量太大,使得数据传输方式不可控(目前是 img -> sendBeason -> xhr)
  • demo官网示例更简单化且提供在线编写能力
  • 可以用浏览器插件的方式去快速加载demo,无需down项目下来本地运行
  • sourcemap 错误跟踪 - 做好服务端再来做这个
  • 管理端查看功能:能不能做到用户在管理平台上能看到除表格分析外,在页面截图上能标出点击量这些信息,比如在a页面点了b按钮多少次

二期暂不考虑功能

  • 支持对特定dom监控事件(例如监控页面button按钮的点击事件,这在大批量埋点场景中比较需要,另提供一些属性来标识特定按钮无需采集)(这个先不做,可以自己过滤)
  • 支持加密传输(加密方式待确定)(这个给用户来做,毕竟钩子已经暴露了)
  • 支持断网续联后发送(这个涉及到数据本地存储,得考虑容量大小,且断网状态下的用户操作是无意义的,暂不考虑做)
  • 支持静默,思考除了错误的场景下什么情况需要静默(如果是想在规定时间内上传,完全可以通过钩子来实现)
  • sendTime err事件 第一个挂载不上(没有复现了,最后再看看是否正常)
  • 支持区间打点,区间采集(记录开始和结束,筛选统计开始和结束之间的事件行为,统计到一个分组中) - 个人认为可以通过钩子来解决,所以暂不处理
  • 探索:一些关键性的api能让使用者去替代更改、比如监听网络状态的内部实现支持使用者去重写 - 不需要
  • 探索:插件化(核心功能+其他插件的形式)- 有利弊,后面需要再去实现
  • 白屏检测 - 需要传入临界点时间,例如在进入页面加载完成后超过这个临界点时间还是白屏则计入白屏事件 - 能不能在load后采集一组数据的色值,随后轮训去看看是否一致(这个得有一定的松紧值来限定,得考虑骨架屏gif的情况),毕竟白屏没准也是黑屏 - 蛮复杂,后面多调研一下
  • 不做全埋点,会被滥用
  • 页面埋点的前缀不可配置
  • 例如只想在用户打开某个页面才开始采集,不是这个页面则结束采集 - 这个通过目前的api能达成
  • 为 vue3 提供一系列个性化hooks - 目前已有api不太需要
  • 此场景怎么做:用户一直点一个带了埋点的按钮,怎么去重呢,简单的节流去重?- 通过目前已有的拦截去做
  • 考虑一些枚举也给用户可以改 - 复杂且效益不高
  • 用户行为应该给个id,要不然后台不好快速找特定事件,点击按钮可以自己给id,但是切换事件或者曝光就拿不到id了,得找个办法去定义 - 不做,这个可以额外自己给id

关于 sendBeacon 的问题

  • 不同浏览器对于发送数据大小的限制不同,一般来说在 2KB-64KB 左右
  • 一些浏览器可能会对其发送频率进行限制,例如 Chrome 在一段时间内只允许发送一次 sendBeacon 请求
  • sendBeacon 方法的返回值,它表示该浏览器是否成功地将数据交给网络传输层处理。由于 sendBeacon 通常用于发送数据,不需要获取响应,因此它的返回值通常是布尔型的。如果返回 true,表示数据已经被传输成功,否则表示数据传输失败
  • 返回值的成功与否只是表明是否成功交给了浏览器的网络层处理,真正的成功与否还需要根据服务器端的响应情况来判断

DNS传递信息

这个软件可以将用户信息,通过网页的 DNS 请求传回服务器。注意,不是 HTTP 请求,而是使用查询域名的 DNS 请求夹带额外信息。这种监视用户的方法,很难发现,也很难阻止。 https://github.com/veggiedefender/browsertunnel (它通过滥用 dns-prefetch 来实现这一点,该功能旨在通过在后台对指定域进行DNS查找来减少网站的感知延迟。DNS 流量不会出现在浏览器的调试工具中,不会被页面的内容安全策略 (CSP) 阻止,并且通常不会受到公司防火墙或代理的检查,使其成为在受限情况下走私数据的理想媒介)

sourcemap

https://mp.weixin.qq.com/s/n1_nq7_DagAmdznt5aTvBg

唯一用户 - 设备指纹

有三个概念:浏览器指纹、设备指纹、行为人指纹。 最终肯定是想达到行为人指纹,但这中间需要算法支持,所以目前尽量支持设备指纹。

sdk内部所标识的唯一用户是设备指纹串(以下简称a串),与其说是唯一用户不如说是唯一机器,所以无法得知 a串代表一个用户还是一群用户(一个设备可能有多个用户使用),所以a串与用户真实id是多对多的关系。

a串是sdk被调用时就会自动解析得出,此外如果想更大限度的使用此功能,最好在用户登录后手动将用户id传入sdk, sdk内部会将a串与用户id绑定,后续在统计数据时能明显观测出某个机器被哪些用户使用,也能观测出某个用户在哪些 机器上登录了,进而可分析出用户常用设备或者分析哪些设备为公共设备,然后就可推测出用户习惯(例如经常在什么时候登录系统)和机器类型,最终达到不同用户不同设备推送不同信息、广告(只是其中一个用途,还有很多方向,例如再结合sdk暴露的公网ip可跟踪用户轨迹,根据使用习惯可杀熟,判断是否被盗号,极端点就是知道你去了A城市用了某个‘公共设备’并且知道你用了多久,分析一下后续会给你推附近网吧这种)

不能用浏览器指纹,这样就硬是把一台设备分为了多个用户,而且浏览器也会升级频繁

  1. 内部生成唯一值存储在localstorage 有以下弊端
  • 多个浏览器就相当于多个机器了,不过这个影响很小,一方面是用户只会偏向于某个浏览器,二方面是可在用户在A、B登录后将B浏览器上的唯一值改为a就行
  • 用户手动清除 localstorage 会重新生成,不过也可以降低影响,不过也需要用户登录,用户登录后重新将用户历史登录设备的唯一值填入 localstorage(默认填充最常登录的唯一值)
  • 用户可以手动清除浏览器缓存。。。。
  • 网吧,教室这种一键恢复的电脑无法检测
  1. canvas 指纹 有以下弊端
  • 多个浏览器多个机器
  • 虽然用户无法清除,但重复概率会很大,特别是同一批量机器的自带浏览器,基于这一点所以暂不考虑 canvas指纹
  1. fingerPrint.js 有以下弊端
  • 多个浏览器多个机器
  • 准确率相对于 canvans 高,但是涉及因素多,设备系统更新 or 浏览器版本更新 or 浏览器关键插件 发生变化都会导致id更改,而这些都是更新较为频繁的
  • 还是会有重复,特别是同种机器同种浏览器,目前网上的测试结果为百万级数据会有大批量重复
  • 但是可以作为辅助,如果用户清除了cookie的情况下,还可以通过fingerPrint.js跟踪到该用户重新set cookie

目前偏向用 1 方案,fingerPrint 作为辅助,1 方案补充 cookie 和 localstorage 相互替换防止删除(如果是安全管家或者删除文件这种删除就没办法了),真删除后利用 fingerPrint 的唯一值向后端查出其代表的本身唯一值(如果此时查出fingerPrint的唯一值对应多个本身唯一值那建议采用最常用的那个唯一值把),然后塞到 localstorage 内

但就目前而言,sdk内部不想主动与服务端发生交互,所以直接纯用 3 方案,也不用存 localstorage

mac查看本机公网IP: curl ipinfo.io/json
mac查看本机局域网网IP: ifconfig