@gomain-fe/monitor-web
v0.1.3
Published
Web error monitoring SDK (Vue/React, fetch/XHR, global errors)
Readme
前端监控 SDK 使用说明
当前只实现四项能力:前端代码错误、接口异常、自行上报异常、异常去重。
安装
Monorepo 内:
pnpm --filter @gomain-fe/monitor-web add @gomain-fe/monitor-web已发布到 npm 的外部项目:
pnpm add @gomain-fe/monitor-web
pnpm add -D @gomain-fe/monitor-plugins @gomain-fe/monitor-types发布流程见 PUBLISH.md。
createWebMonitor(config)
创建 Web 端监控实例。初始化时不监听,需调用 start() 启动。
import { createWebMonitor } from '@gomain-fe/monitor-web'
const monitor = createWebMonitor({
appId: 'huiqian-web',
dsn: '/api/monitor'
})
monitor.start()config
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| appId | string | 应用标识,必填 |
| dsn | string | 默认上报地址;未配置 transport 时必填。与 transport 二选一或同时配置(同时配置时以 transport 为准) |
| transport | (payloads: MonitorPayload[]) => void \| Promise<void> | 自定义发送函数,优先级高于 dsn,支持异步;仅配此项、不配 dsn 时合法 |
| release | string | 发布版本 |
| error | boolean | 是否启用 Web 错误监控,默认 true |
| context | Record<string, string\|number\|boolean\|null> \| (() => Record<string, string\|number\|boolean\|null> \| Promise<Record<string, string\|number\|boolean\|null>>) | 业务上下文,每次上报前获取,支持同步/异步函数 |
| limits | { maxQueueSize?: number } | 队列上限,超出丢弃最旧,默认 50 |
| vue | { app: { config: { errorHandler? } } } | Vue 应用实例,传入后自动接入 app.config.errorHandler |
返回值:MonitorInstance
| 方法/属性 | 签名 | 说明 |
| --- | --- | --- |
| start() | () => void | 启动监听,安装插件 |
| stop() | () => void | 停止监听,恢复 AOP,清理插件 |
| capture(event) | (event: MonitorEvent) => void | 上报事件,仅在 start() 后生效 |
| flush() | () => Promise<void> | 等待当前队列发送完成 |
| use(plugin) | (plugin: MonitorPlugin) => MonitorInstance | 注册插件 |
| renderReact(root, element) | (root, element) => void | 包装 React ErrorBoundary |
| config | MonitorConfig | 当前配置(只读) |
| limits | MonitorLimits | 合并默认值后的阈值(只读) |
错误类型
| type | 自动/手动 | 来源 |
| ---------------- | -------------- | ---------------------------------- |
| runtime-error | 自动 | window error 事件 |
| promise-error | 自动 | unhandledrejection 事件 |
| resource-error | 自动 | 资源加载失败(capture 阶段 error) |
| request-error | 自动 | fetch/XHR 请求失败或状态码 >= 400 |
| vue-error | 自动 | Vue app.config.errorHandler |
| react-error | 自动 | renderReact() 的 ErrorBoundary |
| caught-error | 自动(需配置) | catch 注入插件采集 |
| manual-error | 手动 | capture() 主动上报 |
| sdk-error | SDK 内部 | SDK 自身异常 |
场景
接口异常自动上报
默认开启。自动采集 fetch/XHR 请求失败(抛错或 status >= 400)。
request-error 的 extra 默认包含:
| 字段 | 说明 |
| --- | --- |
| method / url / status / statusText | HTTP 元数据 |
| queryString / params | URL 查询串及解析后的键值对(重复 key 取最后一个) |
| requestHeaders / responseHeaders | 请求/响应头(authorization、cookie、set-cookie 默认脱敏为 [Redacted]) |
| requestBody / responseBody | 请求/响应体原文(默认最多 2048 字符,FormData/Blob 等仅记类型占位) |
| responseJson | 当响应为 JSON 且可解析时附带,便于后台展示;业务错误字段名由消费方自行解读 |
可通过 requestError 配置采集范围:
createWebMonitor({
appId: 'survey-admin',
dsn: '/api/monitor',
requestError: {
captureBody: true,
captureHeaders: true,
maxBodyLength: 2048,
redactHeaders: ['authorization', 'cookie', 'set-cookie']
}
})前端代码错误自动上报
默认开启。运行时错误、Promise 未处理、资源加载失败自动采集。
monitor.start()
// 错误发生后,SDK 自动上报框架错误
// Vue:传入 app,自动接入 errorHandler
createWebMonitor({ appId: '...', dsn: '/...', vue: { app } })
// React:通过 renderReact 包装渲染入口
monitor.renderReact(root, <App />)自行上报
capture() 接收 MonitorEvent 结构,支持 toErrorEvent() 快捷归一化:
import { toErrorEvent } from '@gomain-fe/monitor-core'
// 方式一:toErrorEvent 自动处理 Error / string / unknown
monitor.capture(toErrorEvent('manual-error', new Error('错误信息')))
monitor.capture(toErrorEvent('manual-error', '字符串错误'))
monitor.capture(toErrorEvent('manual-error', someUnknownValue))
// 方式二:直接传入事件对象(仅 error 字段;SDK 解析为 message / 可选 stack 后上报,Error 本身不会打进 JSON)
monitor.capture({
type: 'manual-error',
error: caughtError,
extra: { foo: 'bar' }
})
// 业务封装(mobile 项目 @/monitor)
captureMonitorError({ error: new Error('这种'), extra: { stage: 'oauth' } })catch 注入(Vite 插件)
已在代码中被 catch 吞掉的错误不会触发全局事件。通过 Vite 插件基于 Babel AST 在编译期注入采集(非正则替换,精准操作语法树),默认关闭。注入逻辑:检查 catch 体内是否已有上报调用(有则跳过),在 catch 体首行插入 capture(),先于原有代码执行。
// vite.config.ts
import { monitorCatchPlugin } from '@gomain-fe/monitor-plugins/vite'
export default defineConfig({
plugins: [
monitorCatchPlugin({
catch: true, // 默认 false,必须显式开启
include: ['src/pages/**'], // 注入路径
exclude: ['src/pages/legacy/**'], // 排除路径
monitorVar: '__GM_MONITOR__' // 全局变量名,默认 __GM_MONITOR__
})
]
})运行时挂载实例:
window.__GM_MONITOR__ = monitor
monitor.start()自定义发送
transport 优先级高于 dsn,支持异步。配置后 SDK 不调用默认 sendBeacon:
createWebMonitor({
appId: 'huiqian-web',
transport: async payloads => {
await fetch('/custom-monitor', {
method: 'POST',
body: JSON.stringify(payloads)
})
}
})说明:
- 仅配置
transport、不配置dsn即可正常初始化(appId+transport)。 transport内部通过fetch/XMLHttpRequest上报时,不会被接口异常监控当成业务请求错误再次采集;业务代码无需额外判断或过滤上报地址。- 未配置
transport时,默认使用navigator.sendBeacon发往dsn,失败时回退到fetch(该兜底请求同样不会被误采集)。
动态上下文
每次上报前重新获取,支持静态对象或(异步)函数:
createWebMonitor({
appId: 'huiqian-web',
dsn: '/api/monitor',
context: async () => ({
userId: await fetchCurrentUser(),
route: location.pathname
})
})关闭自动错误监控
createWebMonitor({
appId: 'huiqian-web',
dsn: '/api/monitor',
error: false // 不再自动采集浏览器错误
// 但仍可手动 capture() 和 catch 注入
})自定义插件
monitor.use({
name: 'my-plugin',
setup: monitor => {
// 初始化逻辑
return () => {
// 清理逻辑,stop() 时调用
}
}
})异常去重
同一批发送前,SDK 按事件的 type、message、url、tags、extra 等字段生成指纹去重(不含 stack),相同错误在本批内只入队一次。flush() 完成后,相同错误可以再次上报。
页面卸载前刷新队列
SDK 自动在 pagehide / beforeunload 事件中调用 flush(),无需手动处理。
