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

前端监控:错误捕获与行为日志全解析

image-20251026192854028

行为日志采集

  • 页面浏览(Page Views)
  • 用户点击(Clicks)
  • 键盘输入(Keyboard Inputs)
  • 页面停留时间(Time on Page)
  • 滚动行为(Scrolling Behavior)
  • 表单填写情况(Form Interactions)

错误日志采集

语法错误

  • 缺少括号、大括号或方括号 [() {} []](javascript:void(0))
  • 缺少分号或逗号 ; ,
  • 字符串引号不匹配
  • 关键字拼写错误

同步错误

image-20251026200109158

异步错误

异步错误的话我们可以用window.onerror来进行处理,这个方法比try catch要强大很多

image-20251026200024133

promise错误

在promise中使用catch可以捕获到异步的错误,但是如果没有写catch去捕获错误的话
window,onerror也捕获不到的,所以写promise的时候最好要写上catch,或者可以在全局
加上unhandledrejection的监听,用来监听没有被捕获的promise错误。

image-20251026195945424

resource错误

资源加载错误指的是比如一些资源文件获取失败,可能是服务器挂掉了等原因造成的,出现这种
情况就比较严重了,所以需要能够及时的处理,网路错误一般用window.addEventListener来
捕获。

image-20251026200219830

全局错误捕获

import { lazyReport } from './report';/*** 全局错误捕获*/
export function errorTrackerReport() {// --------  js error ---------const originOnError = window.onerror;window.onerror = function (msg, url, row, col, error) {// 处理原有的onerrorif (originOnError) {originOnError.call(window, msg, url, row, col, error);}// 错误上报lazyReport('error', {message: msg,file: url,row,col,error,errorType: 'jsError'});}// ------  promise error  --------window.addEventListener('unhandledrejection', (error) => {lazyReport('error', {message: error.reason,error,errorType: 'promiseError'});});// ------- resource error --------window.addEventListener('error', (error) => {let target = error.target;let isElementTarget = target instanceof HTMLScriptElement || target instanceof HTMLLinkElement || target instanceof HTMLImageElement;if (!isElementTarget) {return; // js error不再处理}lazyReport('error', {message: "加载 " + target.tagName + " 资源错误",file: target.src,errorType: 'resourceError'});}, true)
}/*** 手动捕获错误*/
export function errorCaptcher(error, msg) {// 上报错误lazyReport('error', {message: msg,error: error,errorType: 'catchError'});
}

路由监听

import { lazyReport } from './report';/*** history路由监听*/
export function historyPageTrackerReport() {let beforeTime = Date.now(); // 进入页面的时间let beforePage = ''; // 上一个页面// 获取在某个页面的停留时间function getStayTime() {let curTime = Date.now();let stayTime = curTime - beforeTime;beforeTime = curTime;return stayTime;}/*** 重写pushState和replaceState方法* @param {*} name * @returns */const createHistoryEvent = function (name) {// 拿到原来的处理方法const origin = window.history[name];return function(event) {// if (name === 'replaceState') {//   const { current } = event;//   const pathName = location.pathname;//   if (current === pathName) {//     let res = origin.apply(this, arguments);//     return res;//   }// }let res = origin.apply(this, arguments);let e = new Event(name);e.arguments = arguments;window.dispatchEvent(e);return res;};};// history.pushStatewindow.addEventListener('pushState', function () {listener()});// history.replaceStatewindow.addEventListener('replaceState', function () {listener()});window.history.pushState = createHistoryEvent('pushState');window.history.replaceState = createHistoryEvent('replaceState');function listener() {const stayTime = getStayTime(); // 停留时间const currentPage = window.location.href; // 页面路径lazyReport('visit', {stayTime,page: beforePage,})beforePage = currentPage;}// 页面load监听window.addEventListener('load', function () {// beforePage = location.href;listener()});// unload监听window.addEventListener('unload', function () {listener()});// history.go()、history.back()、history.forward() 监听window.addEventListener('popstate', function () {listener()});
}/*** hash路由监听*/
export function hashPageTrackerReport() {let beforeTime = Date.now(); // 进入页面的时间let beforePage = ''; // 上一个页面function getStayTime() {let curTime = Date.now();let stayTime = curTime - beforeTime;beforeTime = curTime;return stayTime;}function listener() {const stayTime = getStayTime();const currentPage = window.location.href;lazyReport('visit', {stayTime,page: beforePage,})beforePage = currentPage;}// hash路由监听window.addEventListener('hashchange', function () {listener()});// 页面load监听window.addEventListener('load', function () {listener()});const createHistoryEvent = function (name) {const origin = window.history[name];return function(event) {// if (name === 'replaceState') {//   const { current } = event;//   const pathName = location.pathname;//   if (current === pathName) {//     let res = origin.apply(this, arguments);//     return res;//   }// }let res = origin.apply(this, arguments);let e = new Event(name);e.arguments = arguments;window.dispatchEvent(e);return res;};};window.history.pushState = createHistoryEvent('pushState');// history.pushStatewindow.addEventListener('pushState', function () {listener()});
}

