你想做的是一个 前端监控系统(Frontend Monitoring / RUM, Real User Monitoring),主要包括:
异常监控(JS 报错、资源加载错误、Promise 未捕获异常)
性能监控(白屏时间、首屏时间、页面加载时间、TTFB、FCP、LCP、CLS 等指标)
行为监控(PV/UV、路由变化、用户操作)
上报机制(采集到的数据怎么上报到监控服务)
可视化与报警(监控后台分析、日志存储、异常告警)
下面我给你出一份 详细方案(从埋点到数据上报再到后端处理):
一、整体架构
前端 SDK(埋点脚本)
集成到业务项目中(JS/TS SDK)。
负责采集:
JS 错误(
window.onerror
,window.addEventListener('error')
,unhandledrejection
)性能指标(
Performance API
、PerformanceObserver
)用户行为(
click
,hashchange
,popstate
等事件)
负责数据上报(
sendBeacon
/fetch
/img.src
)。
数据上报服务(Node.js/Go/Python)
接收 SDK 上报的日志。
存储到数据库(如 Elasticsearch、ClickHouse、MongoDB)。
提供查询/分析 API。
可视化与报警
Web 管理后台(React/Vue/Antd)展示监控指标。
Grafana/ELK/Prometheus 也可以做日志与指标可视化。
结合钉钉/企业微信/Slack 做告警。
二、前端 SDK 设计与实现
1. JS 错误监控
// 监听同步运行时错误
window.onerror = function (msg, url, line, col, error) {report({type: 'js_error',msg,url,line,col,stack: error?.stack});
};// 监听资源加载错误 (img, script, css)
window.addEventListener('error', function (e) {if (e.target && (e.target.src || e.target.href)) {report({type: 'resource_error',tagName: e.target.tagName,src: e.target.src || e.target.href});}
}, true);// 监听 Promise 未捕获异常
// 对 👍,window.addEventListener('unhandledrejection') 就是专门用来捕获 未被捕获的 Promise 异常 的。
// 在 JavaScript 中,如果你写了一个 Promise,但是没有在 链路的最后 .catch() 处理错误,浏览器就会触发一个 unhandledrejection 事件。window.addEventListener('unhandledrejection', function (e) {report({type: 'unhandledrejection',reason: e.reason});
});
2. 性能监控(Performance API)
白屏时间:从
navigationStart
到 首次 DOM 绘制(FP/FCP)。首屏时间:业务可定义,如首屏主要内容渲染完成。可通过
MutationObserver
或在业务点埋点。页面加载时间:
loadEventEnd - navigationStart
。核心 Web Vitals:
FCP
(First Contentful Paint)LCP
(Largest Contentful Paint)FID
(First Input Delay)CLS
(Cumulative Layout Shift)
示例:
function getPerformance() {const timing = performance.timing;const paint = performance.getEntriesByType('paint');const nav = timing.navigationStart;return {whiteScreen: paint.find(e => e.name === 'first-paint')?.startTime || 0,fcp: paint.find(e => e.name === 'first-contentful-paint')?.startTime || 0,load: timing.loadEventEnd - nav,domReady: timing.domContentLoadedEventEnd - nav,ttfb: timing.responseStart - nav};
}window.addEventListener('load', () => {setTimeout(() => {report({type: 'performance',data: getPerformance()});}, 3000);
});
3. 用户行为监控(可选)
路由变化监控(SPA:监听
popstate
,hashchange
)。点击行为监控(采集
click
元素路径,做埋点统计)。自定义事件埋点(开发者主动上报)。
// 路由变化
window.addEventListener('hashchange', (e) => {report({type: 'route_change',from: e.oldURL,to: e.newURL});
});
4. 数据上报机制
高优先级(报错、关键性能数据):
navigator.sendBeacon
(页面卸载前保证发送成功)。低优先级:批量
fetch
上报。兜底方案:
new Image().src = 'url?...'
。// 兼容性最好,兼容老浏览器 + 页面卸载时也能发请求
function report(data) {const url = 'https://monitor.xxx.com/report';const body = JSON.stringify({...data,userAgent: navigator.userAgent,url: location.href,timestamp: Date.now()});if (navigator.sendBeacon) {navigator.sendBeacon(url, body);} else {fetch(url, { method: 'POST', body, keepalive: true });}
}
三、后端服务(示例)
Node.js + Express + MongoDB/Elasticsearch/ClickHouse
接收上报:
app.post('/report', (req, res) => {const data = req.body;// 存储日志db.collection('logs').insertOne(data);res.json({ code: 0 });
});
定时聚合分析(统计错误率、性能指标分布)。
四、可视化与报警
指标面板(可视化框架:ECharts/Grafana):
JS 错误率(随时间趋势)
页面加载时间分布
用户地区、设备分布
异常报警:
错误率 > 1%
页面白屏时间 > 3s
LCP > 4s
→ 触发告警,推送到钉钉/企业微信。
五、优化与扩展
支持 SourceMap 解析,错误堆栈反解到源码位置。
支持 Session 关联(用户 ID、会话 ID)。
支持 前后端链路追踪(结合 Trace ID,关联后端 APM)。
支持 采样率(例如 1% 用户采集,降低服务器压力)。
📌 总结:
实现一个前端监控系统主要分 采集(前端 SDK) → 上报(sendBeacon/fetch) → 存储(DB/ES) → 分析与报警(Dashboard+告警系统) 四个环节。
你可以先做一个 轻量级 SDK + Node 后端 + Grafana 可视化 的 MVP 版本,然后逐步扩展。