我见过最“有用”的监控不是把大盘做得多漂亮,而是:线上一报错,你能在 5 分钟内回答三件事——是谁遇到了、在什么页面/什么操作遇到了、怎么复现/怎么修

这篇不讲大而全的平台选型,按“从 0 落地一套能用的前端监控”来写:错误怎么抓、性能怎么量、用户行为怎么采、数据怎么上报,以及最容易被忽略的隐私合规怎么守住底线。

前端监控的目标与意义

做监控前先把目标说清楚,不然很容易变成“什么都采一点,最后没人看”。我通常会把目标分成四类:

  • 稳定性(错误):JS 运行时错误、Promise 未捕获异常、资源加载失败……你需要能“分组 + 定位 + 追踪版本”。
  • 性能体验:首屏与交互是否顺(FCP/LCP/CLS/INP、长任务、请求耗时),以及“哪个页面/哪个接口在拖后腿”。
  • 用户路径:用户做了什么操作后触发问题(点击/跳转/停留),让排障不再靠猜。
  • 安全与合规:采集范围可控、敏感信息不落盘;必要时做脱敏、采样和权限控制。

一句话:监控的价值不在“数据多”,而在“能不能让排障更快、让质量可衡量”。


监控指标数据

错误日志收集

1. 常见错误类型

  • 运行时错误:利用 window.onerror 监听全局 JavaScript 错误。
  • Promise 错误:通过 window.onunhandledrejection 捕获未处理的 Promise 异常。
  • 资源加载错误:监听图片、脚本、样式等静态资源加载失败事件。

2. 错误捕获技术

  • 全局错误监听
    先把最基础的两类(onerror + unhandledrejection)接起来,至少做到:有 message、有 stack、有页面信息、有用户环境/版本号,方便聚合和回溯。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
window.onerror = function(message, source, lineno, colno, error) {
// 组装错误信息,调用上报函数
reportError({
message,
source,
lineno,
colno,
stack: error ? error.stack : null
});
};

window.onunhandledrejection = function(event) {
reportError({
message: event.reason && event.reason.message,
stack: event.reason && event.reason.stack
});
};

  • 异常捕获库
    如果你不想从 0 造轮子,Sentry 这类平台是很现实的选择:错误分组、SourceMap 还原、版本/环境区分、告警一套都给你准备好了。你要做的更多是“接入 + 规范字段 + 控制采样”。

性能监控

1. 浏览器性能 API

利用浏览器内置的 Performance API 可以获取精细的性能指标,例如:

  • 导航时间(Navigation Timing API):计算 DNS 查询、TCP 连接、白屏时间、DOMContentLoaded 等时间节点。
  • 资源加载(Resource Timing API):追踪各类静态资源的加载情况,定位加载瓶颈。
  • 用户感知指标:使用 Web Vitals 指标,如 FCP、LCP、TTI、CLS 等,评价页面加载和渲染质量。

2. 性能上报策略

  • 数据采集:通过定时采集和事件触发,将页面性能数据缓存到内存中。

  • 数据上报:利用 Beacon API 或自定义合并上报策略,将数据批量上报到后端,降低对用户体验的影响:

1
2
3
4
5
6
7
8
9
10
function sendPerformanceData(data) {
// sendBeacon 适合“页面要走了也得把数据送出去”的场景
const payload = JSON.stringify(data);
if (navigator.sendBeacon) {
navigator.sendBeacon('/api/performance', payload);
return;
}
fetch('/api/performance', { method: 'POST', body: payload, keepalive: true });
}

  • 数据分析与告警:结合日志平台(例如 ELK、Prometheus)构建性能监控仪表板,设置告警规则,当关键指标异常时及时通知开发和运维团队。

用户行为监控

1. 用户行为采集

  • 点击与交互记录:追踪用户点击、滑动、表单提交等关键行为,帮助还原用户操作路径。
  • 页面路径与停留时长:记录用户在各页面间的跳转以及在页面的停留时长,分析页面之间的转化率和用户粘性。

2. 实现方法

  • 事件代理:在根节点上绑定事件,通过事件委托方式采集各类用户行为,减少监听器数量,提升性能。
  • 数据上报:同样采用批量上报方式,将行为数据发送至后端或第三方分析平台(如 Google Analytics、Mixpanel),以便后续数据分析和可视化展示。

数据上报与日志处理

