项目介绍:企业级前端监控 SDK 与数据采集系统

提取词

多框架 SDK | 核心层、浏览器层、框架适配层 | 性能与异常采集 | 队列、批量发送与重试 | NestJS 数据接收 | Kafka 异步处理 | ClickHouse 存储与查询 | 系统响应性能提升 50%

指标分析、SDK 封装、SDK DSN 服务、数据统计、数据监控(可视化)

项目介绍

这个项目是一套企业级前端监控 SDK 和数据采集系统,贯通浏览器采集、批量上报、服务端接收、异步处理和数据存储查询。我直接负责 SDK 与数据采集后端的设计和实现。

业务里同时有 React、Vue 多个前端框架,所以我把 SDK 拆成核心层、浏览器层和框架适配层。核心层保留统一事件、插件机制和上传队列策略,浏览器层封装 WEB 采集能力,适配层处理框架生命周期与异常入口。再通过 TS 类型约束模块接口,新增监控项可以复用公共上报能力。

采集侧通过 PerformanceObserver 获取 FCP、LCP、CLS 等性能指标。异常覆盖全局错误、未处理的 Promise 错误、框架异常和业务主动上报,保留消息、堆栈及页面上下文,并整理成统一事件。

事件先进入本地队列,再按时间间隔、数量阈值或路由变化批量发送,结合失败重试与弱网处理减少零散请求。我使用 NestJS 实现数据接收服务,以统一事件协议承接 SDK 上报,再通过 Kafka 完成异步处理。

处理后的监控数据写入 ClickHouse,供后续存储与查询。通过打通采集、上报、接收、处理和存储链路,系统响应性能提升了 50%,不同技术栈的模块也可以复用同一套监控能力。

简历描述

企业级前端监控 SDK 与数据采集系统

  • 技术栈:TypeScript、PerformanceObserver / Web Vitals、NestJS、Kafka、ClickHouse、TypeORM、PostgreSQL、Nx + pnpm
  • 项目简介:主导构建企业级前端监控 SDK 与数据采集系统,贯通浏览器采集、批量上报、服务端处理和数据存储查询。
  • 工作内容与成果:
    • SDK 与多框架适配:按核心层、浏览器层和框架适配层组织 SDK,以统一事件和插件机制支持 React、Vue、Vanilla JS 接入。
    • 性能与异常采集:使用 PerformanceObserver / Web Vitals 采集 FCP、LCP、CLS 等指标,并统一捕获全局错误、Promise rejection 和框架异常。
    • 数据接收与异步处理:使用 NestJS 接收 SDK 上报事件,以统一协议规范数据,并通过 Kafka 完成异步处理。
    • 存储查询与性能结果:使用 ClickHouse 完成监控数据存储与查询,打通采集处理链路,使系统响应性能提升 50%。

可能追问

如何设计和实现一个高扩展性、跨框架兼容的前端监控 SDK?设计过程中需要考虑哪些关键技术点?

项目里的 React、Vue 和 Vanilla JS 模块需要复用监控能力,所以我使用 Nx + pnpm 管理多包工程,把共享逻辑和框架入口分开,组织成核心层、浏览器层和框架适配层。

核心层保留统一事件、插件接口、本地队列和 Transport;浏览器层封装 PerformanceObserver、全局异常等 Web API;框架适配层处理各自的生命周期和异常入口。浏览器采集变化时,各框架复用同一份实现,框架接入方式变化时,也主要调整对应适配包。

性能、异常和数据上报分别组织,采集能力通过插件接入。插件负责生成统一事件,队列决定何时合并发送,Transport 负责具体 HTTP 请求。新增监控项可以沿用这条链路,不必再实现一套网络发送逻辑。

TypeScript 则约束事件结构、插件入口和发送接口,让不同包按一致的类型约定协作。最终,不同技术栈既能保留自己的接入方式,也能共用采集与上报能力。

如何在前端 SDK 中高效采集和分析 Web 性能指标,并确保监控数据的准确性?

我先根据要观察的页面体验选择指标。FCP 看首次内容出现的时间,LCP 看主要内容的绘制,CLS 看布局稳定性,分别反映加载和渲染的不同方面。

采集时,通过 PerformanceObserver 监听浏览器产生的性能条目,再从 PerformanceEntry 中读取对应数据。FCP 从 paint 条目中识别首次内容绘制,LCP 关注最大内容绘制条目,CLS 处理布局偏移数据。

准确性不只是监听到了条目,还要按指标定义进行筛选、计算和聚合,不能把每一次回调都直接当成最终结果。上报时保留一致的指标名称、数值、单位和页面上下文,让不同模块的数据能够按同一口径使用。

计算完成后,将指标封装成统一事件交给本地队列,而不是每个采集模块单独发请求。队列负责批量发送,网络异常时结合重试和弱网处理,在数据实时性与页面、网络开销之间取得平衡。

在前端监控 SDK 中捕获 JavaScript 异常的常见方法有哪些?如何提高异常监控的覆盖率和准确性?

全局入口通过 window.onerror 捕获未处理的运行时错误,通过 window.onunhandledrejection 获取未处理的 Promise 拒绝,先覆盖浏览器层的异常。

取得错误后,统一整理消息和堆栈,提取来源文件、行号等定位信息,并带上页面路径和浏览器环境。这样上报的事件既说明发生了什么,也保留了后续排查需要的上下文。

框架内部异常由适配层补充:React 接入 ErrorBoundary,Vue 接入 errorHandler,再把取得的异常交给同一条上报链路。业务已经在 catch 中处理、但仍希望保留的错误,则通过 captureException 主动上报。

提高准确性时,还可以结合去重和过滤规则减少重复错误与非关键性噪声。生产代码经过压缩后,采集到的堆栈再结合对应版本的 Sourcemap 还原到源码,将异常采集和后续定位衔接起来。

上报请求数的控制如何实现?

核心是将采集和发送分开。采集插件先生成统一事件,放进本地队列,队列再按条件合并发送,不为每个指标单独发请求。

发送由三类条件触发:达到时间间隔就发送已有事件,避免低流量页面一直等待;短时间达到数量阈值时提前发送;路由切换时,将当前页面的指标整理后合并上报。

这些触发方式共用一条发送链路,具体 HTTP 请求由 Transport 执行。新增一种采集项时,直接复用现有队列,不必再维护自己的定时器和发送逻辑。

网络异常时结合失败重试与弱网处理。批量发送主要控制请求开销,重试和弱网处理补充可靠性,整体上平衡数据的实时性、网络负担和上报可靠性。

为什么在数据采集服务中选择使用 Kafka 作为消息队列?如何利用 Kafka 实现高并发数据传输和高可靠性?

Kafka 将请求接收与后续处理分开,通过消息队列衔接数据采集与异步消费。

我负责从 SDK 采集、队列上报到 NestJS 数据接收、Kafka 处理和 ClickHouse 存储的实现,通过统一事件协议贯通前后端。系统响应性能提升了 50%。

怎样处理 sourcemap 的问题?

生产代码压缩后,异常堆栈中的文件和行列号指向构建产物,直接看这些位置很难找到原始代码,所以需要 Sourcemap 把产物位置映射回源码。

我接入了生产 Sourcemap 上传与版本映射。构建时生成 Map 并上传到后台保存,让运行中上报的异常能够关联到对应版本的映射文件。

处理堆栈时,先根据构建版本匹配 Map,再通过 source-map-js 查询原始文件和行列位置。这样就能从 SDK 采集到的压缩堆栈继续定位到源码,而不是停留在一条错误消息上。