【前端】前端监控⊆埋点

news2024/12/25 23:27:19

文章目录

  • 前端监控分为三个方面
  • 前端监控流程
  • 异常监控
    • 常见的错误捕获方法主要是 try / catch 、window.onerror 和window.addEventListener 等。
    • Promise 错误
    • Vue 错误
    • React 错误
  • 性能监控
  • 用户行为监控
  • 常见的埋点方案
  • 来源

前端监控分为三个方面

  1. 异常监控(监控前端页面的报错)
  2. 性能监控(监控页面的性能)
  3. 用户行为监控(监控用户的行为,计算PV、UV、在线时间等、数据监控即我们常说的埋点

前端监控流程

  1. 前端埋点
  2. 数据上报
  3. 加工汇总
  4. 可视化展示
  5. 监控报警

异常监控

  • JS 代码运行错误、语法错误等;
  • AJAX 请求错误;
  • 静态资源加载错误;
  • Promise 异步函数错误;

错误信息监控简单来说就是要搜集报错信息的发生的位置,以及报错的类型,进行上报,便于我们能够更好的掌握错误信息,从而能够对症下药。按照 5W1H 的法则来说,我们需要关注以下的几项信息:

  • What ,发生了什么错误:语法错误、类型错误、数据错误、逻辑错误等;
  • When ,什么时间发生的错误,可带上时间戳进行上报;
  • Who ,哪个用户或者哪一类用户发生了错误,包括用户 ID 、设备信息、IP 信息等;
  • Where ,哪个项目、哪些页面发生错误,可以上报页面的 URL 以及代码报错行数等信息;
  • Why ,为什么会发生错误,也就是用户在什么样的场景下发生的错误,便于问题复现;
  • How ,根据以上的信息如何进行问题的定位,然后怎么处理并解决问题;

常见的错误捕获方法主要是 try / catch 、window.onerror 和window.addEventListener 等。

try / catch

这是我们在代码调试的过程中最常用的一个方式,但它只能捕获代码常规的运行错误,语法错误和异步错误并能捕获到。

// 常规运行时错误,可以捕获 ✅
try {
    console.log(notdefined);
} catch(e) {
    console.log('捕获到异常:', 'ReferenceError');
 
}
 
// 语法错误,不能捕获 ❌
try {
    const notdefined,
} catch(e) {
    console.log('捕获不到异常:', 'Uncaught SyntaxError');
}
 
// 异步错误,不能捕获 ❌
try {
    setTimeout(() => {
        console.log(notdefined);
    }, 0)
} catch(e) {
    console.log('捕获不到异常:', 'Uncaught ReferenceError');
}

window.onerror
当 JS 运行时错误发生时,window 会触发一个 ErrorEvent 接口的 error 事件,并执行 window.onerror() 。

加载一个全局的 error 事件处理函数可用于自动收集错误报告。

最后需要补充的是:window.onerror 函数只有在返回 true 的时候,异常才不会向上抛出,否则即使是知道异常的发生,控制台还是会显示 Uncaught Error 。

 
```javascript
/**
 
* @param { string } message 错误信息
* @param { string } source 发生错误的脚本URL
* @param { number } lineno 发生错误的行号
* @param { number } colno 发生错误的列号
* @param { object } error Error对象
 
*/
 
window.onerror = function(message, source, lineno, colno, error) {
    console.log('捕获到的错误信息是:', message, source, lineno, colno, error )
}
 
// 常规运行时错误,可以捕获 ✅
window.onerror = function(message, source, lineno, colno, error) {
    console.log('捕获到异常:',{message, source, lineno, colno, error});
}
console.log(notdefined);
// message: "Uncaught ReferenceError: notdefined is not defined"
// source: "file:///C:/Users/qinzq42866/Desktop/error.html"
// lineno: 14
// colno: 19
// error: ReferenceError: notdefined is not defined at file
// 语法错误,不能捕获 ❌
window.onerror = function(message, source, lineno, colno, error) {
    console.log('未捕获到异常:',{message, source, lineno, colno, error});
}
const notdefined,
// Uncaught SyntaxError: Missing initializer in const declaration
 
// 异步错误,可以捕获 ✅
window.onerror = function(message, source, lineno, colno, error) {
    console.log('捕获到异常:',{message, source, lineno, colno, error});
}
setTimeout(() => {
    console.log(notdefined);
}, 0)
 
// message: "Uncaught ReferenceError: notdefined is not defined"
 
// source: "file:///C:/Users/qinzq42866/Desktop/error.html"
 
// lineno: 15
 
// colno: 21
 
// error: ReferenceError: notdefined is not defined at file
 
// 资源错误,不能捕获 ❌
<script>
window.onerror = function(message, source, lineno, colno, error) {
    console.log('捕获到异常:',{message, source, lineno, colno, error});
}
 
</script>
 
// GET https://yun.tuia.cn/image/kkk.png 404 (Not Found)

window.addEventListener
当一项静态资源加载失败时,加载资源的元素会触发一个 Event 接口的 Error 事件,这些 Error 事件不会向上冒泡到 window ,但能被捕获。而 window.onerror 不能检测捕获。

// 图片、script、css加载错误,都能被捕获 ✅
 
<script>
 
  window.addEventListener('error', (error) => {
 
     console.log('捕获到异常:', error);
 
  }, true)
 
</script>
 
 
// fetch错误,不能捕获 ❌
 
 
<script>
 
  window.addEventListener('error', (error) => {
 
    console.log('未捕获到异常:', error);
 
  }, true)
 
</script
 
 
<script>
 
  fetch('https://tuia.cn/test')
 
</script>

由于网络请求异常不会发生事件冒泡,因此必须在事件捕获的阶段将其捕捉到才行,这种方式虽然能够捕捉到网络请求的异常,但是却无法判断 HTTP 的状态,因此仍然需要配合服务端的日志进行配合分析。

需要注意的是:不同浏览器下返回的 Error 对象是不一样的,需要做兼容处理。

Promise 错误

没有写 catch 的 Promise 中抛出的错误是无法被 onerror 或 try / catch 捕获到的,这也是为什么我们一定要在 Promise 后面加上 catch 去捕获和处理异常。

为了防止有漏掉的 Promise 异常信息,建议在全局增加一个对 unhandledrejection 的监听,用来全局监听 Uncaught Promise Error 。

说明:当 Promise 被 reject 且没有 reject 处理器的时候,会触发 unhandledrejection 事件;这可能发生在 window 下,但也可能发生在 Worker 中。 这对于调试回退错误处理非常有用。

window.addEventListener("unhandledrejection", event => {
 
    console.warn('UNHANDLED PROMISE REJECTION:', ${event.reason});
 
});
 
window.onunhandledrejection = event => {
 
    console.warn('UNHANDLED PROMISE REJECTION:', ${event.reason});
 
};
 
window.addEventListener("unhandledrejection", function(e){
 
    e.preventDefault()
 
    console.log('捕获到异常:', e);
 
});
 
Promise.reject('promise error');

说明:如果去掉控制台的异常显示,需要加上 event.preventDefault() ;

Vue 错误

由于 Vue 会捕获到所有 Vue 单文件组件或者 Vue.extend 继承的代码,所以在 Vue 里面出现的错误并不会直接抛给 window.onerror ,而是会被 Vue 自身的 Vue.config.errorHandler 捕获。

Vue.config.errorHandler = (err, vm, info) => {
 
console.error('通过vue errorHandler捕获的错误');
 
console.error(err);
 
console.error(vm);
 
console.error(info);
 
}

React 错误

React 16 提供了一个内置函数 componentDidCatch ,使用它可以轻松的捕获到 React 组件内部抛出的错误信息。

 
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
 
  componentDidCatch(error, errorInfo) {
    console.log('捕获到错误:', error, errorInfo);
  }
 
  render() {
    if (this.state.hasError) {
      return `Something went wrong.`;
    }
 
    return this.props.children; 
  }
}

性能监控

  • 不同用户和不同设备下的首屏加载时间,包括白屏时间;
  • HTTP 接口的响应时间;
  • 静态资源、包括图片的下载时间;

根据W3C性能小组引入的新的API(目前IE9以上的浏览器)–window.performance,实现前端性能监控
在这里插入图片描述

(function () {
 
    handleAddListener('load', getTiming)
 
    function handleAddListener(type, fn) {
        if (window.addEventListener) {
            window.addEventListener(type, fn)
        } else {
            window.attachEvent('on' + type, fn)
        }
    }
 
    function getTiming() {
        try {
            var time = performance.timing;
            var timingObj = {};
 
            var loadTime = (time.loadEventEnd - time.loadEventStart);
 
            if (loadTime < 0) {
                setTimeout(function () {
                    getTiming();
                }, 200);
                return;
            }
            // 阶段耗时
            timingObj['DNS解析耗时'] = (time.domainLookupEnd - time.domainLookupStart);
            timingObj['TCP连接耗时'] = (time.connectEnd - time.connectStart);
            timingObj['SSL安全连接耗时'] = (time.connectEnd - time.secureConnectionStart);//针对https
            timingObj['网络请求耗时'] = (time.responseStart - time.requestStart);
            timingObj['数据传输耗时'] = (time.responseEnd - time.responseStart);
            timingObj['DOM解析耗时'] = (time.domInteractive - time.responseEnd);
            timingObj['资源加载耗时, 表示页面中的同步加载资源'] = (time.loadEventStart - time.domContentLoadedEventEnd);
            timingObj['前端onload执行时间'] = (time.loadEventEnd - time.loadEventStart);
 
            //性能指标(上报字段名)
            timingObj["首次渲染"] = time.responseEnd - time.fetchStart
            // timingObj["首屏时间"] =  first meaningful paint
            timingObj["首次可交互"] = time.domInteractive - time.fetchStart
            timingObj["DOMReady"] = time.domContentLoadedEventEnd - time.fetchStart
            timingObj["页面完全加载"] = time.loadEventStart - time.fetchStart
            timingObj["首包时间"] = time.responseStart - time.domainLookupStart
 
 
            for (item in timingObj) {
                console.log(item + ":" + timingObj[item] + '毫秒(ms)');
            }
 
            console.log(performance.timing);
            console.log(performance);
 
        } catch (e) {
            console.log(timingObj)
            console.log(performance.timing);
        }
    }
})();

用户行为监控

  • PV / UV:PV 即 Page View ,也就是页面的浏览数量,没打开页面一次就会统计一次;UV 即 User View
    ,也就是不同用户访问的次数,在 PV 的基础上根据 User 信息的不同做了去重操作;
  • 用户在每个页面停留的时间信息。即从用户打开该页面到用户离开该页面的时间差,用于表示该页面对用户的留存程度;
  • 用户的来处。即从什么入口或什么渠道来到了当前页面,通常会在 URL 中添加查询参数来做区分统计;
  • 用户的页面操作行为。即用户在该页面点击了哪些按钮,或者从什么链接去到了某些页面等等,来分析用户的去向。
import tracker from "../util/tracker";
export function pv() {
  tracker.send({
    kind: "business",
    type: "pv",
    startTime: performance.now(),
    pageURL: getPageURL(),
    referrer: document.referrer,
    uuid: getUUID(),
  });
  let startTime = Date.now();
  window.addEventListener(
    "beforeunload",
    () => {
      let stayTime = Date.now() - startTime;
      tracker.send({
        kind: "business",
        type: "stayTime",
        stayTime,
        pageURL: getPageURL(),
        uuid: getUUID(),
      });
    },
    false
  );
}

常见的埋点方案

代码埋点
嵌入代码的形式
优点:精确(任意时刻,数据量全面)
缺点:代码工作量点

可视化埋点
通过可视化交互的手段,代替代码埋点
将业务代码和埋点代码分离,提供一个可视化交互的页面,输入为业务代码,通过这个系统,可以在业务代码中自定义的增加埋点事件等等,最后输出的代码耦合了业务代码和埋点代码
用系统来代替手工插入埋点代码

无痕埋点
前端的任意一个事件被绑定一个标识,所有的事件都被记录下来
通过定期上传记录文件,配合文件解析,解析出来我们想要的数据,并生成可视化报告供专业人员分析
无痕埋点的优点是采集全量数据,不会出现漏埋和误埋等现象
缺点是给数据传输和服务器增加压力,也无法灵活定制数据结构

来源

前端监控指的是什么?
前端 监控

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

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

相关文章

如何选择示波器?

简介 对于很多工程师来讲&#xff0c;从市场中上百款不同价格和规格的各种型号的示波器中&#xff0c;选择一台新示波器是一件很挠首的事情。本文就旨在指引你拨开迷雾&#xff0c;希望能帮助你避免付出昂贵的代价。 重中之重 选择示波器的第一步不是要看那些示波器的广告和规…

Lombok注解式简化开发

Lombok&#xff08;发音为"lombk"&#xff09;是一种Java库&#xff0c;它通过注解的方式来简化Java代码的编写。它提供了一组注解&#xff0c;用于在编译时生成代码&#xff0c;减少了开发人员需要手动编写的样板代码&#xff0c;提高了代码的简洁性和可读性。 Lom…

【三种加载自定义控制器的方式 Objective-C语言】

一、关于这个手动创建Window呢,给大家说完了 1.但是呢,要给大家补充一个东西, 有时候,有的框架,可能会用到什么东西呢,我写到下面: [UIApplication sharedApplication] 什么东西,是不是应用程序对象, 然后呢,keyWindow 是不是拿到它的主窗口, 然后呢,add什么东西…

2013年12月2日 Go生态洞察:Go 1.2的测试覆盖率工具

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Find My自行车|苹果Find My技术与自行车结合,智能防丢,全球定位

自行车&#xff0c;这项古老而简单的交通工具&#xff0c;近年来在中国经历了一场令人瞩目的复兴。从城市的街头巷尾到乡村的田园小路&#xff0c;自行车成了一种新的生活方式&#xff0c;一个绿色出行的选择。中国的自行车保有量超过两亿辆&#xff0c;但是自行车丢失事件还是…

java算法学习索引之数组矩阵问题

一 将正方形矩阵顺时针转动90 给定一个NN的矩阵matrix&#xff0c;把这个矩阵调整成顺时针转动90后的形式。 顺时针转动90后为&#xff1a; 【要求】额外空间复杂度为O&#xff08;1&#xff09;。 public void rotate(int[][] matrix) {int tR 0; // 左上角行坐标int tC 0;…

2023年中国AI大模型行业发展趋势分析:未来发展将走向通用化和专用化并行[图]

AI大模型是AI预训练大模型的简称&#xff0c;通过在大规模数据上进行预训练&#xff0c;无需大量微调即可支持各种应用&#xff0c;具备多层神经网络结构、高级优化算法和强大计算资源&#xff0c;显著提升了AI的通用性和实用性。 AI大模型特点及意义 资料来源&#xff1a;共研…

Java引用类型(String)

目录 String解析 final的作用 String是否有长度限制 StringBuffer解析 StringBuilder解析 关键字、操作类相关 引用数据类型非常多大致包括&#xff1a;类、 接口类型、 数组类型、 枚举类型、 注解类型、 字符串型。String类型就是引用类型。 String解析 JVM运行时会分…

姿态估计 手势动作实时识别项目(基于mediapipe、keras进行实现)

姿态估计 手势动作实时识别项目(基于mediapipe、keras进行实现) 0、功能展示1、项目原理介绍2、数据集采集脚本3、将采集到的动作数据集利用mediapipe库检测手部关键点信息,转换成数据信息保存到本地4、训练一个效果一般的随机森林分类器5、使用Kreas训练一个效果好点的全连…

linux内核管理

linux内核会占用一定的空间&#xff0c;所以可以清理一下不需要使用的内核. 参考链接 Linux 内核及其关联文件通常存储在 /boot 目录下&#xff0c;内核模块通常存储在 /lib/modules 目录中。 首先查看已安装的列表&#xff1a; dpkg --list | grep linux-image其中&#xff…

Hfish安全蜜罐部署

一、Hfish蜜罐介绍 HFish蜜罐官网 HFish是一款社区型免费蜜罐&#xff0c;侧重企业安全场景&#xff0c;从内网失陷检测、外网威胁感知、威胁情报生产三个场景出发&#xff0c;为用户提供可独立操作且实用的功能&#xff0c;通过安全、敏捷、可靠的中低交互蜜罐增加用户在失陷…

python实战—核心基础4(超市购物小票随机抽奖程序) lv1

目录 一、核心代码解释 二、代码 三、运行截图 一、核心代码解释 1、random() 函数 描述 random() 方法返回随机生成的一个实数&#xff0c;它在[0,1)范围内。 语法 以下是 random() 方法的语法: import randomrandom.random() 注意&#xff1a;random()是不能直接访问…

肉豆蔻酰六肽-16——让皮肤更加光滑、更加柔软

肉豆蔻酰六肽-16 一种合成的脂肪酸连接肽&#xff0c;已知可提高皮肤的弹性&#xff0c;明显镇静&#xff0c;并帮助皮肤看起来和感觉更光滑、更柔软。它是由肉豆蔻酸与六肽 16 结合而成。肉豆蔻酰六肽 16 被归类为蛋白质刺激肽&#xff0c;这意味着它可以帮助皮肤表面&#x…

抽象轻松测试接口API

测试 1.测试环境 2.测试代码 3.代码结构 Maven项目核心依赖 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.3.0</version></dependenc…

2023年中国涂料用环氧树脂需求量及行业市场规模前景分析[图]

环氧树脂具有力学性能高&#xff0c;内聚力强、分子结构致密&#xff0c;粘接性能优异&#xff0c;固化收缩率小&#xff08;产品尺寸稳定、内应力小、不易开裂&#xff09;&#xff0c;绝缘性、防腐性、稳定性、耐热性好&#xff08;可达200℃或更高&#xff09;等特点&#x…

解锁无限可能性:探索Amazon Lightsail的便捷云计算服务

解锁无限可能性&#xff1a;探索Amazon Lightsail的便捷云计算服务 在数字化时代&#xff0c;云计算成为推动创新和业务发展的关键驱动力。Amazon Lightsail 作为 Amazon Web Services&#xff08;亚马逊云科技&#xff09;家族中的一员&#xff0c;为小型企业和创业公司提供了…

共谋发展,共赢未来 | 江西航天红源农业科技总经理孟凡明一行莅临拓世科技集团考察参观

在时刻充满着变化与机遇的商业世界里&#xff0c;农业的颠覆与重构已成为产业新风口&#xff0c;在日新月异的当下&#xff0c;农业与乡村正被开辟成为推动产业结构升级的新战场。 2023年11月20日江西航天红源农业科技有限公司总经理孟凡明一行抵达拓世科技集团南昌总部进行考…

【鸿蒙应用ArkTS开发系列】- 灌水区,鸿蒙ArkTs开发有问题可以在该帖中反馈

大家好, 这是一篇水贴&#xff0c;给大家提供一个交流沟通鸿蒙开发遇到问题的地方。 新增新增这个文章呢&#xff0c;大家在开发使用ArkTS开发鸿蒙应用或者鸿蒙服务的时候&#xff0c;有遇到疑问或者问题&#xff0c;可以在本文章评论区提问&#xff0c;我看到了如果知道怎么…

基于SSM的学生档案管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

SpingBoot原理

目录 配置优先级Bean管理 (掌握)Bean的获取 ApplicationContext.getBeanBean的作用域 Scope("prototype") Lazy第三方Bean Bean Configuration SpringBoot底层原理 起步依赖与自动配置(无需手撸但面试高频知识点)自动配置引入第三方依赖常见方案方案1&#xff1a;Com…