web h5 错误监控

344 阅读3分钟

清晰监控类型: 1、错误监控。2、劫持 http&console。 3、页面性能。 4、页面行为 5、劫持分析

错误类型分类:resource资源加载 script 代码 promise 错误 ajax请求错误

errorType = {
    h5_resource_error: 'h5_resource_error',
    h5_script_error: 'h5_script_error',
    h5_promise_error: 'h5_promise_error',
    h5_ajax_error: 'h5_ajax_error'
}

1、errorMonitor 错误监控 实时上报

  • 添加 error 事件, 统一handlerError 函数处理 (页面错误上报条数的限制 )
  • 添加 unhandledrejection 事件 promise 未捕获的 reject 错误 统一promiseError 处理

2、http 监控 & console 日志监控

  • consoleMonitor 重写原生的方法
   let nativeConsoleError = exports.console.error
   window.console.error = function(err){
       self.handlerError(err)
       nativeConsoleError.apply(exports.console, arguments)
   }
  • http 请求监控 & 获取请求耗时 -- 分析网络性能接口字段
    exports.XMLHttpRequest.prototype.nativeSetRequestHeader = exports.XMLHttpRequest.prototype.setRequestHeader;
    exports.XMLHttpRequest.prototype.setRequestHeader = function(name,value){
        // 添加请求头
        this.xxx = this.xxx || {};
        this.nativeSetRequestHeader.apply(this,arguments);
    };
    exports.XMLHttpRequest.prototype.nativeOpen = exports.XMLHttpRequest.prototype.open;
    xxx.open = function(){}
    exports.XMLHttpRequest.prototype.nativeSend = exports.XMLHttpRequest.prototype.send;
    xxx.send = function(){}
    
    1、load 之后且readyState === 4
    2let isError = ((this.status > 199 && this.status < 300) || this.status === 304) ? false : true;
    3、错误的实时上报,其他情况接口的性能数据,随机上报
    

3、performanceMonitor 页面性能数据

通过监听load 和beforeunload 事件,去取对应的performance 性能数据,进行上报。参考另一篇文章。 h5页面指标解读

4、页面行为监听 & 停留时间 & PV

const EventListenerList = ['DOMContentLoaded','load','beforeunload','unload','pagehide','pageshow','viewhide','viewshow']
EventListenerList.forEach(item=>{
    addEvent(item, ()=>{
        this.actionListener(item)
    }, true)
})

统一分发各各事件监听处理回调 actionMonitor 页面行为 像 DOMContentLoad load beforeunload unload pagehide pageshow viewhide viewshow

最终在页面卸载之前上报,走的是navigator.sendBeacon, 在fiddler 上可看

if(navigator.sendBeacon){
      navigator.sendBeacon('xxx/katoto.json', JSON.stringify(data));
  } else {
      let xhr=new XMLHttpRequest()
      xhr.open('POST','xxx/katoto.json',true);
      xhr.send(JSON.stringify(data))
  }

获取当前网络 navigator.connection.effectiveType // slow-2g, 2g, 3g, 4g

公共字段:像屏幕尺寸、经纬度、net_type 2g 3g 4g

遇到:

  • 0、关闭tab页,unload事件中产生HttpRequest会丢失,最终用navigator.sendBeacon进行数据发送,抓包验证。

    • 浏览器将 Beacon 请求排队让它在空闲的时候执行并立即返回控制
    • 它在unload状态下也可以异步发送,不阻塞页面刷新/跳转等操作。
    • Beacon可解决上面提到的因XHR(XMLHttpRequest)同步请求阻塞而引起的性能缺陷问题。 接口用于安排异步和非阻塞数据传输,从而能最大限度地减少与其它关键型操作的资源争用,同时还能将请求发送到目的地。
  • 1、采集比例 设置不同信息类型随机数处理 Math.random() <= _Random

  • 2、遇到js资源跨域导致错误信息获取为 Script error. at line:0 col:0, at line: col:

    -低版本,webpack 插件解决 -vue-cli 已直接配置支持

  • 3、使用 addEventListener 捕获资源错误时,一定要将 useCapture 即第三个选项设为 true,因为资源错误没有冒泡,所以只能在捕获阶段捕获。同理,由于 window.onerror 是通过在冒泡阶段捕获错误,所以无法捕获资源错误。

tips:在一些特殊情况下,我们依然需要使用 window.onerror。比如,不期望在控制台抛出错误时,因为只有 window.onerror 才能阻止抛出错误到控制台

及时上报、批量上报、用户主动上报?。

用户行为分析的拓展

前端监控了解与简易实现

监控

数据上报

关闭页面: beforeunload --> pagehide --> unload

性能面板呈现的几个主要线程

  • Main 主线程,渲染相关的事都是它做,像脚本执行、样式计算、布局计算、绘制等。
  • Network 网络线程,可以看到所有的网络请求和文件下载调用信息。
  • compositor & raster compositor 合成线程, raster 栅格线程。绘制一个页面,分成
    • 主线程把页面分成若干图层
    • 栅格线程分别对每一个层进行栅格化处理
    • 合成线程将栅格化的图块合并成一个页面

浏览器工作报告

  • 文档下载解析, 遇到script(不含async、defer)标签,解析停止,直到脚本下载并执行完成。图片、css 下载时,html解析过程可以继续。计算style 时候,解析也是挂起的。
  • 首次绘制的动作
    • css 加载完成
    • parse Stylesheet 解析样式表,构建出CSSOM
    • Recalcute Style 重新计算样式,确定样式规则
    • Layout 根据计算结果进行布局,确定元素的大小和位置
    • Update Layer Tree 更新渲染层数
    • Paint 根据Layer Tree 绘制页面(大小、位置、颜色、边框、阴影)
    • Composite Layers 组合层,浏览器将图层合并后输出屏幕

浏览器工作报告

问题

  • 是不是可以兼容所有错误? 样式异常、框架层的错误、fetch请求的错误等 脚本错误大体分为两种:编译错误和运行时错误;
  • 完善的地方
    • 用户主动上报
    • 异常的录制
    • 监控通知
    • source map 错误信息的解读
    • 数据脱敏