当前位置: 首页 > news >正文

你可能不知道的前端监控方案

前言

现有的大部分监控方案都是针对服务端的,而针对前端的监控很少,诸如线上页面的白屏时间是多少、静态资源的加载情况如何、接口请求耗时好久、什么时候挂掉了、为什么挂掉,这些都不清楚。

因而,我们需要一个前端的页面监控系统,持续监控和预警页面性能的状况,并且在发现瓶颈时用于指导优化工作。

前端监控目标

分为性能监控及异常监控

  • 保证稳定性(异常监控) 错误监控包括 JavaScript 代码错误,Promsie 错误,接口(XHR,fetch)错误,资源加载错误(script,link 等)等,这些错误大多会导致页面功能异常甚至白屏。

  • 提升用户体验(性能监控) 性能监控包括页面的加载时间,接口响应时间等,侧面反应了用户体验的好坏。

性能监控

页面加载过程

简单看一下,从输入 url 到页面加载完成的过程如下:

首先需要通过 DNS(域名解析系统)将 URL 解析为对应的 IP 地址,然后与这个 IP 地址确定的那台服务器建立起 TCP 网络连接,随后我们向服务端抛出 HTTP 请求,服务端处理完我们的请求之后,把目标数据放在 HTTP 响应里返回给客户端,拿到响应数据的浏览器就可以开始走一个渲染的流程。渲染完毕,页面便呈现给了用户。

我们可以将这个过程分为如下的过程:

  1. DNS 解析

  2. TCP 连接

  3. HTTP 请求抛出

  4. 服务端处理请求,HTTP 响应返回

  5. 浏览器拿到响应数据,解析响应内容,把解析的结果展示给用户

从开发者角度,观察页面加载各阶段

从输入 url 到用户可以使用页面的全过程时间统计,会返回一个 PerformanceTiming 对象,单位均为毫秒。 关于 performace,已经在《从前端角度浅谈性能》中进行过介绍,,下面再强调一下:

各阶段的性能耗时可以通过 API:window.performance 来获取,对应的具体方法有:performance.timing、performance.getEntriesByType (‘resource’)、performance.navigation 等。 如上,开发者可以通过 performance 中各阶段的时间戳,分别获取到 页面各阶段的性能指标,具体的个静态资源的加载耗时、及 页面是否重定向和重定向耗时。

要触发执行的属性

  • navigationStart: 在同一个浏览器上下文中,前一个网页(与当前页面不一定同域)unload 的时间戳,如果无前一个网页 unload ,则与 fetchStart 值相等

  • redirectStart: 第一个 HTTP 重定向发生时的时间。有跳转且是同域名内的重定向才算,否则值为 0

  • unloadEventStart: 前一个网页(与当前页面同域)unload 的时间戳,如果无前一个网页 unload 或者前一个网页与当前页面不同域,则值为 0

  • redirectEnd: 最后一个 HTTP 重定向完成时的时间。有跳转且是同域名内的重定向才算,否则值为 0

  • unloadEventEnd: 和 unloadEventStart 相对应,返回前一个网页 unload 事件绑定的回调函数执行完毕的时间戳

  • fetchStart: 浏览器准备好使用 HTTP 请求抓取文档的时间,这发生在检查本地缓存之前

  • domainLookupStart:DNS 域名查询开始的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等

  • domainLookupEnd:DNS 域名查询完成的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等

  • connectStart:HTTP(TCP) 开始建立连接的时间,如果是持久连接,则与 fetchStart 值相等,如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接开始的时间

  • secureConnectionStart:HTTPS 连接开始的时间,如果不是安全连接,则值为 0

  • connectEnd:HTTP(TCP) 完成建立连接的时间(完成握手),如果是持久连接,则与 fetchStart 值相等,如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接完成的时间

  • requestStart:HTTP 请求读取真实文档开始的时间(完成建立连接),包括从本地读取缓存,连接错误重连时,这里显示的也是新建立连接的时间

  • responseStart:HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存

  • responseEnd:HTTP 响应全部接收完成的时间(获取到最后一个字节),包括从本地读取缓存

  • domLoading: 开始解析渲染 DOM 树的时间,此时 Document.readyState 变为 loading,并将抛出 readystatechange 相关事件

  • domInteractive: 完成解析 DOM 树的时间,Document.readyState 变为 interactive,并将抛出 readystatechange 相关事件

  • domContentLoadedEventStart:DOM 解析完成后,网页内资源加载开始的时间,文档发生 DOMContentLoaded 事件的时间

  • domContentLoadedEventEnd:DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕),文档的 DOMContentLoaded 事件的结束时间

  • domComplete:DOM 树解析完成,且资源也准备就绪的时间,Document.readyState 变为 complete,并将抛出 readystatechange 相关事件

  • loadEventStart:load 事件发送给文档,也即 load 回调函数开始执行的时间,如果没有绑定 load 事件,值为 0

  • loadEventEnd:load 事件的回调函数执行完毕的时间,如果没有绑定 load 事件,值为 0

