监控系统创建

https://juejin.cn/post/7046756775252459528
https://juejin.cn/post/6936562262480158728#heading-2
https://cloud.tencent.com/developer/article/1983779
https://zhuanlan.zhihu.com/p/495649475

为什么要创建前端监控系统

主要是为了解决两种问题:

  • 如何及时发现问题
  • 如何快速定位并解决问题

前端监控体系主要需要做的事情

  • 页面整体访问情况,pv、uv、用户行为上报
  • 页面的性能情况,包括:加载耗时、接口耗时统计
  • 灰度发布和有效的监控能力,方便及时发现问题
  • 用户反馈问题,需要足够的日志定位

总结起来就是两点:数据收集数据上报

数据收集

一般是三个方面

  • 稳定性(页面稳定性/异常):js错误(js执行错误、promise异常)、资源错误(js、css加载异常)、接口错误(ajax、fetch请求错误)、白屏
  • 流畅性(页面访问速度)
  • 用户行为回放(外部服务调用情况):pv、uv、用户在某个页面的停留时间

1、稳定性(页面稳定性/异常)

1)脚本错误

有两类,分别为【语法错误】【运行时错误】,下面是主要监控方式:

  • try catch:可以用在预知情况下监控特定错误,但发生语法错误或者异步错误时,无法捕捉,常与window.onerror结合使用
  • window.onerror:捕获JS运行时错误
  • window.addEventListener('unhandledrejection'):捕获promise未处理reject的错误,即promise被reject了,但是没有reject处理器,则会走到这一步(https://developer.mozilla.org/zh-CN/docs/Web/API/Window/unhandledrejection_event
  • window.addEventListener('error'):资源加载错误(js、css加载异常),但是他也能上报js运行时错误, 所以判断只有是script、link、image时才去拿数据

为避免重复上报js运行时错误,此时只有event.srcElement inatanceof HTMLScriptElement或HTMLLinkElement或HTMLImageElement时才进行数据采集。

// try catch 语法错误
try {
    function empty()   // <-  throw error 语法错误
} catch(e){
    console.log('语法错误信息 ↙');
    console.log(e);
}
// try catch 异步错误
try {
    setTimeout(function() {
        test // <- throw error 异步错误
    },0)
} catch(e){
    console.log('异步错误信息 ↙');
    console.log(e);
}
2)跨域资源的脚本报错Script error

常见的形式就是,我本来的网站域名是a.com,然后,里面使用script引入了一个cdn连接,cdn连接域名是b.com,这个时候在调用cdn里的方法时就会报Script error,但是获取不到完整的信息,只能获取到类似于:"Script error.", "", 0, 0, undefined的信息

解决方式:

  • 为页面上script标签添加crossorigin属性
// 这一步告诉浏览器,目标脚本通过匿名方式获取。这意味着请求脚本时没有潜在的用户身份信息(如cookies、HTTP 证书等)发送到服务端
<script src="http://another-domain.com/app.js" crossorigin="anonymous"></script>
  • 响应头中增加 Access-Control-Allow-Origin 来支持跨域资源共享,使用*或者上面本来的网站即http://a.com
  • 当 Access-Control-Allow-Origin的值为http://a.com时,响应头中需带上Vary:Origin。避免引缓存导致的权限问题。(ps:为*的时候无所谓,因为所有的域名都让他去请求了)

通过以上方式可以使用window.onerro获取到具体的报错信息

3)接口异常

通过重写XMLHttpRequest和fetch的原生方法来实现

  • 重写XMLHttpRequest的open、send方法
  • 监听load、error、abort事件
window.addEventListener("error", handler("error"), false);

4)资源加载异常

页面内的图片、css、JS等Assets资源加载失败,会在error事件里可以拿到资源加载失败回调:

window.addEventListener( 'error ', function(e){
//排除JSError
    if( ! (e instanceof ErrorEvent)){
//资源路径
        e.target.src || e.target.href
        //资源类型
        e.target.tagName
    }
}, true) // 为true则是捕获阶段处理函数,否则为冒泡阶段处理函数
5)白屏问题

页面加载过程中因为任意问题导致渲染没有完成,呈现空白页面的异常

一般基于不同方案会有不同的处理方式

1、基于mutationObserver:页面加载完成后3s,页面没有节点变化(节点不变不代表不白屏)
2、基于native容器:页面加载完成后3s,页面还是全屏白色像素(依赖容器)
3、基于pointTiming:页面加载完成后3s,页面没有fisrt-point,下方为实现(兼容性不好)
  • document.elementsFromPoint方法可以获取到当前视口内指定坐标处,由里到外排列的所有元素
  • 根据 elementsFromPoint api,获取屏幕水平中线和竖直中线所在的元素(9点监测)
