拓扑图

错误监控

1、js错误

try catch主动捕获,try catch不能捕获异步错误,会被全局onerror事件捕获

try {const str = '11111'str.map()} catch (error) {errorCaptcher(error, error.message)}

window.onerror全局捕获,onerror绑定事件会被覆盖,需要使用自定义事件做下处理,不影响原有事件执行

// 全局事件捕获export const errorTrackerReport = () => {// js错误const originError = window.onerrorwindow.onerror = (msg, url, row, col, error) => {// 执行原有onerror事件originError && originError.call(window, msg, url, row, col, error)lazyReport('error', {message: msg,file: url,row,col,error: JSON.stringify(error, Object.getOwnPropertyNames(error), 2), // 直接传入error类型,序列化会丢失,errorType: 'jsError'})}
2、reject错误

promise未被catch捕获的reject,会被unhandledrejection捕获,添加全局监听捕获

// promise未被捕获错误window.addEventListener('unhandledrejection', (error) => {lazyReport('error', {message: error.reason,error: JSON.stringify(error, Object.getOwnPropertyNames(error), 2), // 直接传入error类型,序列化会丢失,errorType: 'promiseError'})})
3、资源加载错误

资源加载错误需要使用window.addEventListener(‘error’, () => {})捕获,需要筛选错误对象的标签,避免错误捕获重复上报。

// ------- resource error --------window.addEventListener('error', (error) => {let target = error.target;let isElementTarget = target instanceof HTMLScriptElement || target instanceof HTMLLinkElement || target instanceof HTMLImageElement;if (!isElementTarget) {return; // js error不再处理}lazyReport('error', {message: "加载 " + target.tagName + " 资源错误",file: target.src,errorType: 'resourceError'});}, true)
4、语法错误

这个基本不要捕获,开发阶段eslint就可以抛出错误

5、框架错误

vue:Vue.config.handleError、errorCaptured
react:错误边界
小程序:App.onError()、Page.onError()、wx.onError()

6、白屏

白屏的监控使用document.elementsFromPoint(x, y), 判断当前点返回的第一个元素是否为html、body等,判断是否为空白点位,判断多个点位是否为空白。

7、常见问题

window.onerror方式的错误监听,会覆盖原有onerror方法;使用自定义事件改写onerror;

js报错,会走进资源加载错误监听事件内,导致重复日志;判断错误标签是否为script、link、img、video、audio;

除了onerror可以精确到行、列信息,其他错误无法精确位置;其他错误捕获后,使用throw error,让window.onerror再捕获;

行为监控

1、手动埋点

这个没什么说的,sdk提供上报方法,外部直接调用

<buttonstyle={{ 'marginRight': '20px' }}data-no="yes"onClick={() => actionTrackerReport('button', '手动埋点被点击了')}>

2、属性埋点

设置特定属性,全局监听click事件,触发上报功能。例如data-target=”属性埋点被点击了”

export const autoActionTrackerReport = () => {window.addEventListener('click', (e) => {const clickedDom = e.target// 获取自动上报标识内容const target = clickedDom" />const reportWebVitals = onPerfEntry => {if (onPerfEntry && onPerfEntry instanceof Function) {import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {getCLS(onPerfEntry);getFID(onPerfEntry);getFCP(onPerfEntry);getLCP(onPerfEntry);getTTFB(onPerfEntry);});}};

2、performance

使用window.performance原生api计算

代码片段

const {fetchStart,connectStart,connectEnd,requestStart,responseStart,responseEnd,domLoading,domInteractive,domContentLoadedEventStart,domContentLoadedEventEnd,loadEventStart,} = window.performance.timing;// 发送时间指标// 用户体验指标lazyReport('performance', {type: "timing", // 统计每个阶段的时间connectTime: connectEnd - connectStart, // TCP连接耗时ttfbTime: responseStart - requestStart, // 首字节到达时间responseTime: responseEnd - responseStart, // response响应耗时parseDOMTime: loadEventStart - domLoading, // DOM解析渲染的时间domContentLoadedTime:domContentLoadedEventEnd - domContentLoadedEventStart, // DOMContentLoaded事件回调耗时timeToInteractive: domInteractive - fetchStart, // 首次可交互时间loadTime: loadEventStart - fetchStart, // 完整的加载时间})

日志采集

采集方式

1、常规API

2、navigator.sendBeacon

3、JSONP方式,使用img标签

常见问题

异步xhr在页面卸载后,会被中止,导致丢失;

navigator.sendBeacon兼容性不太好;

上报太过频繁,服务器压力大;添加延迟并且合并上报;

error类型JSON.stringfy后会丢失;使用JSON.stringfy的第二个参数解决丢失问题;

TODO

日志上报接口开发

监控平台日志分析平台开发

demo代码

https://github.com/wufeng123456/front-monitor-sdk.git

参考链接

迄今为止最全的前端监控体系搭建篇(长文预警) – 知乎