各个阶段性能计算(可以自定义)

const { timing, navigation } = window.performance
const loadPageInfo = {};// 页面加载类型,区分第一次load还是reload, 0初次加载、1重加载
loadPageInfo.loadType = navigation.type;// 页面加载完成的时间 - 几乎代表了用户等待页面白屏的时间
loadPageInfo.loadPage = timing.loadEventEnd - timing.navigationStart;// 重定向的时间
loadPageInfo.redirect = timing.redirectEnd - timing.redirectStart;// 卸载页面的时间
loadPageInfo.unloadEvent = timing.unloadEventEnd - timing.unloadEventStart;// 查询 DNS 本地缓存的时间
loadPageInfo.appCache = timing.domainLookupStart - timing.fetchStart;// 【重要】DNS 查询时间
// 页面内是不是使用了太多不同的域名,导致域名查询的时间太长?推荐 DNS 预加载。
// 可使用 HTML5 Prefetch 预查询 DNS
loadPageInfo.lookupDomain = timing.domainLookupEnd - timing.domainLookupStart;// HTTP(TCP)建立连接完成握手的时间
loadPageInfo.connect = timing.connectEnd - timing.connectStart;// 【重要】HTTP请求及获取 文档内容的时间
loadPageInfo.request = timing.responseEnd - timing.responseStart;// 【重要】前一个页面 unload 到 HTTP获取到 页面第一个字节的时间
// 【原因】这可以理解为用户拿到你的资源占用的时间,推荐 加异地机房,加 CDN 处理,加宽带,加 CPU 运算速度
// TTFB 即 Time To First Byt
loadPageInfo.ttfb = timing.responseStart - timing.navigationStart;// 解析 DOM 树结构的时间
loadPageInfo.domReady = timing.domComplete - timing.responseEnd;// 【重要】执行 onload 回调函数的时间
// 【原因】是否太多不必要的操作都放在 onload 回调函数里执行了,推荐 延迟加载、按需加载的策略
loadPageInfo.loadEvent = timing.loadEventEnd - timing.loadE

异常监控

  1. Javascript 错误(js 错误、promise 错误)

  2. 监听 error 错误(资源加载错误)

console.error

