记录--前端性能监控初步实战

news2024/11/19 10:28:47

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

前言

在当下前后端分离的主流环境下,前端部分的优化变得越来越重要。为了提升前端的性能和用户体验,我觉得可能需要从三个维度采集数据进行分析。

  1. 前端埋点。通过埋点收集和统计网页的UV/PV、设备型号、浏览器等数据进行分析,比如可以有针对性对使用比较靠前的设备、浏览器等做优化和体验。
  2. 网页性能收集和监控。 采集一个页面从请求开始到完成这个过程中的数据指标。比如收集和监控首屏加载时间、dom渲染时长、响应比较慢的接口等。有了这些数据可以很直观和针对性的对网页的性能进行优化和升级。
  3. 错误收集和监控。收集网页中的js的报错、静态资源加载报错,保证网页正常访问和降低bug率。

1.前端埋点

采集用户的行为,监控产品在用户端的使用情况,根据数据可以明确,前端可以针对性的做优化和体验。

可以简单的初步建立这样的数据模型:

{
 ip: ip地址,统计uv
 ua: 浏览器的userAgent //方便区分浏览器的品牌
 os: 系统名称
 current_page_all: 当前页面访问总次数
 width:浏览器宽度,   
 height:浏览器高度, //统计浏览器的尺寸
 current_enter_time: 进入当前页面的时间戳
 current_leave_time: 离开当前页面的时间戳
 project_id: 项目的id,
 url: 当前url,
 user_uni_id: 临时分配给用户唯一的id
 ....
 还有其他
}

2.在网页中植入对应的js代码

//进入
document.addEventListener('DOMContentLoaded',function(){
   ...
   let args = {
     ua: navigator.userAgent,
     os: navigator.platform,
     width: document.body.clientWidth || document.documentElement.clientWidth,
     height: document.body.clientHeight || document.documentElement.clientHeight,
     project_id: md5('abcd'),
     user_uni_id: '临时分配给用户唯一的id',
     url: window.location.href,
     current_enter_time: new Date().getTime()
     ....
   };
   let img = new Image();
   img.onload = function() {
     img = null;
   };
   img.src= `https://localhost:9700/bury.gif?args=${qs(args)}`;
 });

//离开
window.onbeforeunload = function() {
   ...
   let args = {
     ...
     leave_time: new Date().getTime()
     ....
   };
   let img = new Image();
   img.onload = function() {
     img = null;
   };
   img.src= `https://localhost:9700/bury.gif?args=${qs(args)}`;
}
  1. 收集数据并上报
const fs = require('fs');
route.get('/bury.gif',async (ctx)=>{
  let queryStr = ctx.querystring;
  let d = new Date();
  let year = d.getFullYear();
  let month = d.getMonth()+1;
  let day = d.getDate()+1;
  fs.writeFile(`../logs/${year}-${month}-${day}.log`,queryStr,{flag:'a',encoding:'utf-8',mode:'0666'},function(e){});
   ctx.status = 200;
   ctx.type = 'image/gif';
   ctx.body = {};
});

简单的设想方案是先把数据收集到文本文件里,然后定时的分析这些文本文件,然后把筛选后的放到数据库中。

2.网页性能收集

网页性能主要是收集是输入url地址到网页请求完成资源下载完成这段时间范围内一些请求、加载等指标。

  • 比如举几个简单的指标:

  • 首屏加载时长

  • HTML 文档被加载和解析完成

  • 网页加载完成时间

  • 白屏时间

  • 其他…

  1. 具体实现方案(一):
//index.html
<html>
 <head>
   <script>
     window.startTime = Date.now();
   </script>
 </head>
 <body>
   <script>
     let diff = Date.now()-window.startTime;
     console.log('白屏时长'+diff);
     document.addEventListener('DOMContentLoaded',()=>{
       console.log('HTML 文档被加载和解析完成时间'+Date.now()-window.startTime); 
     });
     window.onload = function() {
       console.log('网页加载完成时间'+Date.now()-window.startTime); 
     };
   </script>
   <script src="a.js"></script>
   <script src="b.js"></script>
   ....
 </body>
</html>

使用performance API

Performance是W3C性能小组引入进来的一个新的API,他可以很好的获取到首屏加载时间、白屏时间、dns查询时间等,是一个很方便的获取网页性能指标的API,而且目前大部分主流浏览器是支持的。

https://www.caniuse.com/

