这套前端监控系统用到的技术栈是: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
<head>
<script>
window.pineapple || (pineapple = {});
pineapple.param = {
"token": "dsadasd2323dsad23dsada"
};
</script>
<script src="js/pineapple.js"></script>
</head>
~~~
## 二、服务端
**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://img.kancloud.cn/06/c5/06c5fa9b2651ab01154b2b5e978d7d49_1487x446.png =600x)
图1
  注意,在安装时默认会下载[MongoDB Compress](https://www.mongodb.com/download-center/compass)(一个可视化的MongoDB工具),默认下载会非常慢,建议自行下载,该工具的界面还是蛮清爽的,如图2所示。
:-: ![](https://img.kancloud.cn/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://img.kancloud.cn/a7/3f/a73f2ff02e9d0e4e596e061e7182b32b_3800x800.png =800x)
图3
  用弹框的形式来创建项目,使用了Ant Design的Model、Form等组件,如图4所示。
:-: ![](https://img.kancloud.cn/13/9c/139c95d431ba0545a101fd3bbb2bd338_3800x982.png =800x)
图4
**3)性能分析**
  在第一个折线图标签中的过滤条件包括项目、字段、日期等,性能指标按平均值呈现,可看到每个性能指标的趋势,如图5所示。
:-: ![](https://img.kancloud.cn/92/68/926838dbf45530acafc42b775ed41de6_3800x1812.png =800x)
图5
  按分时日统计性能平均数,在MongoDB中计算。原先创建日期是以时间戳的形式存储的,为了便于使用Aggregate,改成字符串形式。碰到一个坑,MongoDB中的Date类型采用的是格林尼治时间,而不是当前时区的时间,也就是说存在数据库中的时间会比当前时间早8小时。
  在第二个列表标签中,可以详细看到每条记录的信息,包括代理、网络等,便于在了解趋势的前提下,获悉更为细节的内容,如图6所示。
:-: ![](https://img.kancloud.cn/e1/12/e112aa940f5b906ac3472c89c76348de_3800x1138.png =800x)
图6
  点击ajax那一列,可弹出具体的异步请求信息,如图7所示。
:-: ![](https://img.kancloud.cn/20/5e/205ec1c9eeec43b99541d385de52f9a1_3800x1162.png =800x)
图7
**4)错误分析**
  有三个标签,第一个也是折线图,描绘的是某个时间的错误个数;第二个是错误列表,会给出具体的错误信息,如图8所示。
:-: ![](https://img.kancloud.cn/fe/ae/feaeb4394e020a3835d2da9ca3105f80_3800x1220.png =800x)
图8
  第三个是饼图,饼图主要体现的是发生错误的浏览器分布情况(如图9所示),点击某一块可查看浏览器的具体版本(如图10所示)。
:-: ![](https://img.kancloud.cn/ec/f2/ecf26a65dfa7116217ea0585a458c8fa_3800x1764.png =800x)
图9
:-: ![](https://img.kancloud.cn/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://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200)
推荐一款前端监控脚本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不仅能监控前端的错误、通信、打印等行为,还能计算各类性能参数,包括 FMP、LCP、FP 等。
- ES6
- 1、let和const
- 2、扩展运算符和剩余参数
- 3、解构
- 4、模板字面量
- 5、对象字面量的扩展
- 6、Symbol
- 7、代码模块化
- 8、数字
- 9、字符串
- 10、正则表达式
- 11、对象
- 12、数组
- 13、类型化数组
- 14、函数
- 15、箭头函数和尾调用优化
- 16、Set
- 17、Map
- 18、迭代器
- 19、生成器
- 20、类
- 21、类的继承
- 22、Promise
- 23、Promise的静态方法和应用
- 24、代理和反射
- HTML
- 1、SVG
- 2、WebRTC基础实践
- 3、WebRTC视频通话
- 4、Web音视频基础
- CSS进阶
- 1、CSS基础拾遗
- 2、伪类和伪元素
- 3、CSS属性拾遗
- 4、浮动形状
- 5、渐变
- 6、滤镜
- 7、合成
- 8、裁剪和遮罩
- 9、网格布局
- 10、CSS方法论
- 11、管理后台响应式改造
- React
- 1、函数式编程
- 2、JSX
- 3、组件
- 4、生命周期
- 5、React和DOM
- 6、事件
- 7、表单
- 8、样式
- 9、组件通信
- 10、高阶组件
- 11、Redux基础
- 12、Redux中间件
- 13、React Router
- 14、测试框架
- 15、React Hooks
- 16、React源码分析
- 利器
- 1、npm
- 2、Babel
- 3、webpack基础
- 4、webpack进阶
- 5、Git
- 6、Fiddler
- 7、自制脚手架
- 8、VSCode插件研发
- 9、WebView中的页面调试方法
- Vue.js
- 1、数据绑定
- 2、指令
- 3、样式和表单
- 4、组件
- 5、组件通信
- 6、内容分发
- 7、渲染函数和JSX
- 8、Vue Router
- 9、Vuex
- TypeScript
- 1、数据类型
- 2、接口
- 3、类
- 4、泛型
- 5、类型兼容性
- 6、高级类型
- 7、命名空间
- 8、装饰器
- Node.js
- 1、Buffer、流和EventEmitter
- 2、文件系统和网络
- 3、命令行工具
- 4、自建前端监控系统
- 5、定时任务的调试
- 6、自制短链系统
- 7、定时任务的进化史
- 8、通用接口
- 9、微前端实践
- 10、接口日志查询
- 11、E2E测试
- 12、BFF
- 13、MySQL归档
- 14、压力测试
- 15、活动规则引擎
- 16、活动配置化
- 17、UmiJS版本升级
- 18、半吊子的可视化搭建系统
- 19、KOA源码分析(上)
- 20、KOA源码分析(下)
- 21、花10分钟入门Node.js
- 22、Node环境升级日志
- 23、Worker threads
- 24、低代码
- 25、Web自动化测试
- 26、接口拦截和页面回放实验
- 27、接口管理
- 28、Cypress自动化测试实践
- 29、基于Electron的开播助手
- Node.js精进
- 1、模块化
- 2、异步编程
- 3、流
- 4、事件触发器
- 5、HTTP
- 6、文件
- 7、日志
- 8、错误处理
- 9、性能监控(上)
- 10、性能监控(下)
- 11、Socket.IO
- 12、ElasticSearch
- 监控系统
- 1、SDK
- 2、存储和分析
- 3、性能监控
- 4、内存泄漏
- 5、小程序
- 6、较长的白屏时间
- 7、页面奔溃
- 8、shin-monitor源码分析
- 前端性能精进
- 1、优化方法论之测量
- 2、优化方法论之分析
- 3、浏览器之图像
- 4、浏览器之呈现
- 5、浏览器之JavaScript
- 6、网络
- 7、构建
- 前端体验优化
- 1、概述
- 2、基建
- 3、后端
- 4、数据
- 5、后台
- Web优化
- 1、CSS优化
- 2、JavaScript优化
- 3、图像和网络
- 4、用户体验和工具
- 5、网站优化
- 6、优化闭环实践
- 数据结构与算法
- 1、链表
- 2、栈、队列、散列表和位运算
- 3、二叉树
- 4、二分查找
- 5、回溯算法
- 6、贪心算法
- 7、分治算法
- 8、动态规划
- 程序员之路
- 大学
- 2011年
- 2012年
- 2013年
- 2014年
- 项目反思
- 前端基础学习分享
- 2015年
- 再一次项目反思
- 然并卵
- PC网站CSS分享
- 2016年
- 制造自己的榫卯
- PrimusUI
- 2017年
- 工匠精神
- 2018年
- 2019年
- 前端学习之路分享
- 2020年
- 2021年
- 2022年
- 2023年
- 日志
- 2020