1. 数据上报策略

  • 实时与批量上报:根据数据重要性和网络状况,实时上报关键错误和异常,同时对性能数据和用户行为采用批量上报策略。
  • 上报优化:合并上报、采样、去重、闲时发送,别为了“监控”把用户网络和主线程拖慢。

2. 后端日志处理

  • 日志存储:将前端上报的数据存储在日志系统中(如 Elasticsearch、MongoDB),以便长期保存和查询。
  • 日志分析:利用日志聚合工具(如 Logstash、Fluentd)对数据进行实时分析、分组和告警,构建可视化监控平台(如 Kibana、Grafana)。

监控方案架构设计

监控系统架构

一个完整的前端监控系统通常包括以下几个模块:

  • 数据采集层:在客户端通过全局错误捕获、性能 API 和用户行为监听等方式采集数据。
  • 数据上报层:使用 Beacon API、XHR 或 WebSocket 将数据传输到后端服务。
  • 数据处理层:后端服务负责数据清洗、聚合和存储,构建实时分析管道。
  • 数据可视化层:借助 BI 平台或自建仪表板展示监控数据,支持图表、告警和趋势分析。

这种模块化设计使得系统具有良好的扩展性和灵活性,能够针对不同业务需求做出调整。

安全与隐私考量

监控做到最后,往往不是技术问题,而是“边界问题”。建议你尽早把这些规则写进代码里:

  • 默认不采集用户输入:表单内容、搜索词、手机号邮箱这些,能不采就不采;要采也先脱敏。
  • 标识要可控:用户 ID/设备 ID 做哈希或匿名化;别把完整 cookie/token 带上报文。
  • 按需采样:错误可以全量(但要做限流),行为/性能一般都要采样,不然成本和噪音会爆炸。
  • 权限与留存:谁能看、留多久、怎么删,提前约定清楚。

工具和平台推荐

  • 错误监控:Sentry、LogRocket、Raygun
  • 性能监控:Google Analytics、NewRelic Browser、SpeedCurve
  • 用户行为监控:Mixpanel、Hotjar、Google Analytics
  • 日志聚合与分析:ELK Stack(Elasticsearch、Logstash、Kibana)、Grafana、Prometheus

这些工具大多提供丰富的 API 和插件支持,能快速集成到项目中,为前端监控方案提供全方位支持。

实践案例与代码示例

1. 捕获 JavaScript 错误示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function reportError(errorData) {
// 这里用 sendBeacon 是为了“页面关闭/跳转”时也尽量把错误送出去
const payload = JSON.stringify(errorData);
if (navigator.sendBeacon) {
navigator.sendBeacon('/api/reportError', payload);
return;
}
fetch('/api/reportError', { method: 'POST', body: payload, keepalive: true });
}

window.onerror = function(message, source, lineno, colno, error) {
reportError({
type: 'js_error',
message,
source,
lineno,
colno,
stack: error ? error.stack : null,
timestamp: Date.now()
});
};

window.onunhandledrejection = function(event) {
reportError({
type: 'promise_error',
message: event.reason ? event.reason.message : 'Unhandled Rejection',
stack: event.reason ? event.reason.stack : null,
timestamp: Date.now()
});
};

2. 性能数据采集示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
window.addEventListener("load", () => {
// performance.timing 已逐步被更现代的 PerformanceNavigationTiming 替代,这里做个兼容写法
const nav = performance.getEntriesByType('navigation')[0];
const timing = window.performance.timing;
const navigationStart = timing?.navigationStart || performance.timeOrigin;
const data = {
navigationStart,
domContentLoadedEventEnd: nav
? Math.round(performance.timeOrigin + nav.domContentLoadedEventEnd)
: timing.domContentLoadedEventEnd,
loadEventEnd: nav
? Math.round(performance.timeOrigin + nav.loadEventEnd)
: timing.loadEventEnd,
timestamp: Date.now(),
};
navigator.sendBeacon("/api/reportPerformance", JSON.stringify(data));
});

总结

前端监控真正想要的不是“我有很多指标”,而是一个排障闭环:

  1. 出了问题能被抓到(采集)
  2. 抓到之后能稳定送到后端(上报)
  3. 到了后端能聚合、能过滤噪音(处理)
  4. 最后能把问题指向一个可行动的结论(定位/告警/复盘)

把这个闭环跑起来,你会发现很多“玄学线上问题”会变得很具体:在哪个版本、哪个页面、哪个操作、哪个接口。剩下的就是工程纪律了:字段统一、采样可控、隐私底线不碰。

Happy Monitoring!