上报

import { getCache, addCache, clearCache } from './cache';let timer = null;/*** 上报* @param {*} type * @param {*} params */
export function lazyReport(type, params) {const appId = window['_monitor_app_id_'];const userId = window['_monitor_user_id_'];const delay = window['_monitor_delay_'];const logParams = {appId, // 项目的appIduserId, // 用户idtype, // error/action/visit/userdata: params, // 上报的数据currentTime: new Date().getTime(), // 时间戳currentPage: window.location.href, // 当前页面ua: navigator.userAgent, // ua信息};let logParamsString = JSON.stringify(logParams);addCache(logParamsString);const data = getCache();if (delay === 0) { // delay=0相当于不做延迟上报report(data);return;}if (data.length > 10) {report(data);clearTimeout(timer);return;}clearTimeout(timer);timer = setTimeout(() => {report(data)}, delay);
}export function report(data) {const url = window['_monitor_report_url_'];// ------- fetch方式上报 -------// 跨域问题// fetch(url, {//   method: 'POST',//   body: JSON.stringify(data),//   headers: {//     'Content-Type': 'application/json',//   },// }).then(res => {//   console.log(res);// }).catch(err => {//   console.error(err);// })// ------- navigator/img方式上报 -------// 不会有跨域问题if (navigator.sendBeacon) { // 支持sendBeacon的浏览器navigator.sendBeacon(url, JSON.stringify(data));} else { // 不支持sendBeacon的浏览器let oImage = new Image();oImage.src = `${url}?logs=${data}`;}clearCache();
}
http://www.dtcms.com/a/531897.html

相关文章:

  • 第一部分:网络基础
  • Socket详解
  • Ceph存储
  • [人工智能-大模型-87]:模型层技术 - “神经网络架构演进的全景地图”,“从简单到复杂、从单一到智能” - 通俗易懂版。
  • windows 2003 取消网站访问密码wordpress黑镜百度云盘
  • Spring Boot3零基础教程,自定义 starter,把项目封装成依赖给别人使用,笔记65
  • 建设足球网站的心得和意义渠道分销管理系统
  • 【PLC】汇川InoTouchPad在Win11上显示太小
  • OpenHarmony蓝牙技术全解析:从设备发现到数据传输的完整流程
  • 解压版MySQL的安装与卸载
  • C++编程基础(五):字符数组和字符串
  • 在线旅游网站平台有哪些山东泰安房价2023最新价格
  • [3D Max 基础知识分享]—多孔结构模型编辑
  • 【C++篇】C++11入门:踏入C++新世界的大门
  • 爬虫数据清洗可视化案例之全球灾害数据
  • QT(c++)开发自学笔记:4.Qt 3D简易实现
  • Vue3 自定义事件
  • 上海住房和城乡建设厅网站个人备案网站可以做产品推广
  • Android OpenGLES视频剪辑示例源码
  • 做淘宝客导购网站推广wordpress 明星
  • WebForms 页面
  • Leetcode 39
  • 【STM32项目开源】基于STM32的智能水质检测系统
  • 设计模式-迭代器模式(Iterator)
  • GitHub等平台形成的开源文化正在重塑天热e
  • 做网站需要用什么开发软件有哪些制作视频的软件
  • github中获得Personal Access Token
  • 从RDPDD!DrvEscape到RDPWD!ShareClass::UPSendOrders
  • RiPro数据转换CeoMax插件
  • IA复习笔记4 路由