前端埋点与监控最佳实践:从基础到全流程实现.

前端埋点与监控最佳实践:从基础到全流程实现

大纲

我们会从以下三个方向来讲解埋点与监控的知识:

  • 什么是埋点?什么是监控?

  • JS 中实现监控的核心方案

  • 写一个“相对”完整的监控实例

一、什么是埋点?什么是监控?

在日常沟通中,我们经常会把【埋点】和【监控】放到一起说,但是它们在本质上是有一定的区别的:

1. 埋点

埋点主要用于收集用户行为数据。在日常开发中,我们会通过 在前端代码中插入代码或脚本的方式 来实现埋点功能。

埋点的主要作用就是:捕获特定用户行为(如点击、浏览、提交表单、页面跳转等)以及关键业务数据(如下单金额、商品类别等)

在日常开发中,埋点的实现方案大致可以分为以下三大类:

  • 手动埋点:在代码中手动加入记录代码来捕获特定事件。

  • 自动埋点:利用 DOM 事件代理等技术来捕获页面上所有事件,从而减少手动配置。

  • 可视化埋点:通过工具界面标记需要采集的元素和事件,可以不用手写代码。

2. 监控

而监控则主要关注 系统的性能和稳定性。在日常开发中,我们会通过 采集页面加载时间、资源请求、错误日志等数据 的方式来实现前端监控。

监控的主要作用就是:及时发现并定位页面性能瓶颈或代码异常,目的是为了保障系统不出 bug

在日常开发中,监控一般需要完成以下三大部分:

  • 性能监控:如:首屏加载时间、页面交互耗时、资源加载耗时等。

  • 错误监控:捕获 JavaScript 错误、网络请求失败、资源加载异常等。

  • 用户体验监控:收集白屏、卡顿等影响用户体验的问题等。

区别总结

维度前端埋点前端监控
目标捕获用户行为数据监控系统性能、错误、稳定性
数据类型用户点击、表单提交、页面跳转等页面加载时间、错误日志、卡顿情况等
实现方式手动埋点、自动埋点、可视化埋点错误捕获、性能指标采集
核心关注点用户行为、业务数据系统Bug、性能优化

二、JS 中实现监控的核心方案

根据上面所说,我们知道埋点和监控的目的存在不同,但是它们的思路确是有很多一致性的,其核心都是:获取关键的数据,发送(上报)给服务端,依据数据来解决其不同的目的。

所以,无论是埋点也好,还是监控也罢,我们都需要 获取关键位置数据

1. 跟踪用户事件(点击、滚动等)

定义通用跟踪函数(后续事件会通过该函数完成上报)trackEvent 函数接收事件类型和事件详情,并上报到服务端。

// 用于记录或发送跟踪数据到服务器的函数
function trackEvent(eventType, details) {console.log(`Event: ${eventType}`, details); // 在控制台打印事件类型和详情// 上报到服务端。fetch('/测试接口地址', { method: 'POST', body: JSON.stringify({ eventType, details }) });
}

捕获按钮点击事件:获取 id 为 myButton 的按钮,并在其 click 事件上添加监听器。在按钮被点击时调用 trackEvent 函数,记录点击事件的类型(button_click)、按钮 ID 和时间戳。

// 跟踪按钮点击事件
const button = document.getElementById('myButton'); // 获取按钮元素
button.addEventListener('click', function () {trackEvent('button_click', { buttonId: 'myButton', timestamp: Date.now() }); // 记录点击事件并添加按钮ID和时间戳
});

捕获页面滚动事件:在全局 scroll 事件上添加监听器,每当页面发生滚动时调用 trackEvent 函数,记录滚动事件的类型(page_scroll)、页面垂直滚动距离(scrollY)和时间戳。

// 跟踪页面滚动事件
window.addEventListener('scroll', function () {trackEvent('page_scroll', { scrollY: window.scrollY, timestamp: Date.now() }); // 记录滚动事件并添加滚动位置和时间戳
});

2. 完成性能监控指标

我们可以使用 PerformanceAPI,来检测某些操作需要多长时间。如:页面加载时间和 API 调用耗时的监控:

页面加载时间监控:通过 window.addEventListener('load') 监听页面加载完成的事件,在页面完全加载后获取当前时间(使用 performance.now()),计算出页面加载的总耗时(从页面初始化到加载完成的时间),并通过 trackEvent 函数将事件类型、耗时数据等记录下来。

// 测量页面加载时间
window.addEventListener('load', function () {const pageLoadTime = performance.now(); // 获取页面加载完成后的时间(毫秒)trackEvent('page_load', { duration: pageLoadTime }); // 记录页面加载事件,并包含加载耗时数据
});

