背景:市面上的监控系统有很多,大多收费,对于小型前端项目来说,必然是痛点。另一点主要原因是,功能通用,却未必能够满足我们自己的需求, 所以我们自给自足。

  这是搭建前端监控系统的第二章,主要是介绍如何统计js报错,跟着我一步步做,你也能搭建出一个属于自己的前端监控系统。

  请移步线上: 前端监控系统  

  对于前端应用来说,Js错误的发生直接影响前端应用的质量。对前端异常的监控是整个前端监控系统中的一个重要环节。前端异常包含很多种情况:1. js编译时异常(开发阶段就能排)2. js运行时异常;3. 加载静态资源异常(路径写错、资源服务器异常、CDN异常、跨域)4. 接口请求异常等。这一篇我们只介绍Js运行时异常。

  监控流程:监控错误 -> 搜集错误 -> 存储错误 -> 分析错误 -> 错误报警-> 定位错误 -> 解决错误

  首先,我们应该对Js报错情况有个大致的了解,这样才能够及时的了解前端项目的健康状况。所以我们需要分析出一些必要的数据。

  如:一段时间内,应用JS报错的走势(chart图表)、JS错误发生率、JS错误在PC端发生的概率、JS错误在IOS端发生的概率、JS错误在Android端发生的概率,以及JS错误的归类。

  然后,我们再去其中的Js错误进行详细的分析,辅助我们排查出错的位置和发生错误的原因。

  如:JS错误类型、 JS错误信息、JS错误堆栈、JS错误发生的位置以及相关位置的代码;JS错误发生的几率、浏览器的类型,版本号,设备机型等等辅助信息

一、JS Error 监控功能 (数据概览)

为了得到这些数据,我们需要在上传的时候将其分析出来。在众多日志分析中,很多字段及功能是重复通用的,所以应该将其封装起来。

// 设置日志对象类的通用属性function setCommonProperty() {this.happenTime = new Date().getTime(); // 日志发生时间this.webMonitorId = WEB_MONITOR_ID;     // 用于区分应用的唯一标识(一个项目对应一个)this.simpleUrl =  window.location.href.split('?')[0].replace('#', ''); // 页面的urlthis.customerKey = utils.getCustomerKey(); // 用于区分用户,所对应唯一的标识,清理本地数据后失效this.pageKey = utils.getPageKey();  // 用于区分页面,所对应唯一的标识,每个新页面对应一个值this.deviceName = DEVICE_INFO.deviceName;this.os = DEVICE_INFO.os + (DEVICE_INFO.osVersion ? " " + DEVICE_INFO.osVersion : "");this.browserName = DEVICE_INFO.browserName;this.browserVersion = DEVICE_INFO.browserVersion;// TODO 位置信息, 待处理this.monitorIp = "";  // 用户的IP地址this.country = "china";  // 用户所在国家this.province = "";  // 用户所在省份this.city = "";  // 用户所在城市// 用户自定义信息, 由开发者主动传入, 便于对线上进行准确定位this.userId = USER_INFO.userId;this.firstUserParam = USER_INFO.firstUserParam;this.secondUserParam = USER_INFO.secondUserParam;}// JS错误日志,继承于日志基类MonitorBaseInfofunction JavaScriptErrorInfo(uploadType, errorMsg, errorStack) {setCommonProperty.apply(this);this.uploadType = uploadType;this.errorMessage = encodeURIComponent(errorMsg);this.errorStack = errorStack;this.browserInfo = BROWSER_INFO;}JavaScriptErrorInfo.prototype = new MonitorBaseInfo();

  封装了一个Js错误对象JavaScriptErrorInfo,用以保存页面中产生的Js错误。其中,setCommonProperty用以设置所有日志对象的通用属性。

  1)重写window.onerror 方法, 大家熟知,监控JS错误必然离不开它,有人对他进行了测试测试介绍感觉也是比较用心了

  2)重写console.error方法,为什么要重写这个方法,我不能够给出明确的答案,如果App首次向浏览器注入的Js代码报错了,window.onerror是无法监控到的,所以只能重写console.error的方式来进行捕获,也许会有更好的办法。待window.onerror成功后,此方法便不再需要用了

  3)重写window.onunhandledrejection方法。 当你用到Promise的时候,而你又忘记写reject的捕获方法的时候,系统总是会抛出一个叫 Unhandled Promise rejection. 没有堆栈,没有其他信息,特别是在写fetch请求的时候很容易发生。 所以我们需要重写这个方法,以帮助我们监控此类错误

  下边是启动JS错误监控代码

