写点什么

前端监控:JS 监控 SDK 手摸手教学 - 原理篇 (已开源)

发布于: 刚刚
前端监控:JS监控SDK手摸手教学-原理篇(已开源)

本文作者:cjinhuo,未经授权禁止转载。

概要

本文的主要目的是介绍一种可扩展性较好的 SDK 架构,让后续业务迭代的代码更清晰明朗。这种架构已经在开源监控 SDK:mitojs实践,有兴趣的小伙伴可以去瞅瞅~


来到正文,本文分成三个部分


  • 背景

  • SDK 的架构与迭代

  • 结尾

背景

传统模式下,前端项目发到正式环境后就变成了一个黑盒子,所有报错信息只能通过用户使用时截图、口头描述发送到开发者,然后开发者来根据用户所描述的场景去模拟这个错误的产生,这效率特低,所以很多开源或收费的前端监控平台就应运而生,比如:



等等一些优秀的监控平台

自研的优势


  1. 可以将公司所有的 SDK 统一成一个,包括但不限于:埋点平台 SDK、性能监控 SDK、录屏 SDK

  2. 可以无缝共享采集到的信息,比如错误信息可以和埋点信息联动,便可拿到更细的用户行为栈,更快的排查线上错误

  3. 可以设计更好的服务端结构,相同服务器的性能,不同的架构可以抗住不同的 QPS

监控平台的组成

SDK 的架构与迭代

前端监控的原理其实就那么几个,比如拦截 http 请求就是重写原生函数:fetch、XMLHttpRequest,监控代码错误:window.onerror,但 SDK 也是一个工程,是需要不断迭代追加功能的,所以良好的架构可以为后期迭代打下不错的地基

monorepo

借鉴了sentryvue-next的代码目录结构,最终也是采用monorepo


它的优势:


  1. 分模块打包、分模块热更新、分包发布(提高开发体验)

  2. 抽离抽象类、工具类到某个包,代码结构清晰(降低耦合性,提高代码可读性)

包与包之间的关系

多包打包与发布

试用了lerna后,发现它的功能太多,我想要的只是一个打包和发布的功能,最终是用 js 脚步编写根据命令行的入参来调用rollupapinpmapi来打包和发布,具体打包脚本

可插拔的插件思路

该思路是从rollup和监控开源库dora中借鉴。


我们需要监控:


  • xhr

  • fetch

  • hashroute

  • historyroute

  • error...等等

传统模式

  1. 重写 xhr

  2. 在重写的过程中拿到想要的数据

  3. 通过发布订阅回传

  4. 在订阅中心中拿到数据,并处理


如果没有规范的约束,每个重写的过程都会变的杂乱无章,回传数据和处理数据可能到处都是。


如果我们借鉴了插件模式后,会变成什么样呢?

插件模式

interface BasePluginType<T extends EventTypes = EventTypes, C extends BaseClientType = BaseClientType> {  // 事件枚举  name: T  // 监控事件,并在该事件中用notify通知订阅中心  monitor: (this: C, notify: (eventName: T, data: any) => void) => void  // 在monitor中触发数据并将数据传入当前函数,拿到数据做数据格式转换  transform?: (this: C, collectedData: any) => any  // 拿到转换后的数据进行breadcrumb、report等等操作  consumer?: (this: C, transformedData: any) => void}
复制代码



这时就会有人说了,如果我的业务比这复杂多了,那这个架构还能撑住吗?是可以的,将上面插件中的 3 个 hooks:monitor、transform、consumer分成更多 hooks,可以是 5 个也可以是 10 个,只要你分的颗粒度足够细,且完全按照这些 hooks 的对应功能来编写代码,不管你的项目代码有多几十万行,你的代码层次结构都是很清晰的

举个🌰:监听 unhandlerejection 的插件

插件实际在代码中的使用

在 Vue3 使用 @mitojs/vue

// main.tsimport { createApp } from 'vue'import App from './App.vue'import { init } from "@mitojs/browser";import { vuePlugin } from "@mitojs/vue";
const app = createApp(App)const MitoInstance = init({ vue: app, dsn: 'https://test.com/yourInterface', maxBreadcrumbs: 100},[vuePlugin])
复制代码


可以去vue3 Demo体验一下 sdk 收集的数据,更多信息可以访问vue3 接入指南

@mitojs/core

上面讲完插件是构成整个SDK的主要链路,现在讲下最基本的一些工具类,来串联这些插件,由于需要支持多个端,每个端需要监听的事件、上报方式、可配置项的是不同的,所以需要抽离多个抽象类,方便扩展。如下是@mitojs/core的整体思维导图


浏览器的整体思维导图

微信小程序的整体思维导图

可迭代性

后续如果有人想pull request node监控其他小程序的监控,只要按照这个插件模式开发,可迭代性便会大大提高

结尾

🤔 小结

该架构的思想可适用于任何 SDK,不同 SDK 中对应插件的个数和作用不同。总而言之,把一个大功能分隔成几个小功能区域,在指定的区域写指定功能的代码,让代码逻辑有规律可循。


下一篇「监控 SDK 手摸手 Teach-实现篇」会讲具体在插件代码的编写,敬请期待~

🧐 开源

github 仓库mitojs,新 SDK 重构后,包的体积更小、代码架构更清晰,耦合性更低,文档:mitojs文档,目前有部分人在用mitojs在做自己的监控平台或者埋点相关业务,如果你感兴趣可以,不妨过来瞅瞅 😘

📞 联系 &内推

字节架构前端大量招人,内推可帮助修改简历和实时查询面试进度,欢迎砸简历到我的邮箱:chenjinhuo@bytedance.com


如果你对字节架构前端、错误监控、埋点感兴趣、也直接联系我的微信:cjinhuo


Have A Good Day!!!

发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2019.12.09 加入

还未添加个人简介

评论

发布
暂无评论
前端监控:JS监控SDK手摸手教学-原理篇(已开源)