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

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

大纲

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

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

  • 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>

测试执行结果如下:

图片

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电能质量治理产品在分布式光伏电站的应用

1.概述 随着全球对可再生能源需求的不断增长&#xff0c;分布式光伏电站的建设与扩张正迅速发展。然而&#xff0c;在其运行过程中&#xff0c;分布式光伏电站遭遇了一系列挑战&#xff0c;包括企业关口计量点功率因数降低和谐波污染等问题。这些问题不仅影响了光伏电站的运行…

遥感图像Trento原始数据集下载

遥感图像Trento原始数据集下载 偶然间在某个项目里发现了Trento的完整数据集&#xff0c;不过那个数据集有些奇怪的小改动 虽然我已经不做遥感方向了&#xff0c;不过当初我找这个数据集也是花了很长时间 于是重新整理了一下&#xff0c;就当是方便后来的研究者使用吧 githu…

GenAI 生态系统现状:不止大语言模型和向量数据库

自 20 个月前 ChatGPT 革命性的推出以来&#xff0c;生成式人工智能&#xff08;GenAI&#xff09;领域经历了显著的发展和创新。最初&#xff0c;大语言模型&#xff08;LLMs&#xff09;和向量数据库吸引了最多的关注。然而&#xff0c;GenAI 生态系统远不止这两个部分&#…

个人应用接入使用阿里云盘和百度网盘

一、阿里云盘 官方文档接入流程 语雀流程概述服务端 API 调用流程如下图所示1. 创建账...https://www.yuque.com/aliyundrive/zpfszx/btw0tw 1. 接入授权 1.1. App Key、App Secret和用户授权验证 在通过网盘开发者认证之后&#xff0c;创建个人应用会生成APP ID&#xff…

医院信息化与智能化系统(15)

医院信息化与智能化系统(15) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应…

从比亚迪超越特斯拉,看颠覆全球市场的中国力量

这是比亚迪CEO王传福早年在日本调研电池供应链时发出的感慨。 那时的人们谁也没有想到&#xff0c;比亚迪会从深圳的一家普通的电池供应商开始做起&#xff0c;拼出一条属于自己的“血路”&#xff0c;摇身一变成为名副其实的“电车之王”&#xff0c;并让全球车企仰望。 比亚…

3d 添加辅助坐标器和轨道控制器

1.添加辅助坐标器 使用AxesHelper类来添加坐标轴辅助器&#xff0c;辅助器简单模拟3个坐标轴的对象。红色代表X轴&#xff0c;绿色代表Y轴&#xff0c;蓝色代表Z轴。 // 创建坐标轴辅助器&#xff0c;5是坐标轴的长度 const axesHelper new THREE.AxesHelper(5); // 将坐标轴…

「C/C++」C++标准库之#include<fstream>文件流

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

计算机后台服务-更新下载,重启————未来之窗行业应用跨平台架构

一在教育中应用 1. 提高效率&#xff1a;能够快速收集大量学生的卷子&#xff0c;节省了传统人工收集和整理的时间。 2. 准确性&#xff1a;减少了人工收卷过程中可能出现的错漏和混乱&#xff0c;确保每份卷子都能准确无误地被收集和记录。 3. 即时性&#xff1a;可以实时接收…

奥数与C++小学四年级(第十八题 小球重量)

参考程序代码&#xff1a; #include <iostream> #include <vector>int main() {// 小球的重量std::vector<int> weights {1, 2, 3, 4, 5};// 用来存储可能的结果int a, b, c, d, e, x;// 穷举所有可能的 a, b, c, d, e 的组合for (int i 0; i < weight…

Android启动流程_Init阶段

前言 本文将会介绍 Android 启动流程&#xff0c;将基于 Android 10 代码逻辑介绍原生启动过程。 bootloader 上电 -> 加载 recovery 镜像或者 boot 镜像 -> linux kernel 启动 -> 加载 init 进程 -> 加载 zygote 进程 -> systemserver 进程 -> 系统启动 …

线上3D看车有何优势?

随着Web3D展示技术的不断革新&#xff0c;线上3D看车正逐步成为消费者购车的新选择。这种创新的展示方式不仅提供了更真实、更有趣的互动体验&#xff0c;还带来了诸多优势&#xff0c;让购车过程变得更加便捷、高效。 一、更真实的展示效果 相较于传统的图片和文字描述&…

OpenCv —— 为opencv支持中文,将freetype2库编译进opencv中(附详细编译流程、测试代码)

效果(下面摄像头视频过于老旧 视频效果不好;但文字可添加。) 背景 由于OpenCV本身不支持中文显示,开发者需要借助其他库来实现这一功能。 OpenCV的contrib版本中包含了freetype库,可以通过编译opencv-contrib模块来支持中文显示。这种方法需要在编译OpenCV时特别配置,确保…

打印直角三角形

今天给大家分享一个打印直角三角形的方法 其实直角三角形在终端中的显示是又空格和星号组成的 只要将其看成一个矩形&#xff0c;并找出两者规律便可实现&#xff08;与打印菱形有一定相似的理解&#xff09;&#xff0c;下面我们来分享一个更简便的方法 它的规律是行和列之和…

python-函数前一行加@xxxx的含义参数的约束条件检查装饰器

在sklearn中看到红框中的函数&#xff0c;于是好奇是什么东西&#xff0c;查到python-函数前一行加xxxx的含义 于是找到函数定义&#xff1a;def validate_params(parameter_constraints, *, prefer_skip_nested_validation): 但是&#xff0c;里面没有定义func参数 于是再看…

科技资讯|谷歌Play应用商店有望支持 XR 头显,AR / VR设备有望得到发展

据 Android Authority 报道&#xff0c;谷歌似乎正在为其 Play 商店增加对 XR 头显的支持。该媒体在 Play 商店的代码中发现了相关的线索&#xff0c;包括一个代表头显的小图标以及对“XR 头显”的提及。 谷歌也可能改变了此前拒绝将 Play 商店引入 Meta Quest 头显的决定。今…

百度SEO分析实用指南 提升网站搜索排名的有效策略

内容概要 在数字化时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;已经成为提升网站曝光度的关键工具。本指南将带您了解SEO的基本知识&#xff0c;帮助您在复杂的网络环境中立足。我们将从关键词优化开始&#xff0c;重点讲解如何选择合适的关键词来提高搜索引擎排…

基于vue框架的的考研网上辅导系统ao9z7(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;学生,公告信息,课程分类,考研资料,考研视频,课程信息,院校建议,教师 开题报告内容 基于Vue框架的考研网上辅导系统开题报告 一、研究背景与意义 随着高等教育的普及和就业竞争的加剧&#xff0c;考研已成为众多大学生提升学历、增强就…

flutter 用PUT的方式传输文件不带分隔符

最近有个需求&#xff0c;需要在flutter中用put的方式传输固件到设备上&#xff0c;本来以为用dio或者http这两个框架就能轻松完成的&#xff0c;结果发现&#xff0c;这两个框架传输过去的文件都会修改了源文件&#xff0c;把请求头的分隔符也带进去了&#xff0c;设备无法识别…

Javaweb 实验4 xml

我发现了有些人喜欢静静看博客不聊天呐&#xff0c; 但是ta会点赞。 这样的人呢帅气低调有内涵&#xff0c; 美丽大方很优雅。 说的就是你&#xff0c; 不用再怀疑哦 实验四 XML 目的&#xff1a; 安装和使用XML的开发环境认识XML的不同类型掌握XML文档的基本语法了解D…