前端错误监听与上报框架工作原理,如:Sentry
文章目录
- 前言
- 🔧 一、核心监听方式(浏览器层)
- 1. 拦截同步错误:`window.onerror`
- 2. 拦截异步错误:`window.addEventListener('unhandledrejection')`
- 3. 覆写全局 API:如 `console.error`、`XMLHttpRequest.prototype.send`
- ⚙️ 二、框架适配层(Vue/React/Angular)
- Vue 示例(Vue 2 / Vue 3)
- React 示例(ErrorBoundary)
- 🧪 三、错误信息序列化 & 上报
- 错误标准格式:
- 上报方式:
- 🔄 四、额外能力(增强稳定性与分析能力)
- 1. Source Map 支持
- 2. Breadcrumbs(用户行为轨迹)
- 3. 采样与过滤
- 📦 五、Sentry SDK 封装架构简要流程
- ✅ 总结一句话:
- 🧩 一、前端 SDK 最小实现
- 📁 文件结构
- 🔧 `error-sdk.js`
- 🧪 二、模拟错误触发(`index.html`)
- 🧰 三、后端错误日志接收(Node.js + Express)
- 📁 文件结构
- 🔧 `index.js`
- 📈 四、运行方式(测试用)
- 🚀 五、进阶扩展建议
- ✅ 总结
- Vue 3 错误查看平台
- 🧱 一、项目结构概览(Vue 3 + Vite)
- 🚀 二、主要技术点实现
- 1. 获取错误日志列表(支持时间过滤)
- 2. 日志聚类(前端聚类示例)
- 3. 时间过滤 UI 示例
- 4. 日志卡片组件(堆栈、行为轨迹回放)
- 5. 主视图:分页+聚类展示
- 📦 三、运行环境和后端配合
- 后端 `/api/logs` 响应格式:
- ✅ 四、进一步可扩展能力
前言
像 Sentry 这样的前端错误监听与上报框架,其核心是通过劫持浏览器原生错误处理机制,并拦截框架生命周期中的异常,最终将错误信息序列化后发送到后端进行归档与聚合。
以下是它的底层工作原理剖析:
🔧 一、核心监听方式(浏览器层)
1. 拦截同步错误:window.onerror
window.onerror = function (message, source, lineno, colno, error) { // 捕获运行时错误(语法/引用错误等) sendToServer({ message, source, lineno, colno, stack: error?.stack }); };
作用:
- 捕获未被 try/catch 包裹的错误
- 包含错误信息、脚本来源、行列号、错误堆栈
2. 拦截异步错误:window.addEventListener('unhandledrejection')
了解更多 :unhandledrejection | Web api MDN
window.addEventListener("unhandledrejection", event => { const reason = event.reason; sendToServer({ type: 'PromiseError', reason }); });
作用:
- 捕获未处理的 Promise 错误
- 包括 fetch(...).then().then() 链中报错但未 .catch() 的情况
3. 覆写全局 API:如 console.error、XMLHttpRequest.prototype.send
部分监控库还会:
- 重写 console.error,记录开发者手动抛出的信息
- Hook fetch / XMLHttpRequest 以监听请求失败
⚙️ 二、框架适配层(Vue/React/Angular)
Vue 示例(Vue 2 / Vue 3)
Vue.config.errorHandler = (err, vm, info) => { sendToServer({ message: err.message, stack: err.stack, component: vm.$options.name || '(anonymous)', info }); };
- Vue 把组件渲染和事件处理等错误暴露给 errorHandler
- Sentry 会自动注册这个钩子进行错误接管
React 示例(ErrorBoundary)
class ErrorBoundary extends React.Component { componentDidCatch(error, info) { sendToServer({ error, info }); } ... }
- React 17+ 推荐使用 ErrorBoundary 组件包裹所有 UI 节点
- Sentry 提供开箱即用的 withErrorBoundary 高阶组件
🧪 三、错误信息序列化 & 上报
错误标准格式:
{ "message": "Cannot read property 'x' of undefined", "type": "TypeError", "stack": "at Object. (main.js:10:15)", "timestamp": 1684453410000, "browser": "Chrome 113", "userAgent": "...", "url": "https://xxx.com/page", "breadcrumbs": [...], // 用户行为轨迹 "extra": {...} }
上报方式:
- Sentry 使用beacon / fetch / xhr等方式发送错误日志到后端
- 示例:
navigator.sendBeacon('/api/log', JSON.stringify(error));
- Sentry SDK 支持异步缓冲、重试、采样率控制等机制
🔄 四、额外能力(增强稳定性与分析能力)
1. Source Map 支持
- Sentry 可上传构建时生成的 .map 文件
- 将压缩代码中的错误还原为源码中的具体文件、行号、方法名等
2. Breadcrumbs(用户行为轨迹)
- 自动记录用户行为链,如点击、输入、页面跳转、XHR 请求等
- 每条错误日志都会带一份"历史行为快照"
3. 采样与过滤
- 默认并不记录所有错误,防止高频错误占满带宽
- 可配置采样比例(如 10% 上报)、忽略特定错误类型或路径
📦 五、Sentry SDK 封装架构简要流程
浏览器/框架异常 ↓ 捕获器(window.onerror / unhandledrejection / Vue.errorHandler 等) ↓ 中间层(格式标准化 + 过滤 + 日志构造) ↓ 缓冲池(采样 + 批量 + 异步) ↓ HTTP 上报(beacon/fetch/XHR) ↓ Sentry 服务端聚合处理
✅ 总结一句话:
Sentry 的底层是基于浏览器和框架提供的全局异常钩子,结合源码映射、用户行为追踪和智能采样,完成完整的“采集→转化→上报→可视化”流程。
下面是一个最小可用的“类 Sentry 前端错误上报系统”示例,包括:
- ✅ 前端 SDK(监听、采集、上报)
- ✅ 后端服务(接收、保存、可视化展示)
- ✅ 进阶扩展建议(sourceMap、用户行为轨迹、异常采样)
🧩 一、前端 SDK 最小实现
📁 文件结构
/client/ ├── index.html ├── error-sdk.js ← 错误监听与上报逻辑
🔧 error-sdk.js
(function () { const endpoint = 'https://your-server.com/api/log'; function report(error) { const payload = { message: error.message || error, type: error.name || 'UnknownError', stack: error.stack || '', url: location.href, userAgent: navigator.userAgent, time: Date.now() }; navigator.sendBeacon(endpoint, JSON.stringify(payload)); } // 捕获同步错误 window.onerror = function (msg, src, line, col, err) { report(err || msg); }; // 捕获 Promise 错误 window.addEventListener('unhandledrejection', event => { report(event.reason); }); // 封装为全局对象供外部手动调用 window.$ErrorSDK = { capture: report }; })();
🧪 二、模拟错误触发(index.html)
Test Error
点击按钮触发错误
抛错🧰 三、后端错误日志接收(Node.js + Express)
📁 文件结构
/server/ ├── index.js ← 主服务 ├── db.json ← 模拟数据库
🔧 index.js
const express = require('express'); const fs = require('fs'); const app = express(); const logs = []; app.use(express.json({ limit: '1mb' })); app.use(express.static(__dirname + '/public')); app.post('/api/log', (req, res) => { let raw = ''; req.on('data', chunk => (raw += chunk)); req.on('end', () => { try { const log = JSON.parse(raw); logs.push(log); fs.writeFileSync('db.json', JSON.stringify(logs, null, 2)); res.sendStatus(204); } catch { res.sendStatus(400); } }); }); // 简单页面查看日志 app.get('/logs', (req, res) => { const data = fs.readFileSync('db.json', 'utf-8'); res.send(`
${data}
`); }); app.listen(3000, () => { console.log('🚀 Error log server running on http://localhost:3000'); });📈 四、运行方式(测试用)
-
安装依赖:
npm install express
-
启动后端服务:
node index.js
-
打开 client/index.html,点击按钮模拟异常
-
浏览器访问 http://localhost:3000/logs 查看错误信息
🚀 五、进阶扩展建议
功能 建议实现方式 source map 解析 使用 Sentry CLI 或 source-map npm 包 用户行为 Breadcrumb 记录点击、跳转、输入事件至数组 window.$SDK.track(event) 并附加上报 请求异常采集 Hook XMLHttpRequest 与 fetch,记录失败请求 错误去重与采样 哈希 message+stack 内容并设置 TTL;使用采样率避免刷爆日志 多端接入支持 提供 init({ appKey }) 和上传接口文档,兼容 React/Vue 数据持久化 使用 SQLite / MongoDB / Elasticsearch 替代 db.json 面板可视化 使用 Vue3/React + ECharts 可视化报错趋势、影响用户数等指标 ✅ 总结
你现在已经拥有了一个:
- ✨ 监听错误、捕获堆栈、上报后端的前端 SDK
- 🧾 可接收并持久化日志的 Node 后端
- 📊 简单的错误列表 UI 页面
这就是最小版 Sentry 的工作模型。
Vue 3 错误查看平台
功能包括:
- ✅ 错误列表展示(分页 / 时间过滤)
- ✅ 错误聚类(按 message+stack 聚类)
- ✅ 堆栈信息展开查看
- ✅ 行为轨迹回放(breadcrumbs)
- ✅ 基于 Element Plus 组件库 + Pinia 状态管理(可选)
🧱 一、项目结构概览(Vue 3 + Vite)
error-dashboard/ ├── public/ ├── src/ │ ├── api/ ← 接口调用 │ ├── components/ ← UI 组件(日志卡片、时间过滤等) │ ├── views/ ← 页面(ErrorList.vue) │ ├── App.vue │ └── main.ts ├── index.html ├── vite.config.ts
🚀 二、主要技术点实现
1. 获取错误日志列表(支持时间过滤)
// src/api/error.ts import axios from 'axios'; export interface ErrorLog { id: string; message: string; stack: string; type: string; time: number; url: string; userAgent: string; breadcrumbs: string[]; } export const getErrorLogs = (params: { startTime?: number; endTime?: number }) => axios.get('/api/logs', { params });
2. 日志聚类(前端聚类示例)
// 简化版聚类函数:根据 message + stack 做分组 export function clusterLogs(logs: ErrorLog[]) { const map = new Map(); logs.forEach(log => { const key = log.message + log.stack?.split('\n')[0]; // 可加 hash if (!map.has(key)) map.set(key, []); map.get(key)!.push(log); }); return [...map.entries()].map(([key, group]) => ({ key, count: group.length, latest: group.sort((a, b) => b.time - a.time)[0], samples: group })); }
3. 时间过滤 UI 示例
import { ref } from 'vue'; const emit = defineEmits(['filter']); const range = ref([]); function emitFilter() { if (range.value.length === 2) { emit('filter', { startTime: new Date(range.value[0]).getTime(), endTime: new Date(range.value[1]).getTime() }); } }
4. 日志卡片组件(堆栈、行为轨迹回放)
{{ log.message }} {{ log.type }}{{ new Date(log.time).toLocaleString() }}查看堆栈 行为轨迹{{ log.stack }}
- {{ b }}
5. 主视图:分页+聚类展示
共 {{ group.count }} 次import { ref, onMounted } from 'vue'; import { getErrorLogs } from '@/api/error'; import { clusterLogs } from '@/utils/cluster'; import ErrorCard from '@/components/ErrorCard.vue'; import TimeFilter from '@/components/TimeFilter.vue'; const logs = ref([]); const clusters = ref([]); async function fetchLogs(params = {}) { const res = await getErrorLogs(params); logs.value = res.data; clusters.value = clusterLogs(logs.value); } function onFilter(params) { fetchLogs(params); } onMounted(() => fetchLogs());📦 三、运行环境和后端配合
后端 /api/logs 响应格式:
[ { "id": "uuid", "message": "Uncaught TypeError: Cannot read property 'x'", "stack": "at main.js:1:123", "type": "TypeError", "time": 1684928000000, "url": "https://xxx.com/page", "userAgent": "...", "breadcrumbs": ["click button", "fetch /api/user fail", ...] } ]
✅ 四、进一步可扩展能力
功能 实现方式建议 搜索 / 排序 加入输入框 + 下拉框(Element UI Table 支持) 权限访问 登录鉴权 + token 验证 图表展示错误趋势 Vue + ECharts 绘制 bar/line 图 map 映射源码 后端集成 source-map npm 包,转堆栈回原文件 行为轨迹可视化 类似 DevTools 的 Timeline,做 step-by-step 回放
- Sentry SDK 支持异步缓冲、重试、采样率控制等机制
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。