4、自建前端监控系统

最后更新于:2022-04-02 06:10:09

  这套前端监控系统用到的技术栈是:React+MongoDB+Node.js+Koa2。将性能和错误量化,解决业务和开发都不知道,只有用户知道的问题,提升业务稳定性。   因为自己平时喜欢吃菠萝,所以就取名叫[菠萝系统](https://github.com/pwstrick/pineapple)。其实在很早以前就有这个想法,当时已经实现了[前端的参数搜集](https://github.com/pwstrick/Primus),只是后台迟迟没有动手,也就拖着。 * 目前完成的还只是个雏形,仅仅是搜集了错误和相关的性能参数。 * 后台样式采用了封装过的matrix。 * 分析功能还很薄弱,只是做了简单的演示,并且各种基础功能还有待完善。 * 后面打算强化数据分析,并且还要实现错误的回放机制,思路的话以前也调研过,参考之前的[一篇文章](https://www.cnblogs.com/strick/p/12206766.html)。   现在的这个系统还只能算是个玩具,后期还需要雕琢雕琢。下面是这套系统的目录结构。 ~~~ ├── pingapple --------------------------------- 菠萝监控系统 │ ├── client -------------------------------- 系统的前端部分 │ ├── sdk ----------------------------------- 信息搜集代码库 │ ├── server -------------------------------- 系统的后端部分 ~~~ ## 一、SDK **1)primus.js**   在之前的《[前端页面性能参数搜集](https://www.cnblogs.com/strick/p/5750022.html)》一文中,详细记载了各类性能指标的计算规则,并整理到了[primus.js](https://github.com/pwstrick/Primus/blob/master/js/primus.js)中。   本次将在primus.js的基础上做适当的修改,包括删除代理、测速、资源信息等功能,改变部分性能指标的计算规则,例如从浏览器发起HTTP请求算起,忽略浏览器重定向的时间等。 **2)错误处理**   完善错误处理,将错误分成三类:runtime、load和Promise。在window的error事件中,处理前两种错误。像img元素载入的图片地址不存在,就会执行formatLoadError()函数;像变量未定义,就会执行formatRuntimerError()函数。 ~~~ window.addEventListener("error", function (event) { var errorTarget = event.target; // 过滤 target 为 window 的异常 if ( errorTarget !== window && errorTarget.nodeName && LOAD_ERROR_TYPE[errorTarget.nodeName.toUpperCase()] ) { handleError(formatLoadError(errorTarget)); } else { handleError( formatRuntimerError( event.message, event.filename, event.lineno, event.colno, event.error ) ); } }, true ); ~~~   将window绑定[unhandledrejection](https://developer.mozilla.org/zh-CN/docs/Web/Events/unhandledrejection)事件后,就会在Promise被拒绝且没有reject的回调函数时触发。 ~~~ window.addEventListener( "unhandledrejection", function (event) { // console.log('Unhandled Rejection at:', event.promise, 'reason:', event.reason); handleError({ type: ERROR_PROMISE, desc: event.reason, stack: "no stack" }); }, true ); ~~~ **3)初始化**   由于要计算白屏时间,DOM时间等,所以位置不能随便放,得要放在head的最后面。 ~~~html ~~~ ## 二、服务端 **1)Koa**   [Koa](https://koa.bootcss.com/)是由Express原班人马打造的Web轻量框架,通过组合各种中间件来避免繁琐的回调函数嵌套,当前使用的版本是V2。 ~~~ npm install --save koa ~~~   使用的Koa脚手架:koa-generator,创建项目的结构,并且在此基础上做了调整(目录如下所示)。暂时还不会用到静态资源和视图层。 ~~~ npm install -g koa-generator ~~~ ~~~ ├── server --------------------------------- 服务端 │ ├── bin -------------------------------- 命令 │ ├── config ----------------------------- 配置目录 │ ├── controllers ------------------------ MVC中的逻辑层 │ ├── db --------------------------------- MVC中的数据层 │ ├── public ----------------------------- 静态资源 │ ├── routes ----------------------------- 路由 │ ├── utils ------------------------------ 工具库 │ ├── views ------------------------------ MVC中的视图层 │ ├── app.js ----------------------------- 入口文件 ~~~   为了区分开发环境和生产环境,通过cross-env统一不同系统设置环境变量的方式。 ~~~ npm install --save cross-env ~~~   package.json中的命令如下,添加了环境配置。 ~~~ "scripts": { "start": "node bin/www", "dev": "cross-env NODE_ENV=development ./node_modules/.bin/nodemon bin/www", "prd": "cross-env NODE_ENV=production pm2 start bin/www" } ~~~   prd按字面意思应该是生产环境的命令,其中使用了pm2,默认没有安装。还没部署过Node.js,还不清楚里面有多少坑。 ~~~ npm install --save pm2 ~~~ **2)MongoDB**   MongoDB是一个开源的非关系型数据库(图1是[下载界面](https://www.mongodb.com/download-center/community)),既没有表、行等概念,也没有固定的模式和结构,所有的数据以文档(一个对象)的形式存储。但其使用方式和关系型数据库相似,并且还支持对数据建立索引,适用于高并发读写、海量数据存储和实时分析等。 :-: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/06/c5/06c5fa9b2651ab01154b2b5e978d7d49_1487x446.png =600x) 图1   注意,在安装时默认会下载[MongoDB Compress](https://www.mongodb.com/download-center/compass)(一个可视化的MongoDB工具),默认下载会非常慢,建议自行下载,该工具的界面还是蛮清爽的,如图2所示。 :-: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/00/6c/006cc776c4f374808aa37d855244cba9_1365x870.png =600x) 图2   在Mac上配置MongoDB比较麻烦,不像Windows那样一件安装,需要一些步骤,废了点力气才装好,下面是执行的命令。 ~~~ sudo mongod --dbpath=/Users/pw/data ~~~ **3)Mongoose**   [Mongoose](https://mongoosejs.com/)是MongoDB的一个ORM(Object-Document Mapper,对象文档映射)工具,可在Node.js环境中执行,封装了MongoDB操作文档的[常用方法](https://mongoosedoc.top/docs/index.html),包括引入数据库连接(connect),定义模型(model),声明文档结构(scheme),实例化模型等操作数据库的方法。 ~~~ npm install --save mongoose ~~~   借鉴了以前PHP数据分层的思想,单独分离出数据库的连接,并抽象通用的Model层(如下所示)。 ~~~ const mongoose = require("./db"); class Mongodb { constructor(name, schema) { //声明结构 const mySchema = new mongoose.Schema(schema, { typeKey: "$type" }); this.model = mongoose.model(name, mySchema); } //保存 save(obj) { obj.created = Date.now(); //日期 const doc = new this.model(obj); return new Promise((resolve, reject) => { doc.save((err, row) => { if (err) { reject(err); return; } resolve(row); }); }); } } module.exports = { model: Mongodb, mongoose }; ~~~ **4)路由**   由于发送的地址是一张gif图片,因此在处理路由时,返回本地的一张gif图,如下所示,图像地址得是绝对路径,否则无法读取。 ~~~ router.get('/pa.gif', async (ctx, next) => { const ctr = new indexController(); ctr.collect(ctx); const url = path.resolve(__dirname, "../public/images/blank.gif"); ctx.body = fs.readFileSync(url); //空白gif图 }); ~~~ **5)代理分析**   在接收参数的时候分析代理所带的信息,例如浏览器、操作系统、设备等。使用的是一个第三方库:[UAParser.js](http://faisalman.github.io/ua-parser-js/),四年前就关注过,当时GitHub上只有1K多个关注量,现在已经翻了4倍。 ~~~ npm install --save ua-parser-js ~~~ **6)假数据**   制作一套合适的假数据,新增命令“npm run data”,初始化数据,便于展示。 ## 三、后台 **1)UI**   后台模板采用了之前封装过的[Matrix](https://github.com/pwstrick/grape-skin),但不会依赖Bootstrap框架。   将整个页面分成五块,分别是导航、侧边栏、面包屑、底部栏以及主体。   安装react-router的history,用于路由。 ~~~ npm install --save history ~~~   期间也会安装各类依赖包,例如不支持在类中直接声明属性等。   在使用的过程中,ESLint会不时的弹出各种错误和警告,期间就不停的修改问题或查找相关配置忽略部分限制。   后台的侧边栏和面包屑等部分,会随着URL的不同而发生状态变化,本来想用多页实现,但配置要改很多,就依然做成一个SPA,只是稍微做了些改动。   组件库采用了流行的[Ant Design](https://ant.design/components/button-cn/),调用了按钮、单选框、日期等组件。 ~~~ npm install --save antd ~~~   图表库使用的是[ECharts](https://www.echartsjs.com/zh/index.html),目前只用到了折线图和饼图。在引用图表时,为了优化构建,采取了按需引用的手段。 ~~~ npm install --save echarts ~~~ **2)项目管理**   首先建立一个项目,然后才能分析该项目的性能和错误,如图3所示。 :-: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/a7/3f/a73f2ff02e9d0e4e596e061e7182b32b_3800x800.png =800x) 图3   用弹框的形式来创建项目,使用了Ant Design的Model、Form等组件,如图4所示。 :-: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/13/9c/139c95d431ba0545a101fd3bbb2bd338_3800x982.png =800x) 图4 **3)性能分析**   在第一个折线图标签中的过滤条件包括项目、字段、日期等,性能指标按平均值呈现,可看到每个性能指标的趋势,如图5所示。 :-: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/92/68/926838dbf45530acafc42b775ed41de6_3800x1812.png =800x) 图5   按分时日统计性能平均数,在MongoDB中计算。原先创建日期是以时间戳的形式存储的,为了便于使用Aggregate,改成字符串形式。碰到一个坑,MongoDB中的Date类型采用的是格林尼治时间,而不是当前时区的时间,也就是说存在数据库中的时间会比当前时间早8小时。   在第二个列表标签中,可以详细看到每条记录的信息,包括代理、网络等,便于在了解趋势的前提下,获悉更为细节的内容,如图6所示。 :-: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/e1/12/e112aa940f5b906ac3472c89c76348de_3800x1138.png =800x) 图6   点击ajax那一列,可弹出具体的异步请求信息,如图7所示。 :-: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/20/5e/205ec1c9eeec43b99541d385de52f9a1_3800x1162.png =800x) 图7 **4)错误分析**   有三个标签,第一个也是折线图,描绘的是某个时间的错误个数;第二个是错误列表,会给出具体的错误信息,如图8所示。 :-: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/fe/ae/feaeb4394e020a3835d2da9ca3105f80_3800x1220.png =800x) 图8   第三个是饼图,饼图主要体现的是发生错误的浏览器分布情况(如图9所示),点击某一块可查看浏览器的具体版本(如图10所示)。 :-: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/ec/f2/ecf26a65dfa7116217ea0585a458c8fa_3800x1764.png =800x) 图9 :-: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/5b/56/5b56b375f2647b1398003cd9f3a17914_3798x1561.png =800x) 图10 ***** > 原文出处: [博客园-Node.js躬行记](https://www.cnblogs.com/strick/category/1688575.html) [知乎专栏-Node.js躬行记](https://zhuanlan.zhihu.com/pwnode) 已建立一个微信前端交流群,如要进群,请先加微信号freedom20180706或扫描下面的二维码,请求中需注明“看云加群”,在通过请求后就会把你拉进来。还搜集整理了一套[面试资料](https://github.com/pwstrick/daily),欢迎阅读。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200)
';