API 调用耗时监控:在 measureApiCallPerformance 函数中使用 performance.now() 获取调用 API 前的开始时间,通过 fetch 方法发起网络请求并在响应返回后再次获取时间差,计算 API 请求的总耗时。将 API 耗时和接口地址等信息通过 trackEvent 函数记录下来。

// 测量 API 调用的耗时
function measureApiCallPerformance() {const start = performance.now(); // 记录 API 调用的开始时间fetch('https://api.sunday.com/data').then(response => response.json()).then(data => {const duration = performance.now() - start; // 计算 API 调用的耗时trackEvent('api_call', { duration: duration, endpoint: 'https://api.sunday.com/data' }); // 记录 API 调用事件,并包含耗时和接口地址});
}

3. 进行错误追踪监听

我们可以利用 window.onerror 回调或者直接使用一些库(如:Sentry)完成错误监听:

基础错误跟踪:通过 window.onerror 捕获全局 JavaScript 错误。当错误发生时,window.onerror 会自动获取错误的详细信息(如错误信息、文件、行号、列号及堆栈信息),并将这些信息通过 trackEvent 函数发送到后台,用于后续的错误分析和排查。

// 使用 window.onerror 实现基础的错误跟踪
window.onerror = function (message, source, lineno, colno, error) {// 捕获 JavaScript 错误信息,并通过 trackEvent 函数记录trackEvent('js_error', {message: message,      // 错误信息source: source,        // 错误发生的文件lineno: lineno,        // 错误所在的行号colno: colno,          // 错误所在的列号error: error ? error.stack : '' // 错误的堆栈信息(如果有)});
};

第三方错误跟踪服务(Sentry):Sentry 是一个常用的错误监控服务。通过 dsn 配置唯一的项目标识,之后可以使用 Sentry.captureException 方法捕获并上报自定义错误。这种方式适合用于捕获更多类型的异常并进行详细的错误分析。

