拓扑图
错误监控
1、js错误
try catch主动捕获,try catch不能捕获异步错误,会被全局onerror事件捕获
javascript"> try {
const str = '11111'
str.map()
} catch (error) {
errorCaptcher(error, error.message)
}
window.onerror全局捕获,onerror绑定事件会被覆盖,需要使用自定义事件做下处理,不影响原有事件执行
// 全局事件捕获
export const errorTrackerReport = () => {
// js错误
const originError = window.onerror
window.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提供上报方法,外部直接调用
<button
style={{ '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?.getAttribute('data-target')
const no = clickedDom?.getAttribute('data-no')
// 主动上报设置,避免重复
if (no) return
if (target) {
lazyReport('action', {
actionType: 'click',
data: target
})
} else {
const path = getPath(clickedDom)
lazyReport('action', {
actionType: 'click',
data: path
})
}
})
}
3、自动埋点
代码同属性埋点,日志会记录点击的元素路径
4、常见问题
属性埋点和自动埋点监听click事件,依托于事件冒泡,容易被阻止;阻止冒泡的地方使用手动埋点;
开启自动埋点,触发手动埋点会冒泡到自动埋点,导致重复上报;添加特定属性,避免重复上报;
自动埋点,随便点击都会记录,怎么筛选掉无用的点击;TODO
PV
1、history路由
自定义事件改写history.pushState、history.replaceState
浏览器操作前进、后退;使用window.popstate
刷新页面:监听load事件
页面卸载:监听unload事件
2、hash路由
添加hashChange事件监听
自定义事件改写history.pushState,vue-router实现会优先使用history.pushState,不支持再使用location.hash改变
页面刷新,会被hashchange事件捕获
页面卸载:监听unload
UV
UV只需要登录后把用户信息,上传到接口即可
性能监控
1、web-vitals
使用三方库web-vitals,输出性能指标
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.***/wufeng123456/front-monitor-sdk.git
参考链接
迄今为止最全的前端监控体系搭建篇(长文预警) - 知乎