首页 > 其他分享 >简单了解前端性能监控

简单了解前端性能监控

时间:2024-04-14 21:45:29浏览次数:27  
标签:eagle const 前端 self xhr let 监控 ._ 性能

作为一名开发来讲,以下场景你有没有遇到:

  • 点击这个按钮怎么没反应了
  • 页面为什么白了
  • 怎么一直正在加载
  • 很多用户说图片加载不出来
  • ......

那么有一款性能监控产品太重要了,但是性能相关的东西实在太多了。那么从一个熟悉又陌生的api开始,performance。

1.什么是performance

mdn上是这么解释的:Performance 接口可以获取到当前页面中与性能相关的信息。它是 High Resolution Time API 的一部分,同时也融合了 Performance Timeline API、Navigation Timing API、User Timing API 和 Resource Timing API。

直接在控制台打印:

 除去eventCounts和memory兼容不是很好的属性,重点看下剩余四个。

2.performace.timing属性

我们配合这张经典图来了解这些属性

 

页面进来之前:

 navigationStart:前一个网页卸载时间。

unloadEventStart:前一个网页的upload事件开始

unloadEventEnd:前一个网页的upload事件结束

redirectStart:网页重定向开始时间

redirectEnd:网页重定向结束时间

页面进来之后:

fetchStart:开始请求网页

domainLookupStart:dns查询开始

domainLookupEnd:dns查询结束

connectStart:向服务器建立握手开始

connectEnd:向服务器建立握手结束

secureConnectionStart:安全握手开始,默认值0。非https的没有

requestStart:向服务器发送请求开始

responseStart:服务器返回数据开始

responseEnd:服务器返回数据结束

解析dom开始:

domLoading:解析dom开始,document.readyState为loading

domInteractive:解析dom结束,document.readyState为interactive

domContentLoadedEventStart:DomContentLoaden所有回调开始执行

domContentLoadedEventEnd:ContentLoaded结束,dom内容加载完毕

loadEventStart:load事件发生前

loadEventEnd:load事件发生后

3.实战一波

有了上边的具体数据,如何进行计算进行监控上报呢。

以下代码中的p均为performance.timing对象

3.1 网络连接相关

// 上一个页面的时间,没多大用途
const pervPage = p.fetchStart - p.navigationStart 
// 重定向时间
const redirect = p.redirectEnd - p.redirectStart
// dns查找时间
const dns = p.domainLookupEnd - p.domainLookupStart
// tcp建立时间
const connect = p.connectEnd - p.connectStart
// 网络总耗时
const network = p.connectEnd - p.navigationStart

网络建连层如果太慢或者出问题,那么首先应该和运维部门沟通,查找问题,和前端后端关联性不大。

3.2 网络接收相关

// 前端发送到接收的时间
const send = p.responseStart - p.requestStart
// 接收数据用时
const receive = p.responseEnd - p.responseStart
// 总耗时
const request = p.responseEnd - p.requestStart

3.3 前端渲染

// dom解析时间
const dom = p.domComplete - p.domLoading
// loadEvent时间
const loadEvent = p.loadEventEnd - p.loadEventStart
// 总耗时
const frontend = p.loadEventEnd - p.domLoading

3.4 关键阶段

// 页面完全加载的时间
const load = p.loadEventEnd - p.navigationStart
// dom准备时间
const domReady = p.domainLookupStart - p.navigationStart
// 可操作时间
const interactive = p.domInteractive - p.navigationStart
// 首字节时间
const ttfb = p.responseStart - p.navigationStart

3.5 使用

