前端监控之性能与异常
字数 1934 2025-08-11 11:39:36
前端监控之性能与异常监控教学文档
1. 前言
前端监控是保障Web应用稳定性和用户体验的重要手段。与服务端监控相比,前端监控长期以来被忽视,导致以下问题难以发现和解决:
- 页面白屏时间
- 静态资源加载情况
- 接口请求耗时
- 页面崩溃原因
- 用户行为分析
建立完善的前端监控系统可以:
- 持续监控和预警页面性能状况
- 发现性能瓶颈并指导优化工作
- 收集用户行为数据支持产品迭代
2. 前端监控目标
2.1 保证稳定性(异常监控)
- JavaScript代码错误
- Promise错误
- 接口错误(XHR、fetch)
- 资源加载错误(script、link等)
2.2 提升用户体验(性能监控)
- 页面加载时间
- 接口响应时间
- 关键渲染节点
3. 性能监控
3.1 页面加载过程
从URL输入到页面加载完成的完整流程:
- DNS解析:将URL解析为IP地址
- TCP连接:与服务器建立TCP连接
- HTTP请求:向服务器发送HTTP请求
- 服务端处理:服务器处理请求并返回响应
- 浏览器渲染:解析响应内容并渲染页面
3.2 Performance API详解
通过window.performanceAPI可以获取详细的性能指标:
3.2.1 关键时间戳(按触发顺序)
| 属性 | 描述 |
|---|---|
| navigationStart | 前一个页面unload的时间戳 |
| redirectStart | 第一个HTTP重定向开始时间 |
| unloadEventStart | 前一个页面unload开始时间 |
| redirectEnd | 最后一个HTTP重定向完成时间 |
| unloadEventEnd | 前一个页面unload回调执行完毕时间 |
| fetchStart | 浏览器准备发起HTTP请求的时间 |
| domainLookupStart | DNS查询开始时间 |
| domainLookupEnd | DNS查询完成时间 |
| connectStart | TCP连接开始时间 |
| secureConnectionStart | HTTPS连接开始时间 |
| connectEnd | TCP连接完成时间 |
| requestStart | HTTP请求开始时间 |
| responseStart | 开始接收响应时间 |
| responseEnd | 响应完全接收时间 |
| domLoading | 开始解析DOM树时间 |
| domInteractive | 完成DOM解析时间 |
| domContentLoadedEventStart | DOM解析完成后资源加载开始时间 |
| domContentLoadedEventEnd | DOM解析完成后资源加载完成时间 |
| domComplete | DOM树解析完成且资源就绪时间 |
| loadEventStart | load事件开始执行时间 |
| loadEventEnd | load事件执行完毕时间 |
3.3 性能指标计算
const { timing, navigation } = window.performance;
const loadPageInfo = {};
// 页面加载类型:0初次加载,1重加载
loadPageInfo.loadType = navigation.type;
// 页面加载总时间(白屏时间)
loadPageInfo.loadPage = timing.loadEventEnd - timing.navigationStart;
// 重定向时间
loadPageInfo.redirect = timing.redirectEnd - timing.redirectStart;
// 卸载页面时间
loadPageInfo.unloadEvent = timing.unloadEventEnd - timing.unloadEventStart;
// DNS本地缓存查询时间
loadPageInfo.appCache = timing.domainLookupStart - timing.fetchStart;
// DNS查询时间(重要)
loadPageInfo.lookupDomain = timing.domainLookupEnd - timing.domainLookupStart;
// TCP连接时间
loadPageInfo.connect = timing.connectEnd - timing.connectStart;
// HTTP请求及获取文档时间(重要)
loadPageInfo.request = timing.responseEnd - timing.responseStart;
// TTFB(Time To First Byte,重要)
loadPageInfo.ttfb = timing.responseStart - timing.navigationStart;
// DOM解析时间
loadPageInfo.domReady = timing.domComplete - timing.responseEnd;
// onload回调执行时间(重要)
loadPageInfo.loadEvent = timing.loadEventEnd - timing.loadEventStart;
3.4 性能优化建议
-
DNS查询优化:
- 减少不同域名数量
- 使用DNS预加载(HTML5 Prefetch)
-
TTFB优化:
- 增加异地机房
- 使用CDN
- 增加带宽
- 提升CPU运算速度
-
onload回调优化:
- 避免在onload中执行过多操作
- 采用延迟加载策略
- 按需加载资源
4. 异常监控
4.1 JavaScript错误监控
4.1.1 重写console.error捕获错误
var oldError = console.error;
console.error = function(tempErrorMsg) {
var errorMsg = (arguments[0] && arguments[0].message) || tempErrorMsg;
var lineNumber = 0;
var columnNumber = 0;
var errorStack = arguments[0] && arguments[0].stack;
if(!errorStack) {
saveJSError('console_error', errorMsg, '', lineNumber, columnNumber, 'CustomizeError: ' + errorMsg);
} else {
saveJSError('console_error', errorMsg, '', lineNumber, columnNumber, errorStack);
}
return oldError.apply(console, arguments);
};
4.1.2 监听error事件
window.addEventListener('error', function(e) {
var errorMsg = e.error && e.error.message,
errorStack = e.error && e.error.stack,
pageUrl = e.filename,
lineNumber = e.lineno,
columnNumber = e.colno;
saveJSError('on_error', errorMsg, pageUrl, lineNumber, columnNumber, errorStack);
});
4.2 Promise错误监控
window.onunhandledrejection = function(e) {
var errorMsg = '';
var errorStack = '';
if(typeof e.reason === 'object') {
errorMsg = e.reason.message;
errorStack = e.reason.stack;
} else {
errorMsg = e.reason;
errorStack = 'UncaughtInPromiseError: ' + errorMsg;
}
saveJSError('promise_error', errorMsg, '', 0, 0, errorStack);
}
4.3 资源加载错误监控
通过error事件监听资源加载错误:
window.addEventListener('error', function(e) {
// 判断是否为资源加载错误
if(e.target && (e.target.src || e.target.href)) {
var resourceUrl = e.target.src || e.target.href;
saveResourceError(resourceUrl, e.timeStamp);
}
}, true); // 使用捕获阶段确保能捕获到资源加载错误
5. 数据上报
监控数据需要上报到服务器进行分析和展示:
function saveJSError(type, message, url, line, column, stack) {
var errorData = {
type: type,
message: message,
url: url || window.location.href,
line: line,
column: column,
stack: stack,
timestamp: new Date().getTime(),
userAgent: navigator.userAgent
};
// 使用图片信标或navigator.sendBeacon上报数据
reportError(errorData);
}
function reportError(data) {
var url = 'https://your-monitor-server.com/api/error';
var blob = new Blob([JSON.stringify(data)], {type: 'application/json'});
// 优先使用sendBeacon,在不阻塞页面卸载的情况下发送数据
if(navigator.sendBeacon) {
navigator.sendBeacon(url, blob);
} else {
// 回退方案:使用同步XHR
var xhr = new XMLHttpRequest();
xhr.open('POST', url, false);
xhr.send(blob);
}
}
6. 监控系统扩展
完整的监控系统还应包括:
6.1 接口监控
- 接口请求成功率
- 接口响应时间
- 接口错误码统计
6.2 用户行为监控
- PV/UV统计
- 页面停留时间
- 点击热力图
- 用户路径分析
6.3 可视化平台
- 性能指标仪表盘
- 错误趋势图表
- 报警阈值设置
- 错误详情查看
7. 最佳实践
- 采样率控制:高流量站点应设置合理的采样率
- 数据聚合:服务端应对相似错误进行聚合
- 错误过滤:忽略已知或无关紧要的错误
- 性能优化:监控脚本本身应轻量高效
- 隐私保护:敏感信息应脱敏处理
8. 总结
前端监控系统建设要点:
- 通过Performance API全面监控页面性能
- 通过错误事件监听捕获各类异常
- 实现可靠的数据上报机制
- 建立可视化分析平台
- 持续优化监控策略
完善的监控系统能为产品提供:
- 稳定性保障
- 性能优化依据
- 用户体验洞察
- 产品决策支持