// 使用第三方服务 Sentry 进行错误跟踪
Sentry.init({ dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' }); // 初始化 Sentry
Sentry.captureException(new Error('在这里描述错误内容')); // 捕获并上报自定义错误

4. 自定义的埋点上报

有时候我们可能还需要进行一些特别要求的数据上报,比如:跟踪用户在页面特定区域的停留时间,一共分成三步来做:

  1. 当用户的鼠标进入指定区域(ID 为 sectionId)时,通过 mouseenter 事件记录进入的时间戳 sectionStartTime

  2. 当用户的鼠标离开该区域时,通过 mouseleave 事件获取当前时间,计算用户在该区域的停留时长 timeSpent

  3. 将停留时间和区域标识一起通过 trackEvent 函数发送到分析系统,方便后续分析用户在页面不同区域的停留时长

// 跟踪用户在页面特定区域的停留时间
let sectionStartTime = 0; // 记录进入区域的时间
const sectionElement = document.getElementById('sectionId'); // 获取目标区域的 DOM 元素// 当用户鼠标进入该区域时触发
sectionElement.addEventListener('mouseenter', function () {sectionStartTime = Date.now(); // 记录进入区域的时间戳
});// 当用户鼠标离开该区域时触发
sectionElement.addEventListener('mouseleave', function () {const timeSpent = Date.now() - sectionStartTime; // 计算停留时间trackEvent('time_spent', { section: 'sectionId', duration: timeSpent }); // 上报停留时间和区域标识
});

5. 局部小总结

通过以上的几个案例,我们可以再次明确:监控核心就是获取关键的数据,发送(上报)给服务端

我们只需要 依照自己的需求,找到对应的 事件节点,获取 需要上报的数据,通过接口传递给服务端即可。

PS:这里需要注意的是 上报的方式分为:【统一上报】和 【实时上报】 两大类,这里不去细说。

因此,想要完成监控,那么就需要更加深入的了解关键事件节点,如:浏览器窗口事件、鼠标事件、键盘事件、表单事件 甚至是 DOM 是否可见

三、一个完整的表单监控示例

那么接下来咱们就完成一个表单监控示例。他可以监控到 浏览量、按钮点击量和表单提交量 等

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>表单行为跟踪示例</title></head><body><!-- 示例表单 --><h1>用户注册表单</h1><form id="registrationForm"><label for="username">用户名:</label><input type="text" id="username" name="username" required /><br /><br /><label for="email">邮箱:</label><input type="email" id="email" name="email" required /><br /><br /><label for="password">密码:</label><input type="password" id="password" name="password" required /><br /><br /><button type="button" id="submitButton">注册</button></form><script>// 通用跟踪函数:用于记录事件并发送到服务器function trackEvent(eventType, details) {console.log(`Event: ${eventType}`, details)// 将数据发送到分析服务fetch('/请求路径', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ eventType, details })})}// 1. 监控页面浏览量window.addEventListener('load', function () {trackEvent('page_view', {url: window.location.href,timestamp: Date.now()})})// 2. 监控输入字段聚焦事件const inputFields = document.querySelectorAll('#registrationForm input')inputFields.forEach((field) => {field.addEventListener('focus', function () {trackEvent('input_focus', {fieldName: field.name,timestamp: Date.now()})})})// 3. 监控按钮点击量const submitButton = document.getElementById('submitButton')submitButton.addEventListener('click', function () {trackEvent('button_click', {buttonId: 'submitButton',timestamp: Date.now()})// 模拟提交表单,调用表单提交处理逻辑handleSubmit()})// 4. 监控表单提交量const form = document.getElementById('registrationForm')function handleSubmit() {// 验证表单是否有效(如果需要可以增加更多验证逻辑)if (form.checkValidity()) {trackEvent('form_submit', {formId: 'registrationForm',formData: {username: form.username.value,email: form.email.value,password: form.password.value // 注意:实际场景中避免记录敏感信息},timestamp: Date.now()})// 模拟发送表单数据到服务器fetch('/请求路径', {method: 'POST',body: new FormData(form)}).then((response) => response.json()).then((data) => {console.log('Form submitted successfully', data)})} else {alert('请填写完整表单')}}</script></body>
</html>

测试执行结果如下:

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/59120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rom定制系列------红米k30_4G版澎湃os安卓13批量线刷固件

&#x1f49d;&#x1f49d;&#x1f49d;红米k30 4G版&#xff0c;机型代码;phoenix.此机型官方固件最后一版为稳定版13.0.6安卓12的固件。客户的软件需运行在至少安卓13的系统至少。测试原生适配有bug。最终测试在第三方澎湃os安卓13的固件可以完美运行。 &#x1f49d;&am…

钉钉平台开发小程序

一、下载小程序开发者工具 官网地址&#xff1a;小程序开发工具 - 钉钉开放平台 客户端类型 下载链接 MacOS x64 https://ur.alipay.com/volans-demo_MiniProgramStudio-x64.dmg MacOS arm64 https://ur.alipay.com/volans-demo_MiniProgramStudio-arm64.dmg Windows ht…

android——渐变色

1、xml的方式实现渐变色 效果图&#xff1a; xml的代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <shape xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools…

微信小程序生成二维码

目前是在开发小程序端 --> 微信小程序。然后接到需求&#xff1a;根据 form 表单填写内容生成二维码&#xff08;第一版&#xff1a;表单目前需要客户进行自己输入&#xff0c;然后点击生成按钮实时生成二维码&#xff0c;不需要向后端请求&#xff0c;不存如数据库&#xf…

rhce:web服务器

web服务器简介 服务器端&#xff1a;此处使用 nginx 提供 web 服务&#xff0c; RPM 包获取&#xff1a; http://nginx.org/packages/ /etc/nginx/ ├── conf.d #子配置文件目录 ├── default.d ├── fastcgi.conf ├── fastcgi.conf.default ├── fastcgi_params #用…

解决使用netstat查看端口显示FIN_WAIT的问题

解决使用netstat查看端口显示FIN_WAIT的问题 1. 理解`FIN_WAIT`状态2. 检查应用程序3. 检查网络延迟和稳定性4. 更新和修补系统5. 调整TCP参数6. 使用更详细的工具进行分析7. 咨询开发者或技术支持8. 定期监控和评估结论在使用 netstat查看网络连接状态时,如果发现大量连接处…

01LangChain 实战课开篇——AI奇点时刻

LangChain 实战课开篇——AI奇点时刻 课程简介 课程背景&#xff1a;随着ChatGPT和GPT-4的出现&#xff0c;AI技术与实际应用之间的距离变得前所未有的近。LangChain作为基于大模型的应用开发框架&#xff0c;为程序员提供了开发智能应用的新工具。 LangChain 概述 定义&am…

【java】java的基本程序设计结构06-运算符

运算符 一、分类 算术运算符关系运算符位运算符逻辑运算符赋值运算符其他运算符 1.1 算术运算符 操作符描述例子加法 - 相加运算符两侧的值A B 等于 30-减法 - 左操作数减去右操作数A – B 等于 -10*乘法 - 相乘操作符两侧的值A * B等于200/除法 - 左操作数除以右操作数B /…

Spring Cloud Sleuth(Micrometer Tracing +Zipkin)

分布式链路追踪 分布式链路追踪技术要解决的问题&#xff0c;分布式链路追踪&#xff08;Distributed Tracing&#xff09;&#xff0c;就是将一次分布式请求还原成调用链路&#xff0c;进行日志记录&#xff0c;性能监控并将一次分布式请求的调用情况集中展示。比如各个服务节…

关于我的编程语言——C/C++——第四篇(深入1)

&#xff08;叠甲&#xff1a;如有侵权请联系&#xff0c;内容都是自己学习的总结&#xff0c;一定不全面&#xff0c;仅当互相交流&#xff08;轻点骂&#xff09;我也只是站在巨人肩膀上的一个小卡拉米&#xff0c;已老实&#xff0c;求放过&#xff09; 字符类型介绍 char…

一台手机可以登录运营多少个TikTok账号?

很多TikTok内容创作者和商家通过运营多个账号来实现品牌曝光和产品销售&#xff0c;这种矩阵运营方式需要一定的技巧和设备成本&#xff0c;那么对于很多新手来说&#xff0c;一台手机可以登录和运营多少个TikTok账号呢&#xff1f; 一、运营TikTok账号的数量限制 TikTok的官…

DNS服务器部署

一、要求 1.搭建dns服务器能够对自定义的正向或者反向域完成数据解析查询。 2.配置从DNS服务器&#xff0c;对主dns服务器进行数据备份。 二、配置 1.搭建dns服务器能够对自定义的正向或者反向域完成数据解析查询。 &#xff08;1&#xff09;首先需要安装bind服务 &#xf…

三周精通FastAPI:28 构建更大的应用 - 多个文件

官方文档&#xff1a;https://fastapi.tiangolo.com/zh/tutorial/bigger-applications 更大的应用 - 多个文件 如果你正在开发一个应用程序或 Web API&#xff0c;很少会将所有的内容都放在一个文件中。 FastAPI 提供了一个方便的工具&#xff0c;可以在保持所有灵活性的同时…

【react使用AES对称加密的实现】

react使用AES对称加密的实现 前言使用CryptoJS库密钥存放加密方法解密方法结语 前言 项目中要求敏感信息怕被抓包泄密必须进行加密传输处理&#xff0c;普通的md5加密虽然能解决传输问题&#xff0c;但是项目中有权限的用户是需要查看数据进行查询的&#xff0c;所以就不能直接…

【STM32】INA3221三通道电压电流采集模块,HAL库

一、简单介绍 芯片的datasheet地址&#xff1a; INA3221 三通道、高侧测量、分流和总线电压监视器&#xff0c;具有兼容 I2C 和 SMBUS 的接口 datasheet (Rev. B) 笔者所使用的INA3221是淘宝买的模块 原理图 模块的三个通道的电压都是一样&#xff0c;都是POWER。这个芯片采用…

《机器人SLAM导航核心技术与实战》第1季:第10章_其他SLAM系统

视频讲解 【第1季】10.第10章_其他SLAM系统-视频讲解 【第1季】10.1.第10章_其他SLAM系统_RTABMAP算法-视频讲解 【第1季】10.2.第10章_其他SLAM系统_VINS算法-视频讲解 【第1季】10.3.第10章_其他SLAM系统_机器学习与SLAM-视频讲解 第1季&#xff1a;第10章_其他SLAM系统 …

《HelloGitHub》第 103 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…

【OJ题解】C++实现反转字符串中的每个单词

&#x1f4b5;个人主页: 起名字真南 &#x1f4b5;个人专栏:【数据结构初阶】 【C语言】 【C】 【OJ题解】 题目要求&#xff1a;给定一个字符串 s &#xff0c;你需要反转字符串中每个单词的字符顺序&#xff0c;同时仍保留空格和单词的初始顺序。 题目链接: 反转字符串中的所…

Oracle OCP认证考试考点详解082系列09

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 41. 第41题&#xff1a; 题目 41.Examine the description of the EMPLOYEES table NLS_DATE_FORMAT is set to DD-MON-YY Which query…

创建线程时传递参数给线程

在C中&#xff0c;可以使用 std::thread 来创建和管理线程&#xff0c;同时可以通过几种方式将参数传递给线程函数。这些方法包括使用值传递、引用传递和指针传递。下面将对这些方法进行详细讲解并给出相应的代码示例。 1. 值传递参数 当你创建线程并希望传递参数时&#xff…