image.png
 for (let i = 1; i <= 9; i++) {
      xElements = document.elementsFromPoint(
        (window.innerWidth * i) / 10,
        window.innerHeight / 2
      );
      yElements = document.elementsFromPoint(
        window.innerWidth / 2,
        (window.innerHeight * i) / 10
      );
      isWrapper(xElements[0]);
      isWrapper(yElements[0]);
    }
6)crash

页面因为内存溢出、死循环等原因导致崩溃的异常

1、基于LocalStroage里的页面离开状态
  • 在页面加载时,标记开始加载
  • 在pagehide或者beforunload时标记离开,二次进入页面时判断是否正常离开
  • 埋点发送滞后,起不到监控告警作用
2、基于native
  • 监控webview进程状态,发送crash日志
  • 依赖容器
3、基于service worker
  • html请求进入service worker时,标记页面开始加载
  • 每隔一段时间像sw发送一次心跳,当一段时间没有收到心跳则表示crash了
  • 兼容性差,一个页面只能有一个sw,如果页面也需要使用sw,则需进行嵌入,切换页面又可能pause

2、流畅性(页面访问速度)

image.png
1)卡顿

响应用户交互的响应时间如果大于100ms,用户就会感觉卡顿

卡顿:页面整个生命周期中,主线程持续执行某一个任务的耗时大于50ms
浏览器的事件队列机制决定,要实现小于100毫秒的响应,应用必须在每50毫秒内将控制返回给主线程

  • new PerformanceObserver
  • entry.duration(持续时间) > 100 判断大于100ms,即可认定为长任务(entry是参数,详见第三个链接)
  • 使用 requestIdleCallback上报数据
2)PV、UV、用户停留时间

PV(page view) 是页面浏览量,UV(Unique visitor)用户访问量。PV 只要访问一次页面就算一次,UV 同一天内多次访问只算一次。
对于前端来讲,只要每次进入页面上报一次 PV 就行,UV 的统计放在服务端来做

 window.addEventListener(
    "beforeunload",
    () => {},
    false// 冒泡的时候做回调
}
3)加载时间(onload时监听)

3、用户行为回放(外部服务调用情况)【可以先不说】

数据上报

主要有三种方式处理信息上报

丢点:在浏览器点击跳转时,跳转前的点击上报请求都会进行一个三次握手,如果此时,网络较慢、服务器运行缓慢或者上报请求还在处理阶段,这时,如果页面被卸载了,浏览器都会自动对当前的请求进行终止。这样,这个http的请求就没有建立,导致上报没有真正发出。

延迟卸载:在卸载事件处理器中尝试通过一个同步的 XMLHttpRequest 向服务器发送数据。这导致了页面卸载被延迟。

img请求

  • 兼容性好
  • 部分浏览器可能造成丢点、get请求长度限制,延迟页面卸载
  • 就是动态js创建img标签,把上报的url拼接,然后放在src上

Fetch/XHR(XMLHttpRequest)

  • 兼容性好
  • fetch丢点,XHR不丢点,但是页面延迟卸载

Navigator.sendBeacon(推荐使用)

sendBeacon()会使用户代理在有机会时异步地向服务器发送数据,同时不会延迟页面的卸载或影响下一导航的载入性能

  • 不丢点,不会页面延迟卸载
  • 兼容性不好
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,846评论 2 374
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,146评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,789评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,656评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,467评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,870评论 3 389
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,500评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,790评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,828评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,628评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,449评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,881评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,077评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,376评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,879评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,089评论 2 338

推荐阅读更多精彩内容

  • 前端的监控主要分为三个方面: 性能监控 白屏时间; 首屏时间; 用户可交互时间; 总下载时间; TCP连接时间;...
    神刀阅读 637评论 0 0
  • 前言想当初自己也是从一个小白一步一步走到现在(小白中的老人 ),虽然还是一个大厂朋友都没有,但是始终不放弃学习的机...
    livcll学院阅读 233评论 0 0
  • 前言 最近杂七杂八的事情比较多,难得抽出时间来弥补一下之前的系列,欠大家的埋点系列现在开始走起来 为什么需要埋点系...
    Small_Song阅读 1,376评论 0 0
  • 前端监控分为性能监控和错误监控。其中监控分为俩个环节: 数据采集和数据上报。本文主要讲的是如何进行数据采集和数据上...
    Adam_5361阅读 837评论 0 0
  • 1.为什要做前端监控 更快发现问题和解决问题 做产品的决策依据 提升前端工程师的技术深度和广度,打造简历亮点 为业...
    niuqinyan阅读 513评论 0 0