1.Performance一些常用用法的总结

let timing = window.performance.timing
//白屏时间
timing.responseStart - timing.navigationStart
//DNS 查询时长
timing.domainLookupEnd - timing.domainLookupStart
//request请求耗时
timing.responseEnd - timing.responseStart
//HTML 文档被加载和解析完成耗时
timing.domComplete - timing.domInteractive
//网页加载完成耗时
timing.loadEventEnd - timing.navigationStart
//重定向耗时
timing.redirectEnd - timing.redirectStart;
//占用的内存
window.performance.memory.usedJSHeapSize;

2.此外还有一些高级用法,比如可以收集一些请求和静态资源的请求时间

let  time = [];
let entryLists = window.performance.getEntries();
for(let i=0;i<entryLists.length;i++) {
  let item = entryLists[i];
  let obj = {};
     let soureTypes = ['script','css','xmlhttprequest','link','img'];
     if(soureTypes.indexOf(item.initiatorType)>=0){
       obj.name = item.name;  
       //请求时间
       obj.reqTime = item.responseEnd - item.responseStart;
       time.push(obj);
     }
}

3.关于Performance的更多用法可以参考:

https://www.jianshu.com/p/1355232d525a
https://blog.csdn.net/hb_zhouyj/article/details/89888646

4.收集数据上报

收集上报数据,使用koa2创建接口performance.gif

const fs = require('fs');
route.get('/performance.gif',async (ctx)=>{
  let queryStr = ctx.querystring;
  let d = new Date();
  let year = d.getFullYear();
  let month = d.getMonth()+1;
  let day = d.getDate()+1;
  fs.writeFile(`../performance-logs/${year}-${month}-${day}.log`,queryStr,{flag:'a',encoding:'utf-8',mode:'0666'},function(e){});
   ctx.status = 200;
   ctx.type = 'image/gif';
   ctx.body = {};
});

3.错误收集和监控

错误收集主要就是针对js报错、静态资源加载等出错信息进行收集。

  1. 收集js报错最先想到的可能是try catch。
try {
    console.log(b);
    } catch(e) {
      console.log(e);
      sendErrorReq();
    };

但是使用使用的话,每个页面收集错误都要充斥这try catch,这样其实是不太好的。

而且catch似乎没办法捕获到异步的操作。

try {
      setTimeout(()=>{
       console.log(b); 
      })
    } catch(e) {
      console.log(e);
      sendErrorReq();
    };

试了一下没有执行到catch里边的sendErrorReq函数。

使用try catch是一种局部错误监听方式。

  1. 用window.onerror或者是window.addEventListener(‘error’)

window.onerror

/**
      *msg 错误信息
      *url 错误所在的页面地址
      *row 错误所在的行数
      *col 错误所在的列数
      **/
     window.onerror = function(msg,url,row,col) {
       console.log(msg,url,row,col, error);
     };
    b();

使用window.onerror可以检测到js的报错,但是没法监听静态资源加载失败的情况。

<img src="一个不存在的图片地址" alt="">

window.addEventListener(‘error’)

window.addEventListener(‘error’)能够监听到静态资源加载出错

window.addEventListener('error',(e)=>{
      let localName = e.srcElement.localName;
      let currentSrc = e.srcElement.currentSrc;
      if(localName=='img') {
        console.log(`图片${currentSrc}加载失败了`);
        sendErrorData(currentSrc);
      }
      ...
      // e.preventDefault();
    },true);

必须设为捕获过程中执行,否则依然无法监听。

3. promise错误的收集

new Promise((resolve,reject)=>{
       reject('hi');
    }).catch(e=>{
      console.log(e);
      sendErrorData(e)
    });
axios.get(...).catch(e=>{
  console.log(e);
   sendErrorData(e)
})

但是有种情况,如果promise不加catch的话,
没法通过window.onerror去监听,但是还是通过监听unhandledrejection事件去收集的

4.unhandledrejection

window.addEventListener('unhandledrejection', event => {
       console.log('error:'+event.reason); 
        sendErrorData(event.reason);
    });   
    new Promise((resolve,reject)=>{
       reject('hi');
    });

在看下在vue中收集报错,以vue-cli3创建的项目进行演示

测试了一下window.onerror这种方式 无法监听错误的。

在网上找了下原因

可以看到在vue的源码里,因为如果没有定义errorHandler就会走到logError这个方法,所以没法使用window.onerror进行监听。

