Open Genzhen opened 3 years ago
每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案 欢迎大家在下方发表自己的优质见解 二维码加载失败可点击 小程序二维码
每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案 欢迎大家在下方发表自己的优质见解
前端的数据其实有很多,从大众普遍关注的 PV、UV、广告点击量,到客户端的网络环境、登陆状态,再到浏览器、操作系统信息,最后到页面性能、JS 异常,这些数据都可以在前端收集到。
这里的异常是指 JS 的异常,用户的浏览器上报 JS 的 bug,这会极大地降低用户体验
e.src
除了上面提到的 4 类基本的数据统计需求,我们当然还可以根据实际情况来定义一些其他的统计需求,如用户浏览器对 canvas 的支持程度, 再比如比较特殊的-用户进行轮播图翻页的次数,这些数据统计需求都是前端能够满足的,每一项统计的结果都体现了前端数据的价值
let info = { title: "前端监控系统", // 页面标题 url: "http://localhost:8080", // 页面url timestamp: "1212121212121212", // 访问时间戳 userAgent: "chrome", // 用户浏览器类型 kind: "stability", // 大类 type: "error", // 小类 errorType: "jsError", // 错误类型 message: "uncaught TypeError:blablabla", // 错误详情 filename: "http://localhost:8080/", // 访问的文件名 position: "0:0", // 行列信息 stack: "btn Click (http://localhost:8080)", // 堆栈信息 selector: "HTML BODY #container .content INPUT", // 选择器 };
let info = { title: "前端监控系统", // 页面标题 url: "http://localhost:8080", // 页面url timestamp: "1212121212121212", // 访问时间戳 userAgent: "chrome", // 用户浏览器类型 kind: "stability", // 大类 type: "xhr", // 小类 eventType: "load", // 事件类型 pathname: "/success", status: "200-0k", duration: "5", // 持续时间 response: "hahah", // 响应内容 params: "参数", // 参数 };
let info = { title: "前端监控系统", url: "http://localhost:8080/", timestamp: "1239404040404044", userAgent: "chorme", kind: "stability", type: "blank", emptyPoints: "0", // 空白点 screen: "2049 * 1152", // 分辨率 viewPoint: "2048 * 994", // 视口 selector: "HTML BODY #container", // 选择器 };
整体大致可以分四个阶段:信息采集、存储、分析、监控。
采集阶段:收集异常日志,先在本地做一定的处理,采取一定的方案上报到服务器。
存储阶段:后端接收前端上报的异常日志,经过一定处理,按照一定的存储方案存储。
分析阶段:分为机器自动分析和人工分析。机器自动分析,通过预设的条件和算法,对存储的日志信息进行统计和筛选,发现问题,触发报警。人工分析,通过提供一个可视化的数据面板,让系统用户可以看到具体的日志数据,根据信息,发现异常问题根源。
报警阶段:分为告警和预警。告警按照一定的级别自动报警,通过设定的渠道,按照一定的触发规则进行。预警则在异常发生前,提前预判,给出警告。
性能监控: 使用 Resource Timing API 和 Performance Timing API,可以计算许多重要的指标,比如页面性能统计的起始点时间、首屏时间等。
异常监控: 前端捕获异常分为全局捕获和局部捕获。局部捕获作为补充,对某些特殊情况进行捕获,但分散,不利于管理。所以,我会选择全局捕获的方式,即通过全局的接口,将捕获代码集中写在一个地方。具体在实现项目中,我应该会采用 badjs-report,它重写了 window.onerror 进行上报异常,无需编写任何捕获错误的代码。
前端埋点: 埋点的方案有手动埋点,即在需要监控的地方插入监控逻辑,但是工作量可能会很大;还有无埋点,前端自动采集全部事件,上报埋点数据,但是缺点是服务器压力会很大。我可能倾向于采用声明式埋点,将埋点代码和具体的业务逻辑解耦,只用关心需要埋点的控件,并且为这些控件声明需要的埋点数据即可,主要是为了降低埋点的成本吧。在 dom 元素上增添埋点信息,比如
// key表示埋点的唯一标识;act表示埋点方式 <button data-stat="{key:'buttonKey', act: 'click'}">埋点</button>
监控告警: 这里我认为最便捷、高效的方式,就是接入内部的告警组了吧,尤其是在阿里,似乎什么轮子都有,那可能需要考虑就是触发告警的阈值和时机了。
性能:使用 Performance API,可以得到许多重要的指标,如页面性能统计的起始点时间、首屏时间等
报错:使用 onerror 和 onunhandledrejection,甚至是 try catch
操作行为:对事件触发函数做 patch,或者添加特定的事件监听
PV/UV:利用浏览器存储方法或 Cookie、IP 等储存相应用户信息,随请求发送
设备信息:获取 navigator.userAgent
PV、UV 属于增长数字类型,可以用 Redis 等记录,如果有需要,定时入库。其他属于大量文字信息,可以用成熟的消息队列来消费。因为有大量写,所以可以考虑做读写分离。
技术难点:
可能整个系统比较复杂的就是如何高效合理的进行监控数据上传。除了异常报错信息本身,还需要记录用户操作日志,如果任何日志都立即上报,这无异于自造的 DDOS 攻击。那就需要考虑前端日志的存储,日志如何上传,上传前如何整理日志等问题。
前端在收集的过程中可能会影响用户体验。
后端对于收到的日志要使用合适的工具进行收集,数据量大时选择如何取舍。
可能会采取的方案
扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。
一、为什么要做前端监控
二、前端数据分类
前端的数据其实有很多,从大众普遍关注的 PV、UV、广告点击量,到客户端的网络环境、登陆状态,再到浏览器、操作系统信息,最后到页面性能、JS 异常,这些数据都可以在前端收集到。
2.1 访问相关的数据
2.2 性能相关的数据
2.3 点击相关的数据
2.4 异常相关的数据
这里的异常是指 JS 的异常,用户的浏览器上报 JS 的 bug,这会极大地降低用户体验
e.src
为空或不是对象2.5 其它数据
除了上面提到的 4 类基本的数据统计需求,我们当然还可以根据实际情况来定义一些其他的统计需求,如用户浏览器对 canvas 的支持程度, 再比如比较特殊的-用户进行轮播图翻页的次数,这些数据统计需求都是前端能够满足的,每一项统计的结果都体现了前端数据的价值
三、性能指标
四、前端监控目标(监控分类)
4.1 稳定性(stability)
4.2 用户体验(experience)
4.3 业务
五、前端监控流程
六、常见的埋点方案
6.1 代码埋点
6.2 可视化埋点
6.3 无痕埋点
七、编写监控采集脚本
7.1 监控错误
7.2 数据结构设计
整体大致可以分四个阶段:信息采集、存储、分析、监控。
采集阶段:收集异常日志,先在本地做一定的处理,采取一定的方案上报到服务器。
存储阶段:后端接收前端上报的异常日志,经过一定处理,按照一定的存储方案存储。
分析阶段:分为机器自动分析和人工分析。机器自动分析,通过预设的条件和算法,对存储的日志信息进行统计和筛选,发现问题,触发报警。人工分析,通过提供一个可视化的数据面板,让系统用户可以看到具体的日志数据,根据信息,发现异常问题根源。
报警阶段:分为告警和预警。告警按照一定的级别自动报警,通过设定的渠道,按照一定的触发规则进行。预警则在异常发生前,提前预判,给出警告。
性能监控: 使用 Resource Timing API 和 Performance Timing API,可以计算许多重要的指标,比如页面性能统计的起始点时间、首屏时间等。
异常监控: 前端捕获异常分为全局捕获和局部捕获。局部捕获作为补充,对某些特殊情况进行捕获,但分散,不利于管理。所以,我会选择全局捕获的方式,即通过全局的接口,将捕获代码集中写在一个地方。具体在实现项目中,我应该会采用 badjs-report,它重写了 window.onerror 进行上报异常,无需编写任何捕获错误的代码。
前端埋点: 埋点的方案有手动埋点,即在需要监控的地方插入监控逻辑,但是工作量可能会很大;还有无埋点,前端自动采集全部事件,上报埋点数据,但是缺点是服务器压力会很大。我可能倾向于采用声明式埋点,将埋点代码和具体的业务逻辑解耦,只用关心需要埋点的控件,并且为这些控件声明需要的埋点数据即可,主要是为了降低埋点的成本吧。在 dom 元素上增添埋点信息,比如
监控告警: 这里我认为最便捷、高效的方式,就是接入内部的告警组了吧,尤其是在阿里,似乎什么轮子都有,那可能需要考虑就是触发告警的阈值和时机了。
性能:使用 Performance API,可以得到许多重要的指标,如页面性能统计的起始点时间、首屏时间等
报错:使用 onerror 和 onunhandledrejection,甚至是 try catch
操作行为:对事件触发函数做 patch,或者添加特定的事件监听
PV/UV:利用浏览器存储方法或 Cookie、IP 等储存相应用户信息,随请求发送
设备信息:获取 navigator.userAgent
PV、UV 属于增长数字类型,可以用 Redis 等记录,如果有需要,定时入库。其他属于大量文字信息,可以用成熟的消息队列来消费。因为有大量写,所以可以考虑做读写分离。
技术难点:
可能整个系统比较复杂的就是如何高效合理的进行监控数据上传。除了异常报错信息本身,还需要记录用户操作日志,如果任何日志都立即上报,这无异于自造的 DDOS 攻击。那就需要考虑前端日志的存储,日志如何上传,上传前如何整理日志等问题。
前端在收集的过程中可能会影响用户体验。
后端对于收到的日志要使用合适的工具进行收集,数据量大时选择如何取舍。
可能会采取的方案