// dom解析完成
let isDOMReady = false;
// callback 就是获取上边计算performance各个指标的回调
function domready (callback) {
  if (isDOMReady) return;
  let timer = null;
  let runCheck = () => {
    if (performance.timing.domComplete) {
      clearTimeout(timer);
      callback();
      isDOMReady = true;
      // 1、停止循环检测 2、运行callback
    } else {
      // 再去循环检测
      timer = setTimeout(runCheck, 100);
    }
  }
  if (document.readyState === "interactive") {
    callback();
    return;
  }
  document.addEventListener('DOMContentLoaded', () => {
    // 开始循环检测 是否 DOMContentLoaded 已经完成了
    runCheck();
  })
}
// 在onload事件中
let isOnload = false;
function onl oad (callback) {
  if (isOnload) return;
  let timer = null;
  let runCheck = () => {
    if (performance.timing.loadEventEnd) {
      clearTimeout(timer);
      callback();
      isOnload = true;
      // 1、停止循环检测 2、运行callback
    } else {
      // 再去循环检测
      timer = setTimeout(runCheck, 100);
    }
  }
  if (document.readyState === "interactive") {
    callback();
    return;
  }
  window.addEventListener('load', () => {
    runCheck();
  })
}

在domready和onload方法中,可以避免出现负数问题。

4. 资源监控

 performance提供了getEnteries方法,用来获取加载的资源文件,返回数组形式。

 同样的,我们也可以封装个方法,根据这些属性,计算出想要的信息。代码中r代表数组某一项

const resourceData = {
  initiatorType: r.initiatorType,
  name: r.name,
  duration: parseInt(r.duration),

  // 连接过程
  redirect: r.redirectEnd - r.redirectStart, // 重定向的时间
  dns: r.domainLookupEnd - r.domainLookupStart, // dns查找的时间
  connect: r.connectEnd - r.connectStart, // tcp连接的时间
  network: r.connectEnd - r.startTime, // 网络总耗时

  // 接收过程
  send: r.responseStart - r.requestStart, // 发送开始到接收的总时长
  receive: r.responseEnd - r.responseStart, // 接收的总时长
  request: r.responseEnd - r.requestStart, // 接收的总耗时

  // 核心指标
  ttfb: r.responseStart - r.requestStart, // 首字节时间
}

但是,如果我们开发是一个商城网站,里边会有很多css、js、img等资源,他们都值得监控吗?

可以封装一个方法,传入link、script、或者图片名称包含包含某些字段的,或者随机抽取几个,我们去自定义去监听规则。有兴趣可以搜索一下大量日志log上报策略。

5. ajax请求监控

在实战项目中,肯定会涉及到网络请求和后端的交互,如何监听ajax请求的相关数据呢?

通过修改XMLHttpRequest原型,自定义open和send方法来达到目的。

const ajax = () => {
  let xhr = window.XMLHttpRequest;
  if (xhr._eagle_monitor_flag) return;
  xhr._eagle_monitor_flag = true;
  let _originOpen = xhr.prototype.open;
  xhr.prototype.open = function (method, url, async, user, password) {
    // 往xhr上自定义属性
    this._eagle_xhr_info = {
      url, method, status: null
    }
    return _originOpen.apply(this, arguments);
  }
  let _originSend = xhr.prototype.send;
  xhr.prototype.send = function () {
    let _self = this;
    this._eagle_start_time = Date.now();

    let ajaxEnd = (eventType) => () => {
      if (_self.response) {
        // 统计返回数据的大小
        let responseSize = null;
        switch (_self.responseType) {
          case 'json':
            // JSON兼容性问题 && stringify报错
            responseSize = JSON.stringify(_self.response).length;
            break;
          case 'arraybuffer':
            responseSize = _self.response.byteLength;
            break;
          default: 
            responseSize = _self.responseText.length; // 简单使用responseText的值
        }
        _self._eagle_xhr_info.event = eventType;
        _self._eagle_xhr_info.status = _self.status;
        _self._eagle_xhr_info.success = _self.status === 200;
        _self._eagle_xhr_info.duration = Date.now() = _self._eagle_start_time;
        _self._eagle_xhr_info.responseSize = responseSize;
        _self._eagle_xhr_info.requestSize = value ? value.length : 0 // value一定有length?百度查一下兼容写法;
        _self._eagle_xhr_info.type = 'xhr';
        // 打印_eagle_xhr_info,进行额外操作
        // console.log(_self._eagle_xhr_info)
        // callback(_self._eagle_xhr_info)
      }
    };

    // 这三种状态都代表着请求已经结束了
    // 需要统计一些信息,并进行上报
    this.addEventListener('load', ajaxEnd('load'), false);
    this.addEventListener('error', false);
    this.addEventListener('abort', false);

    return _originSend.apply(this, arguments);
  }
}