5.errorHandler

在vue的手册中,推荐监听vue报错的可以使用errorHandler这个配置方法。

//main.js
Vue.config.errorHandler = function (err, vm, info) {
  console.log('错误是:', err)
  sendErrorData(err);
}
然后随便故意写错
mounted() {
  a();
}
就能收集到报错信息了

 当然最后把收集的错误上报给服务器,创建一个接口error.gif。

const fs = require('fs');
route.get('/error.gif',async (ctx)=>{
  let queryStr = ctx.querystring;
  ....
  fs.writeFile(`../error-logs/${year}-${month}-${day}.log`,queryStr,{flag:'a',encoding:'utf-8',mode:'0666'},function(e){});
   ctx.status = 200;
   ctx.type = 'image/gif';
   ...
});

本文转载于:

http://events.jianshu.io/p/a6572eb10e00

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

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

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

相关文章

SCRM与CRM的区别

当私域流量的概念兴起时&#xff0c;企业直接触达用户的场景也越来越丰富&#xff0c;SCRM形式的私域运营已然成为很多企业数字化转型布局的关键阵地。 前言 当私域流量的概念兴起时&#xff0c;企业直接触达用户的场景也越来越丰富&#xff0c;SCRM形式的私域运营已然成为很多…

服务器部署所有前后端分离项目

1、Linux服务器安装好jdk、mysql、redis、node 2、拉取最新代码 gitee仓库项目地址&#xff1a;https://gitee.com/y_project/RuoYi-Vue 拉取代码到本地 3、修改后端配置 3.1、修改系统内上传文件位置的配置&#xff1a; 默认是windows系统的配置&#xff0c;将此配置修改…

JMeter接口测试使用教程哪里有?

JMeter接口测试使用教程哪里有&#xff1f;接口测试是测试工程师的必备技能之一&#xff0c;运用JMeter工具一步步实现接口请求&#xff0c;数据参数化&#xff0c;断言等操作&#xff0c;通过常见的企业实际测试场景详解JMeter各项技术使用&#xff0c;最后结合Jenkins持续集成…

Django搭建个人博客Blog-Day01

创建虚拟环境虚拟环境相当于一个抽屉&#xff0c;在这个抽屉里面安装的任何软件&#xff0c;都不会影响到其他抽屉&#xff0c;所以利用虚拟环境就可以做到同时安装不同版本的第三方库&#xff0c;而互不影响。使用虚拟环境的目的是为了防止一些第三方库出现版本不兼容问题&…

c++11 标准模板(STL)(std::forward_list)(五)