// 重写console.error,可以捕获更全面的报错信息
var oldError = console.error;console.error = function(tempErrorMsg){
var errorMsg = ( arguments[0] && arguments[0].message ) || tempErrorMsg;
var lineNumber = 0;
var columnNumber = 0;
var errorStack = arguments[0] && arguments[0].stack;
if( !errorStack ){
saveJSError( 'console_error', errorMsg, '', lineNumber, columnNumber, 'CustomizeError: ' + errorMsg );
}else{
saveJSError( 'console_error', errorMsg, '', lineNumber, columnNumber, errorStack );
}return oldError.apply( console, arguments )

error 事件

通过对 error 事件的监听,可以捕捉到 js 语法 及 资源加载 的错误。根据 event.target.src/href 来判断是否为资源加载错误。

window.addEventListener( 'error', function(e){
var errorMsg = e.error && e.error.message,
errorStack = e.error && e.error.stack,
pageUrl = e.filename,
lineNumber = e.lineno,
columnNumber = e.colno;saveJSError( 'on_error', errorMsg, pageUrl, lineNumber, columnNumber, errorStack );
} );

Promise

// 捕获未处理的Promise错误
window.onunhandledrejection = function(e){
var errorMsg = '';
var errorStack = '';
if( typeof e.reason === 'object' ){
errorMsg = e.reason.message;
errorStack = e.reason.stack;
}else{
errorMsg = e.reason;
errorStack = '';}saveJSError( 'on_error', errorMsg, '', 0, 0, 'UncaughtInPromiseError: ' + errorStack );
}

相关文章:

你可能不知道的前端监控方案

前言 现有的大部分监控方案都是针对服务端的,而针对前端的监控很少,诸如线上页面的白屏时间是多少、静态资源的加载情况如何、接口请求耗时好久、什么时候挂掉了、为什么挂掉,这些都不清楚。 因而,我们需要一个前端的页面监控系…...

java spring AOP 完全注解开发

我们先创建一个项目 然后引入java spring aop的依赖 然后 在src下创建目录 我这里 直接就叫 Aop了 下面创建一个User类 参考代码如下 package Aop;import org.springframework.stereotype.Component;Component public class User {public void add(){System.out.println(&qu…...

ctf pwn基础-4

今天是学pwn的第四天,去接触了pwn的整数溢出。 目录 基础 实例讲解 实例讲解2 基础 关于整数溢出,这里以int为例,因为我php之前搞的比较多,以为这个int也是想php一样是64,最大值是9开头的那个,闹了不少笑…...

bool与引用类型

bool与引用类型bool类型介绍与使用bool(布尔类型)大小&#xff1a;1个字节返回值有两个&#xff1a;1(true)&#xff0c;0(false)#include<iostream>using namespace std;int main() {bool a false;bool b true;cout << "a " << a << end…...

tkinter界面的TCP通信/tkinter开启线程接收TCP

前言 用简洁的语言写一个可以与TCP客户端实时通信的界面。之前做了一个项目是要与PLC进行信息交互的界面&#xff0c;在测试的时候就利用TCP客户端来实验&#xff0c;文末会附上TCP客户端。本文分为三部分&#xff0c;第一部分是在界面向TCP发送数据&#xff0c;第二部分是接收…...

[SQL Statements] 基本的SQL知识 之DDL针对数据库的基本操作

SQL Statements SQL语句的学习 之 DDL针对数据库的基本操作 什么是database 在 MySQL 中&#xff0c;Database&#xff08;数据库&#xff09;是一组有组织的数据集合&#xff0c;可以存储和管理相关数据的容器。一个数据库可以包含多个表&#xff08;Table&#xff09;&…...

Qt的MOC机制

Qt的MOC机制 Qt扩展了C&#xff0c;使得开发者拥有很多方便使用的工具。如何使用Qt提供的特性呢&#xff1f;比如信号与槽&#xff0c;那就需要开发者在类中声明Q_OBJECT宏&#xff0c;这样程序员就能使用Qt提供的功能了。为什么这样可以呢&#xff1f;先从C文件的编译过程开始…...

Linux驱动——设备模型

目录 一、起源 二、新方案 2.1 sysfs: 2.2 uevent 三、代码中自动mknod 四、实例 一、起源 仅devfs&#xff0c;导致开发不方便以及一些功能难以支持&#xff1a;&#xff08;硬编&#xff09; 1. 热插拔&#xff08;插上usb设备就立马能安装驱动&#xff09; 2. 不支持…...

.NET基础加强第一课--面向对象(OO)

.NET基础加强第一课--面向对象&#xff08;OO&#xff09;面向对象什么是类&#xff1f;封装--属性封装字段2&#xff0c; 方法的多个参数封装成一个类3&#xff0c; 把一堆代码封装到一个方法中4&#xff0c; 将一些功能封装到几个类中5&#xff0c; 将一些具有共有功能封装到…...

从Linux源码角度看套接字的Listen及连接队列

今天就从Linux源码的角度看下Server端的Socket在进行listen的时候到底做了哪些事情(基于Linux 3.10内核)&#xff0c;当然由于listen的backlog参数和半连接hash表以及全连接队列都相关&#xff0c;在这里也一块讲了。 Server端Socket需要Listen 众所周知&#xff0c;一个Serv…...

cesium: 显示闪烁的点(004)

第004个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中设置闪烁的点。主要是介绍entity>point 相关的属性设置 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共107行)相关API参考:专栏目标示例效果 配…...

常见代码审计工具,代码审计为什么不能只用工具?

代码审计是一种发现程序漏洞&#xff0c;安全分析为目标的程序源码分析方式。今天主要分享的是几款常用的代码审计工具&#xff0c;以及代码审计工具有哪些优缺点&#xff1f; 代码审计工具 seay代码审计工具&#xff0c;是一款开源的利用C#开发的一款代码审计工具。主要有SQ…...

es8集群模式部署

准备3台机器 192.168.1.41 192.168.1.42 192.168.1.43因为es集群有几个节点&#xff0c;所以我对应node1&#xff0c;node2&#xff0c;node3.这几个名称并不是主机名&#xff0c;而是es节点名称 2. 开始部署&#xff0c;基础配置 (三台都做) systemctl stop firewalld syste…...

OAuth2

1.什么是OAuth2 OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时&#xff0c;任何第三方都可以使用OAUTH认证服务&#xff0c;任何服务提供商都可以实现自身的OAUTH认证服务&#xff0c;因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP、JavaScript&…...

一、简单排序

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、Comparable接口介绍 1.描述 2.Comparable使用 二、冒泡排序 1.排序原理 2.冒泡排序实现 2.1 冒泡排序API 2.2 冒泡排序实现 3.冒泡排序时间复杂度 三…...

慢SQL出现原因、优化、开启慢查询日志

文章目录慢SQL:出现原因&#xff1a;解决方式&#xff1a;开启慢查询日志&#xff1a;慢SQL: 出现原因&#xff1a; &#xff08;1&#xff09;数据库表索引设置不合理 &#xff08;2&#xff09;SQL语句有问题&#xff0c;需要优化 解决方式&#xff1a; &#xff08;1&am…...

要理解网络,其实不就是理解这三张表吗

我们如果要理解数据是如果在网络世界中穿梭的&#xff0c;那其实只要了解其中的三张表就可以了。这三张表分别为路由表、转发表、ARP 表。 假设我们用聊天工具聊天的时候&#xff0c;我在北京&#xff0c;你在广东&#xff0c;当我给你发送一条消息的时候。搭载这这条消息的数据…...

Java异常架构与异常关键字

Java异常简介 Java异常是Java提供的一种识别及响应错误的一致性机制。 Java异常机制可以使程序中异常处理代码和正常业务代码分离&#xff0c;保证程序代码更加优雅&#xff0c;并提高程序健壮性。在有效使用异常的情况下&#xff0c;异常能清晰的回答what, where, why这3个问…...

【阅读笔记】SecureML: A System for ScalablePrivacy-Preserving Machine Learning

1. Motivation 针对机器学习中的出现的数据隐私泄露的风险&#xff0c;提出了线性回归、逻辑回归以及简单神经网络的隐私保护模型。 2. Contributions 2.1 为线性回归、逻辑回归以及神经网络设计安全计算协议 2.1.1.1 线性回归 线性回归损失函数为&#xff1a; , 采用SG…...

【2023美赛】C题Wordle预测27页中文论文及Python代码详解

【2023美赛】C题Wordle预测27页中文论文及Python详解 相关链接 &#xff08;1&#xff09;2023年美赛C题Wordle预测问题一建模及Python代码详细讲解 &#xff08;2&#xff09;2023年美赛C题Wordle预测问题二建模及Python代码详细讲解 &#xff08;3&#xff09;2023年美赛C题…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...