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)
';