标签:eagle,const,前端,self,xhr,let,监控,._,性能
From: https://www.cnblogs.com/zmyxixihaha/p/18134552

相关文章

  • JMeter——异步请求性能测试
    前段时间任务要求要对一种异步请求做性能测试,异步请求步骤如下:step1:发一个数据计算的请求,response里面返回一个jobIdstep2:带上这个jobId,就可以实时查看这个请求返回的jobStatus,如果jobStatus==0,则成功返回计算结果;如果jobStatus==2,则代表jobinprogress;如果jobStatus==......
  • centos 监控
    1.pom.xml引入<dependency><groupId>ch.ethz.ganymed</groupId><artifactId>ganymed-ssh2</artifactId><version>262</version></dependency>ViewCode 2.java代码packa......
  • wsl、Prometheus、grafana、性能瓶颈分析
    感觉学着没啥意义,有时候面试又问。待业半年了,技术有个屁用一、wslwsl解释看百度百科,主要是为了有一个linux环境,方便学习1、找到Windows功能,勾选       2、管理员运行终端      3、运行命令(默认安装ubuntu):wsl --install......
  • 未来的前端框架技术发展趋势
    ​福利开篇推荐老铁们,你们是否平常开发有这样的问题:1.需要公网访问内网的一个服务?2.需要一个开发环境直接支持https,但是弄本地证书既不合法,又很麻烦?3.本地有强劲的服务器,需要对公网提供服务,但是拉宽带既贵,又麻烦?4.有云主机,但同时云主机需要访问内部的服务器?5.......
  • 通达信条件预警使用教程(引用选股公式盘中实时监控)
    步骤汇总:第1步:设置预警范围第2步:设置选股公式(预警公式)第3步:运行效果以下是详细步骤:第一步:设置预警范围 单击通达信右下角条件预警图标,单击设置,设置已有公式,过程如下:  注意事项:预警对电脑配置要求高,低配置的电脑不宜监控太多目标,建议只监控备选,此处我选择的是我之前......
  • Magnet DVR Examiner 3.12.0 (Windows) - 从监控系统 CCTV 和监控 DVR 恢复视频和元数
    MagnetDVRExaminer3.12.0(Windows)-从监控系统CCTV和监控DVR恢复视频和元数据DigitalForensicSoftware|DVR和CCTV恢复解决方案请访问原文链接:https://sysin.org/blog/magnet-dvr-examiner/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgMagnetDV......
  • 在Linux中,如何使用shell脚本进行系统监控和报告?
    在Linux中,使用shell脚本进行系统监控和报告是一种自动化管理任务的有效方法。脚本可以定期收集系统的关键信息,生成报告,并在发现问题时通知管理员。以下是创建这样一个脚本的基本步骤:1.确定监控目标首先,确定你需要监控的系统指标,如CPU使用率、内存使用、磁盘空间、网络流量、服......
  • 性能监控工具 grafana + prometheus + node_exporter 下载配置
        grafana   prometheus: 时序数据库,存储数据的   node_exporter: 收集数据(收集监控数据)     node_exporter 收集linux**系统资源利用**数据   这个解决方案中,node_exporter是可变的,是根据你要收集**哪些数据来进行选择**一、安装解压配置pr......
  • 短视频app源码,一文带你轻松搞懂前端大文件上传思路
    短视频app源码,一文带你轻松搞懂前端大文件上传思路文件上传是我们在平时开发短视频app源码中经常会遇到的业务,如果只是简单的文件上传那还不足以作为项目亮点,而当我们给它加上切片、续传的功能,就不一样了。本文会带大家搞明白这些功能的实现思路,主要聚焦于前端部分,基于Vue3......
  • freemarker 生成前端文件
    Freemarker是一种模板引擎,它允许我们在Java应用程序中分离视图和业务逻辑。在Freemarker中,List是一种非常有用的数据结构,它允许我们存储一组有序的元素。有时候,我们需要判断一个List是否为空,这在程序设计中有许多应用场景。本文将详细介绍如何使用FreemarkerList判断一个List是否......