定义于头文件 <forward_list> template< class T, class Allocator std::allocator<T> > class forward_list;(1)(C11 起)namespace pmr { template <class T> using forward_list std::forward_list<T, std::pmr::polymorphic_…

当我们在谈论DataOps时,我们到底在谈论什么

1. DataOps到底是什么&#xff1f; 伴随着全球数字化转型的高速发展&#xff0c;在云计算、物联网、5G、边缘计算、元宇宙等新技术的驱动下&#xff0c;数据爆炸的时代已经来临。IDC Global DataSphere显示&#xff0c;2021年&#xff0c;全球数据总量达到了84.5ZB&#xff0c…

Java多线程案例——阻塞队列(生产者消费者模型)

一&#xff0c;阻塞队列1.阻塞队列的概念和作用阻塞队列同数据结构中的队列一样都遵守“先进先出”的原则&#xff08;不了解队列相关知识的朋友请查看之前队列的博文&#xff1a;(6条消息) 栈和队列&#xff08;内附模拟实现代码&#xff09;_徐憨憨&#xff01;的博客-CSDN博…

功率放大模块如何选择(安泰功率放大器模块产品介绍)

功率放大器模块系列产品介绍 一、功率放大模块介绍 功率放大模块&#xff1a; 功率放大模块具有体积小&#xff0c;集成度高&#xff0c;使用方便&#xff0c;应用广泛等优点&#xff0c;凭借着输出频率广、输出电压高、输出功率大等特性&#xff0c;能够广泛应用在各种领域…

动态范围控制原理

DRC介绍 开门见山&#xff0c;动态范围的定义就是信号的最大幅值和最小幅值比值的对数(单位dB)&#xff0c; 动态范围会受到系统中各个环节的影响。例如同样是这段音乐&#xff0c;在一个40dB背景噪声的环境中播放&#xff0c;那么由于掩蔽效应等因素的影响&#xff0c;最终实际…

前端跳转第三方网页中间页

前端跳转安全提示 掘金跳转中间页背景介绍跳转过渡页的优点实现原理解析哈喽啊小伙伴们久等了 消失了有半年了 &#xff0c;因为个人工作原因没腾出时间给大家分享日常踩坑和特殊功能的讲解。不过这次我回来了就要好好分享了背景介绍 前端小伙伴一定知道CSDN 和 稀土掘金 两大…

Dev-C++下载安装详细教程

文章目录前言一、下载Dev-C二、安装Dev-C三、使用Dev-C打印HelloWorld总结前言 本文总结了关于Dev-C下载与安装的详细过程&#xff0c;并使用Dev-C打印了“Hello World!”。本篇博客面向C语言初学者&#xff0c;或者考研复试的学生使用&#xff0c;因为大部分学校的考研复试都使…

为什么 TCP 建立连接需要三次握手

TCP 协议是我们几乎每天都会接触到的网络协议&#xff0c;绝大多数网络连接的建立都是基于 TCP 协议的&#xff0c;学过计算机网络或者对 TCP 协议稍有了解的人都知道 —— 使用 TCP 协议建立连接需要经过三次握手&#xff08;three-way handshake&#xff09;。 如果让我们简…

多线程案例-线程池

1.什么是线程池线程存在的意义是当使用进程进行并发编程太重了,此时引入了一个"轻量级的"进程-线程.创建线程比创建进程更高效,销毁线程比销毁进程更高效,调度线程比调度进程更高效..此时我们就用多线程来代替进程进行并发编程了,但是随着对性能的要求的提高,线程相对…

大数据必学Java基础(一百一十八):什么是Maven和它的下载整合

文章目录 什么是Maven和它的下载整合 一、什么是Maven 二、IDEA默认整合了Maven 三、下载地址

【Linux】RHEL8 中nmcli使用,必备!

redhat8中nmcli日常使用 第 2 章 配置以太网连接 Red Hat Enterprise Linux 为管理员提供不同的选项来配置以太网连接。例如&#xff1a; 在命令行中使用 nmcli 配置连接。使用 nmtui 在基于文本的用户界面中配置连接。使用 RHEL 系统角色在一个或多个主机上自动配置连接。使…

电脑小问题:定时关机的设置

设置定时关机生活中&#xff0c;我们有时候需要对电脑进行定时关机。那么&#xff0c;如何设置定时关机呢&#xff1f;步骤如下&#xff1a; 1. 按 win R &#xff0c;弹出命令窗口&#xff0c;输入 taskschd.msc &#xff0c;点击确定。 2. 弹出任务计划程序窗口&#xff0c;…

使用ResNet34实现CIFAR10数据集的训练

如果对你有用的话&#xff0c;希望能够点赞支持一下&#xff0c;这样我就能有更多的动力更新更多的学习笔记了。&#x1f604;&#x1f604; 使用ResNet进行CIFAR-10数据集进行测试&#xff0c;这里使用的是将CIFAR-10数据集的分辨率扩大到32X32&#xff0c;因为算力相关的…

摘要/哈希/散列算法MD5 SHA1 SHA256 SHA512的区别和MAC算法

一、摘要算法大致都要经过以下步骤 1. 明文数据预处理 1.1 填充比特 MD5、SHA1、SHA256 的分组长度都是512bit 需要填充比特使其位长对512求余的结果等于448 SHA512 的分组长度是 1024bit 需要填充比特使其对1024求余的结果等于896 相同&am…

ECharts基本使用

文章目录Echarts概述Echarts初体验ECharts基础配置Echarts社区介绍Echarts-map使用Echarts概述 常见的数据可视化库&#xff1a; D3.js 目前 Web 端评价最高的 Javascript 可视化工具库(入手难)ECharts.js 百度出品的一个开源 Javascript 数据可视化库Highcharts.js 国外的前…

项目合并后,font字体资源被替换导致TextMeshPro不能显示文字,抢救方法

一&#xff0c;字体消失 项目合并时&#xff0c;因为资源更替&#xff0c;导致TextMeshPro不能找到自己原来使用的font资源&#xff0c;以致不能显示文字。 二、抢救方式 1、找到所有用到TextMeshPro的物体2、把他们的字体重新设置成你要的字体 关键步骤&#xff1a; 1、找…