浅谈前端埋点&监控 https://www.zoo.team/article/monitor
在开始正文之前,我们先想想为什么需要埋点&监控?
当我们在分析复盘一个产品是否成功的时候,不同的角色考虑的方向是不同的。
站在产品的视角,经常会问如下几个问题:
1. 产品有没有用户使用
2. 用户用得怎么样
3. 系统会不会经常出现异常
4. 如何更好地满足用户需求服务用户
当站在技术视角时,经常会问如下几个问题:
1. 系统出现异常的频率如何
2. 异常出现后如何快速进行定位追踪
3. 如何分析解决问题
而当站在老板的视角时,问题可能又会变为:
1. 我的存量用户多少,未来还有多少潜力
2. 多少用户在系统内进行了消费
当在回答了上述问题之后,埋点&监控便跃然纸上。因为要回答以上问题,只有通过对系统进行数据分析的方式才能弄清楚。
其实无论是埋点亦或是监控,二者并不是独立存在,而是相互依存的关系。
从单个页面的常规数据角度出发我们可以通过埋点获取:访问次数(UV/PV)、地域数据(IP)、在线时长、区域点击次数等数据。
当我们将这些单点数据按照特定的纬度进行数据聚合,就可以获得全流程视角下的数据如:用户留存率/流转率、用户转化率、用户访问深度等数据。
而在埋点数据进行上报的同时,我们也可以同步收集页面基础数据/接口相关数据如:页面加载/渲染时长、页面异常、请求接口等数据。
同时对于前端监控来说,大致可以分成三个方向:数据监控、性能监控、异常监控。
数据监控即通过数据分析用户行为,常见的监控数据包括:PV/UV、页面停留时长、通过什么入口进入、在页面触发了什么行为等。统计这些数据就是为了清楚用户来源,拓宽产品的推广渠道;了解用户在页面停留的时间情况,针对停留较短的页面进行分析改进。也就是我们常说的:who(uuid)、when(time)、from where(referrer)、where(x,y)、what (自定义拓展数据)串成的用户行为路径。
性能监控主要是针对前端进行监控,比如不同用户在不同地区使用不同机型下的首屏加载时间、页面的白屏时间、静态资源下载时间等数据。通过针对这些性能数据进行监控,可以大概反映前端性能的好坏,根据性能监测的结果可以进一步的去优化前端性能。
前端代码在执行过程中也可能会发生异常,因此需要引入异常监控例如 sentry 等工具及时的上报异常情况,可以避免线上故障的发上。常见的异常包括:Javascript 的异常监控、css 的异常监控等。
目前公司已经存在一套埋点 SDK 在运行,使用的是代码埋点方案,其埋点上报数据可大致分为三类:页面进入、事件触发、页面离开。
(1) 页面进入 (pageIn)
进入页面时,同步推送页面基础信息如:当前页面的来源页面、操作系统、浏览器、页面 url,发生时间等
{
title: '政采云', // document title
pre: '', // referrer
utm-url: 'a.b.c.d.e', // url 中获取的 utm
utm-cnt: 'a.b.0.0.e', // 这个页面的 utm a b 值
scr: '1400x900', // 分辨率
os: 'mac', // 操作系统
k: 'webkit', // 浏览器内核
b: 'chrome/70', // 浏览器及版本
lver: '1.0.0', // js 版本
createTime: '', // 当前时间的时间戳(用户本地时间)
logType: 1 // 页面进入发送数据
}
(2) 事件触发 (Event)
触发事件时,同步推送事件类型 (click、hover 等)、鼠标位置、附加业务参数等
{
evt: 'click', // 事件类型
utm-cnt: 'a.b.c.d.e', // utm 值
bdata: '{"test": "12345" }', // 业务数据
mx: xx, // 鼠标点击位置 x
my: xx, // 鼠标点击位置 y
lver: '1.0.0', // js 版本
logType: 2 // 数据类型
}
(3) 页面离开 (pageOut)
离开页面时,同步推送发生时间、页面 url 等
{
title: '政采云', // document title
pre: '', // referrer
utm-url: 'a.b.c.d.e', // url 中获取的 utm
utm-cnt: 'a.b.0.0.e', // 这个页面的 utm a b 值
lver: '1.0.0', // js 版本
createTime: '', // 当前时间的时间戳(用户本地时间)
logType: 3 // 页面离开发送数据
}
其埋点大致逻辑如下图,通过生成独有的四段值 +pvid 即可定位某个项目的某个页面在某个区块点击了某个按钮,同时生成唯一的 pvid 记录页面的 pv 数据。具体说明可翻阅往期关于政采云埋点分析系统的文章:前端工程实践之数据埋点分析系统(一)。前端搞监控|如何实现用户行为的动态采集与分析 (https://juejin.cn/post/6844904161566261256)
在现有 SDK 的基础上我们可以发现,目前的埋点 SDK 只上报了一些用户的基础信息数据,在性能数据和异常数据的上报上还存在可拓展的空间。
(1) 性能数据上报
在获取用户基础数据的同时,后续可以通过 window.performance
API 获取前端性能数据,在第一次进入页面时随 pageIn 一起将页面初始性能数据进行上报。
可进行上报的字段包含如下:
const getPerformanceData = () => {
let performance = {};
try {
performance = window.performance.getEntries()[0];
} catch (e) {}
const {
domainLookupEnd = 0,
domainLookupStart = 0,
connectStart = 0,
connectEnd = 0,
requestStart = 0,
responseStart = 0,
// etc...
} = performance;
const dns = ~~(domainLookupEnd - domainLookupStart);
const tcp = ~~(connectEnd - connectStart);
const ttfb = ~~(responseStart - requestStart);
// etc...
return {
// TODO...
};
};
(2) 接口数据上报
除了上报性能数据外,我们也可将页面内所发的所有请求通过重写 XMLHttpRequest
进行劫持打标上报,即在当前页面下的所有请求 header 上默认加上当前页面 ID,将各个请求与当前页面的 pageId 进行绑定。
通过该类数据可以进行统计分析出某一页面的请求量、请求异常等情况判断出页面级别的请求健康度;后期甚至可与 Yapi 接口系统打通,若出现异常情况可直接将实际请求参数与文档上的请求参数进行对比,排除异常是由于请求参数错误造成的。
let req = XMLHttpRequest;
(function(open, send) {
// TODO...
XMLHttpRequest.prototype.open = function() {
open.apply(this, arguments);
}
// TODO...
XMLHttpRequest.prototype.send = function () {
this.setRequestHeader('XXXXX', 'XXX')
send.apply(this, arguments);
}
})(req.prototype.open, XMLHttpRequest.prototype.send)
对于已经采集上来的数据经由数仓清洗之后的可视化玩法就千变万化了。可以针对不同元数据按不同指标纬度聚合,产生不同的数据分析侧重点。再通过各类可视化工具进行展示,例如:浑仪系统、小采BI等。
浑仪系统(内部系统)主要针对埋点进行元数据后台管理,推进埋点平台的规范化建设。同时在此基础上,优化数据分析功能,为公司内部用户提供埋点数据自助分析平台,提升数据利用率和日常工作效率。
小采 BI 是可视化团队内部搭建系统,分为报表搭建、大屏搭建和看板搭建等模块。通过内部这些搭建工具直接对元数据进行展示,组合成面向不同受众、不同角色的自定义数据报表或监控大屏等。
本文只是针对埋点系统和监控系统的融合的一点简单的介绍与探索,实际操作落地上肯定会有各种问题。比如多端情况下的数据埋点&上报,比如手动埋点增加了工作量破坏了原有代码的可读性等一系列实操上的问题,这些都需要逐步完善优化,同时我们也希望各位读者提出自己意见和建议,一起完善埋点&监控的大生态。