性能监控
前端项目的整体稳定性是怎么保证的?
- 稳定性,要站在Leader 角度,做了贡献
- 性能采集、异常采集、用户行为埋点SDK开发
- 数据上报协议
- 数据统计清洗与加工
- 可视化
异常和性能的监控SDK内核如何实现?
- 重点介绍SDK实现细节
- 性能、异常指标设计
- 上报逻辑,图片、sendbacon、fet&h
- 用户自定义指标数据
性能指标
核心性能
加载性能 | 全称 | 描述 |
---|---|---|
FP | First Paint 首次绘制 | 页面任意像素被渲染所花费的时间 |
FCP | First Contentful Paint 首次内容绘制 | 页面开始渲染任何文本、图片、svg的时间 |
LCP | Largest Contentful Paint 最大内容绘制 | 页面中最大的文本或图片元素渲染完成的时间 |
TTFB | Time to First Byte 首字节时间 | 浏览器发送请求到收到第一个字节的时间 |
交互性能 | 全称 | 描述 | 理想值 |
---|---|---|---|
INP | Interaction to Next Paint 交互到下一次绘制 | 用户交互(如点击按钮) 到界面响应的时间 | |
TBT | Total Blocking Time 总阻塞时间 | 从 FCP 到 之间 主线程被阻塞的时间总和 | |
CLS | Cumulative Layout Shift 累计布局偏移 | 页面意外的布局移动得分 影响用户体验 | |
TTI | Time to Interactive |
补充性能 | 定义 |
---|---|
DNS 查询时间 | 从发起请求到 DNS 查询完成的时间 |
资源加载时间 | 所有静态资源(如图片、CSS、JS)的下载时长 |
长任务 (Long Task) | 主线程运行超过 50ms 的任务 |
performance 性能
js
performance = {
"timeOrigin": 1756781433903.2,
"timing": {
"connectStart": 1756781433904,
"secureConnectionStart": 0,
"unloadEventEnd": 1756781433937,
"domainLookupStart": 1756781433904,
"domainLookupEnd": 1756781433904,
"responseStart": 1756781433924,
"connectEnd": 1756781433904,
"responseEnd": 1756781433932,
"requestStart": 1756781433915,
"domLoading": 1756781433941,
"redirectStart": 0,
"loadEventEnd": 1756781434694,
"domComplete": 1756781434693,
"navigationStart": 1756781433903,
"loadEventStart": 1756781434694,
"domContentLoadedEventEnd": 1756781434671,
"unloadEventStart": 1756781433937,
"redirectEnd": 0,
"domInteractive": 1756781434123,
"fetchStart": 1756781433904,
"domContentLoadedEventStart": 1756781434671
},
"navigation": {
"type": 1,
"redirectCount": 0
}
}
异常指标及其监控
运行时异常
采用window.onerror监听,代码如下,此时我输出一个未定义的变量,查看捕获的异常
js
window.onerror = function (msg, source, line, col, error) {
const {name, message, stack} = error;
console.log({
'错误信息': msg,
'错误文件': source,
'错误行号': line,
'错误列号': col,
'错误对象': {
name,
message,
stack
}
});
return true;
};
error 异常结果
js
let error = {
'错误信息': 'Uncaught ReferenceError: a is not defined',
'错误文件': 'http://localhost:3001/web-vite-vue3/src/pages/main.vue?t=1756783123513',
'错误行号': 23,
'错误列号': 34,
'错误对象': {}
};
promise reject异常
js
window.addEventListener('unhandledrejection', function (e) {
console.log('Promise 错误:', e.reason);
});
请求异常
重写fetch
js
const originFetch = window.fetch;
window.fetch = function (...args) {
return originFetch(...args).then((response) => {
if (!response.ok) {
throw new Error('请求异常', response.status);
}
return response;
});
};
资源加载异常
js
window.addEventListener('error', function (e) {
if (e.target != window) {
console.log('静态资源错误:', e);
}
});
用户行为埋点
- 无痕埋点(事件冒泡和捕获)
- 可视化埋点
- 手动埋点
捕获所有的点击事件的链路xPath
js
window.onclick = (e) => {
const {target} = e;
console.dir('target', target);
const paths = e.path || e.composedPath();
const xPath = paths.map(item => item.tagName).join('/');
console.log('xPath', xPath);
};
数据上报
- image上报
- fetch请求上报
- sendBeacon上报
js
const baseUrl = 'http://localhost:3001/api/report';
const reportMessage = (message) => {
const img = new Image();
img.src = `${baseUrl}?message=${message}`;
};
完整开发流程
docker容器编排
如果你是windows电脑,先安装docker desktop ,下载安装之后一直下一步,完整完成之后重启电脑。项目地址在GitHub
创建docker-compose.yml文件,内容如下:用到了kafka和clickhouse
yml
version: '1'
services:
modify-kafka:
image: bitnami/kafka:3.9.0
container_name: modify-kafka
ports:
- "9092:9092"
- "9093:9093"
environment:
- KAFKA_CFG_NODE_ID=1
- KAFKA_CFG_PROCESS_ROLES=broker,controller
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@modify-kafka:9093
- KAFKA_CFG_LISTENERS=PLAINTEXT://modify-kafka:9092,CONTROLLER://modify-kafka:9093
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT
- ALLOW_PLAINTEXT_LISTENER=true
modify-clickhouse:
image: bitnami/clickhouse:25.3.1
container_name: modify-clickhouse
ports:
- "8123:8123"
- "9000:9000"
environment:
- CLICKHOUSE_DB=default
- CLICKHOUSE_USER=default
- CLICKHOUSE_PASSWORD=default
networks:
default:
name: modify-network
driver: bridge
补充:技术选型 kafka + clickhouse
kafka是一个高吞吐、分布式、可持久化的消息队列系统,非常适合埋点这类高并发、低延迟、高可靠的数据采集场景
- ✅ 优势:
- 高吞吐量:每秒可处理百万级消息,适合埋点这种高频小数据包场景
- 持久化与可靠性:数据写入磁盘,支持副本机制,保证不丢失
- 解耦生产者与消费者:前端/日志服务只需把数据丢进 Kafka,后端可以异步消费处理
- 支持多消费者组:不同业务系统(如实时分析、离线数仓、监控告警)可以同时消费同一份数据
- 削峰填谷:前端埋点流量可能突发(如大促),Kafka 可以缓冲流量,避免后端服务被打垮
- ❌ 劣势:
- 需要维护集群(不过现在有云服务如 Confluent、阿里云 Kafka 等)
- 不适合复杂查询或直接分析
ClickHouse 是一个列式存储、面向 OLAP(在线分析处理)的数据库,特别适合对海量数据做快速聚合查询
- ✅ 优势:
- 极快的查询性能:对聚合查询(如 UV、PV、留存、漏斗)响应速度极快(秒级甚至毫秒级)
- 高压缩比:列式存储 + 高效压缩算法,节省存储成本
- 高吞吐写入:适合批量写入埋点数据(通过 Kafka 消费写入)
- 适合宽表设计:可将用户属性、事件属性打平成宽表,便于分析
- 支持实时分析:数据写入后几乎可立即查询,适合实时看板
- ❌ 劣势:
- 不支持事务和更新(适合 append-only 场景)
- 不适合高并发点查(如单条用户记录查询)
- 数据更新/删除成本高(但埋点场景通常不需要修改历史数据)
服务启动与停止
通过docker-compose
启动与停止,其中-f
指定配置文件,-p
指定项目名
json
{
"scripts": {
"docker:start": "docker-compose -f build/docker-compose.yml up -d",
"docker:stop": "docker-compose -f build/docker-compose.yml down",
"docker:start:group": "docker-compose -f build/docker-compose.yml -p tracking-point up -d",
"docker:stop:group": "docker-compose -f build/docker-compose.yml -p tracking-point down"
}
}
测试连接
在webstrom
当中下载一个kafka
插件,安装完成后重启,在views->Tool Windows -> Kafka
,直接通过localhost:9092
进行测试连接
clickhouse
用数据库连接工具测试连接即可。