/*** 页面JS错误监控*/function recordJavaScriptError() {// 重写console.error, 可以捕获更全面的报错信息var oldError = console.error;console.error = function () {// arguments的长度为2时,才是error上报的时机// if (arguments.length < 2) return;var errorMsg = arguments[0] && arguments[0].message;var url = WEB_LOCATION;var lineNumber = 0;var columnNumber = 0;var errorObj = arguments[0] && arguments[0].stack;if (!errorObj) errorObj = arguments[0];// 如果onerror重写成功,就无需在这里进行上报了!jsMonitorStarted && siftAndMakeUpMessage(errorMsg, url, lineNumber, columnNumber, errorObj);return oldError.apply(console, arguments);};// 重写 onerror 进行jsError的监听window.onerror = function(errorMsg, url, lineNumber, columnNumber, errorObj){jsMonitorStarted = true;var errorStack = errorObj ? errorObj.stack : null;siftAndMakeUpMessage(errorMsg, url, lineNumber, columnNumber, errorStack);};function siftAndMakeUpMessage(origin_errorMsg, origin_url, origin_lineNumber, origin_columnNumber, origin_errorObj) {var errorMsg = origin_errorMsg ? origin_errorMsg : '';var errorObj = origin_errorObj ? origin_errorObj : '';var errorType = "";if (errorMsg) {var errorStackStr = JSON.stringify(errorObj)errorType = errorStackStr.split(": ")[0].replace('"', "");}var javaScriptErrorInfo = new JavaScriptErrorInfo(JS_ERROR, errorType + ": " + errorMsg, errorObj);javaScriptErrorInfo.handleLogInfo(JS_ERROR, javaScriptErrorInfo);};};

OK, 错误日志有了,该怎么计算错误率呢?

  JS错误发生率 = JS错误个数(一次访问页面中,所有的js错误都算一次)/PV (PC,IOS,Android平台同理)

所以我们需要记下页面的PV记录

    /*** 添加一个定时器,进行数据的上传* 2秒钟进行一次URL是否变化的检测* 10秒钟进行一次数据的检查并上传*/var timeCount = 0;setInterval(function () {checkUrlChange();// 循环5后次进行一次上传if (timeCount >= 25) {// 如果是本地的localhost, 就忽略,不进行上传var logInfo = (localStorage[ELE_BEHAVIOR] || "") +(localStorage[JS_ERROR] || "") +(localStorage[HTTP_LOG] || "") +(localStorage[SCREEN_SHOT] || "") +(localStorage[CUSTOMER_PV] || "") +(localStorage[LOAD_PAGE] || "") +(localStorage[RESOURCE_LOAD] || "");if (logInfo) {localStorage[ELE_BEHAVIOR] = "";localStorage[JS_ERROR] = "";localStorage[HTTP_LOG] = "";localStorage[SCREEN_SHOT] = "";localStorage[CUSTOMER_PV] = "";localStorage[LOAD_PAGE] = "";localStorage[RESOURCE_LOAD] = "";utils.ajax("POST", HTTP_UPLOAD_LOG_INFO, {logInfo: logInfo}, function (res) {}, function () {})}timeCount = 0;}timeCount ++;}, 200);

  上边的代码我用了定时器,大概的意思是200毫秒进行一次URL变化的检查,5秒进行一次数据的检查,如果有数据就进行上传,并清空上一次的数据。为什么用定时器呢,因为在单页应用中,路由的切换和地址栏的变化是无法被监控的,我确实没有想到特别好的办法来监控,所以用了这种方式,如果有人有更好的办法,请给我留言,谢谢。 

  封装简易的Ajax

  为了将这些数据上传到我们的服务器,我们总不能每次都用xmlHttpRequest来发送ajax请求吧,所以我们需要自己封装一个简单的Ajax

/**** @param method  请求类型(大写)  GET/POST* @param url     请求URL* @param param   请求参数* @param successCallback  成功回调方法* @param failCallback   失败回调方法*/this.ajax = function(method, url, param, successCallback, failCallback) {var xmlHttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');xmlHttp.open(method, url, true);xmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');xmlHttp.onreadystatechange = function () {if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { var res = JSON.parse(xmlHttp.responseText); typeof successCallback == 'function' && successCallback(res); } else { typeof failCallback == 'function' && failCallback(); } }; xmlHttp.send("data=" + JSON.stringify(param)); }

二、JS Error 详细信息解析

  统计JS Error的目的,一、是为了了解线上项目的健康状况,二、是为了分析错误,帮助我们查找问题之所在,并且解决它。

  所以,如何定位线上的问题,并解决问题,是我们现在要讨论的重点。下面我们需要对几个关键点进行分析:

  ①  某种错误发生的次数——发生次数跟影响用户是成正比的, 如果发生次数跟影响用户数量都很高,那么这是一个比较严重的bug, 需要立即解决。 反之, 如果次数很多,影响用户数量很少。说明这种错误只发生在少量设备中,优先级相对较低,可以择时对该类机型设备进行兼容处理。当然,ip地址访问次数也能说明这个问题

  

  ②  页面发生了哪些错误——这个有利于我们缩小问题的范围,方便我们排查,如:

  

  ③  错误堆栈——这点不用说,是定位错误最重要的因素。正常情况下,代码都是被压缩的,所以我在后台解析并截取出错代码附近的一部分代码,进行展示,排查错误。PS: 我看到网上有人利用jsMap反向找到代码的具体位置,想法很不错,后期我会加上。 另外,代码虽然被压缩,但是依然很轻松定位到出错的位置,如下图所示, 所以这个功能暂时作为附加题,不用那么着急加上。

 

  ④  设备信息——当错误发生是,分析出用户当时使用设备的浏览器信息,系统版本,设备机型等等,能够帮我们快速的定位到需要兼容的设备,进而提升解决问题的效率。

  ⑤  用户足迹——我个人觉得比较有用,但是代价太高。 因为这个需要记录下用户在页面上的所有行为,需要上传非常多的数据,功能待定。

     这个功能已经在后边进行完善了,点击 查看足迹 按钮即可查出这个用的行为足迹,在定位线上问题方面,有很大的作用 , 我在后边的篇幅中有介绍   搭建前端监控系统(五)怎样定位线上问题

  

  到此,已经收集到了JS错误日志的大部分信息了,并且已经分析出JS错误的详细信息了。

三、JS报错的实时监控与报警

  既然我们已经具有了搜集js报错和分析报错的能力了,那么我们也可以做到Js报错实时监控,以及实时预警了,这样可以防范线上事故于未然,及时的制止线上事故的持续发生, 减少损失。

  如上图所示,我展示了从当前时间向前推算24小时,每小时报错数量。另外展示了7天前同一时间段的报错数量,如果你的项目健康稳定,那么在相同时间段的报错数量应该不会相差太大。如果出现相差太大的情况发生,说明线上出现了问题,此刻应该发出警告,避免线上事故的发生。demo上暂未加上警告功能,但是原理清楚了,后边自然水到渠成。

  上一章: 搭建前端监控系统(一)阿里云服务器搭建篇

  下一章: 搭建前端监控系统(三)NodeJs服务器部署篇


  

转载于:https://www.cnblogs.com/warm-stranger/p/9417084.html

搭建前端监控系统(二)JS错误监控篇相关推荐

  1. 前端js错误监控onerror的总结

    打工者联盟为了抵抗996.拖欠工资.黑心老板.恶心公司,让我们组成打工者联盟.客观评价自己任职过的公司情况,为其他求职者竖起一座引路的明灯.https://book.employleague.cn/ ...

  2. Grafana监控系统之Prometheus+Grafana监控系统搭建

    Grafana监控系统之Prometheus+Grafana监控系统搭建 本文章内容较长,可通过右上角点击目录快速定位想看的内容 => => 一. 概述 1.1 Grafana介绍 Gra ...

  3. 服务器账户登录监控系统,服务器账户登录监控系统

    服务器账户登录监控系统 内容精选 换一换 在使用裸金属服务器时,您可能会遇到各种问题,比如远程登录.扩容磁盘.重装操作系统.备份服务器等.为方便您获取这些场景的操作指导,本文提供了常用操作的导航.在您 ...

  4. 运维想吃透监控系统,就这一篇足够了

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:51CTO技术栈 ID:blog51cto 作者:崔皓 &q ...

  5. 第二十期:想吃透监控系统,就这一篇够不够?

    经济高速发展的今天,我们处于信息大爆炸的时代.随着经济发展,信息借助互联网的力量在全球自由地流动,于是就催生了各种各样的服务平台和软件系统. 经济高速发展的今天,我们处于信息大爆炸的时代.随着经济发展 ...

  6. 彻底吃透监控系统,就这一篇!

    由于业务的多样性,这些平台和系统也变得异常的复杂.如何对其进行监控和维护是我们 IT 人需要面对的重要问题.就在这样一个纷繁复杂地环境下,监控系统粉墨登场了. 今天,我们会对 IT 监控系统进行介绍, ...

  7. 计算机机房监控系统上海,上海机房监控-上海机房环境监控系统

    动力设备及环境集中监控系统的建设目的是通过运用先进的传感技术.通讯技术和计算机技术,对用户机房内的电源.蓄电池.高低压配电.油机等多种动力设备,以及温度.湿度.火警.盗警等环境参量进行实时监测,能够及 ...

  8. 消控监控系统 服务器,动环监控系统【斯必得智慧机房】

    原标题:动环监控系统[斯必得智慧机房] 动环监控系统是全名为机房动力环境监控系统顾名思义动环监控系统是保障基站/机房稳定运行的有效手段.目的是对机房的监控,机房呢有大量的及分散的而且各个机房有自己的独 ...

  9. 配电室环境监控系统的站端监控屏柜功能介绍

    随着无人值守配电室的普及和贯彻,加强对配电室环境的监测,保障供电安全,已成为非常重要的工作.当电力设备出现故障或现场发生异常时(如:设备短路.电缆温度过高.进水.非法闯入等),配电室环境监控系统能及时 ...

最新文章

  1. 计算机在我国开始被应用于,(),计算机在我国也开始被应用于会计工作,并由此引出了“会计电算化”这一具有强烈中国特色的专 - 试题答案网问答...
  2. 工程项目如何实现采购效益最大化?
  3. 从道的角度来论述大数据对企业价值
  4. PHP中间件ICE,ICE的安装配置,ICE常见编译和运行(异常)错误(自测Php版本安装部分,因为php版本跟ice版本不一样失败)
  5. [css] 你是怎么设计css sprites(精灵图)的?有哪些技巧?
  6. JSP--(使用请求转发的动作标识jsp:forward)
  7. 定时器控件timer winform 114869229
  8. Android SDK实例之Snake游戏深入解析(一)
  9. mybatis-plus排除非表中字段
  10. 分页查询超时问题(1)
  11. 面向对象进阶4:软件开发规范
  12. URAL 1823. Ideal Gas(数学啊 )
  13. 在linux上使用scp命令拷贝一个目录到另一台服务器的时候报not a regular file错误的解决办法...
  14. 农夫过河问题 matlab,农夫过河问题 宽搜(bfs)算法详解
  15. Axure动态面板设置 2020-11-06
  16. JAVA简历解析(无规则简历)
  17. 迪杰斯特拉算法和弗洛伊德算法
  18. shell脚本--三种引号的区别
  19. 修改IDEA默认配置路径
  20. 爱奇艺低代码引擎:千变万化、快速搭建的万花筒

热门文章

  1. 用c语言编写最大最小值_C语言学习教程,用C语言编写扫雷游戏
  2. C++新特性探究(四):Raw String Literals
  3. Matlab中3条曲线归一,matlab中关于数据归一化函数mapminmax的使用
  4. 预充电电路工作原理_变频冰箱开关电源电路工作原理及检修思路
  5. html工具箱源码,大灰狼的ASP工具箱——XMLHTTP的应用,获得远程的文件,获得远程HTML文件源码...
  6. android编辑框显示,android – 如何在屏幕上显示文本编辑框?
  7. 图像 存储csv_matplotlib基于数据文件绘制其图像
  8. 宝塔linux apache怎么部署证书,Linux+Apache部署SSL证书方法步骤
  9. 基于arduino的光控窗帘_分别基于STM32和Arduino的智能窗帘硬件分析与程序设计
  10. C++socket编程(六):6.1 设置socket的阻塞和非阻塞