针对白屏埋点,我是这样做的(前端监测)

8,136 阅读5分钟

前言

“白屏”,我作为一个切图切到手的切图崽,听运营那边反馈真不少了;有时一大早的就嚷嚷着:“那个切图崽,我们的产品又白屏啦。”;此时,我心中是“WDNMD”。其实,这个问题还是挺恶心的,要是在测试环境被测出来还好,可以及时修复;但是在生产环境,这就TMD;因为你也不知道什么时候就出现了这个问题,是刚出现的,还是昨天,还是一周前...这样就会造成不必要的损失。在生产环境,我们可爱的用户,会把“白屏”认为正在加载,一直在等,一直等到绝望,然后就去投诉运营:“你们的产品真垃圾,加载一天都没加载出来”。最后,运营就YY前端。老子,受够了,老子一定要在“白屏”出现的第一时间,消灭它;那么怎么才知道它出现了呢?那就要“埋个地雷了”(一般称为埋点)。那么怎么埋?又什么时候埋?

怎么埋 ?

这里要按自己公司的产品或者自己的项目来决定了。下面是我对公司的产品提出的三个“埋点方案”,可参考,但不一定适合你们。

垂直埋点

因为我们产品,主要页面都是居中布局,所以这种“埋点”可以满足我们产品的80%页面。垂直“埋点”,也就是在X,Y轴上埋,看图

假设,要在X,Y轴上各埋10个点,每个点的距离相等,那么X轴上的点坐标就是(i/10 * 屏幕的宽度,1/2 * 屏幕的高度, i 代表第几个点。那么Y轴上的坐标就是(1/2 * 屏幕的宽度,i / 10 * 屏幕的高度),it同理。

得到X,Y轴的坐标公式,如下:

X=i10屏幕的宽度,12屏幕的高度)X = (\frac{i}{10}*屏幕的宽度,\frac{1}{2}*屏幕的高度)

Y=12屏幕的宽度,i10屏幕的高度)Y = (\frac{1}{2}*屏幕的宽度,\frac{i}{10}*屏幕的高度)

交叉埋点

因为,垂直埋点可以解决居中布局的页面,但是我们有些新闻页面,有时只会在第一象限有内容,这时就进入了这种埋点的盲区了,就会被误判为“白屏”。看图

所以,就要考虑交叉埋点方案了。交叉埋点主要是将“地雷”埋在屏幕的两条对角线上。看图

这两条对角线为K1,K2(X,Y轴只是辅助线,方便理解)。我们要在它们身上各埋10个点,每个点的距离也是一样,那么该怎么取它们的坐标点?其实也很容易,我们只有取它们 i/10屏幕宽度,i/10屏幕高度就可以了。那么K1的坐标点就是:K1 = (i/10 * 屏幕宽度,i/10 * 屏幕高度),K2也很容易,只需将K1的坐标点逆向一下就好,K2 = ((10-i)/10 * 屏幕宽度,10-i)/10 * 屏幕g高度)

得到K1,K2轴的坐标公式,如下:

K1=i10屏幕的宽度,i10屏幕的高度)K1 = (\frac{i}{10}*屏幕的宽度,\frac{i}{10}*屏幕的高度)

K2=10i10屏幕的宽度,10i10屏幕的高度)K2 = (\frac{10-i}{10}*屏幕的宽度,\frac{10-i}{10}*屏幕的高度)

垂直交叉埋点

上面说了,我们页面多数都是居中布局,如果,内容比较少,又会进入交叉埋点的盲区,看图

所以,综合上面的情况,最后我们采取了两者结合的埋点方案。看图

公式就是两者的结合

X=i10屏幕的宽度,12屏幕的高度)X = (\frac{i}{10}*屏幕的宽度,\frac{1}{2}*屏幕的高度)

Y=12屏幕的宽度,i10屏幕的高度)Y = (\frac{1}{2}*屏幕的宽度,\frac{i}{10}*屏幕的高度)

K2=i10屏幕的宽度,i10屏幕的高度)K2 = (\frac{i}{10}*屏幕的宽度,\frac{i}{10}*屏幕的高度)

K1=10i10屏幕的宽度,10i10屏幕的高度)K1 = (\frac{10-i}{10}*屏幕的宽度,\frac{10-i}{10}*屏幕的高度)

如何代码实现

埋点的规则,我们已经找出来了,那么用代码实现就简单到不行了。


function blankWhite(){
  let point = 10
  let warpTag = ['HTML', 'BODY']
  let empty = 0
  function isWarp (ele){
    if(warpTag.includes(ele[0].nodeName)){
      empty+=1
    }
  }
  for (let i = 1; i < point; i++) {
    let x = document.elementsFromPoint(i / point * window.innerWidth,  window.innerHeight / 2)
    let y = document.elementsFromPoint( window.innerWidth / 2, i / point * window.innerHeight)
    let k2 = document.elementsFromPoint(i/point * window.innerWidth, i / point * window.innerHeight)
    let k1 = document.elementsFromPoint( (point-i)/point * window.innerWidth, (point-i)/point*window.innerHeight)
    isWarp(x)
    isWarp(y)
    isWarp(k2)
    isWarp(k1)
  }

  if(empty === 36){
    // doimg someThings ....
    // 如果为白屏,可以对白屏做一些你自己要干的事情,比如我们会把错误上传到自己公司的管理后台监测模块,方便我们及时知道白屏出现,以及修复
  }
}

那么为什么是 empty === 36 不是 empty === 40 ,明明埋了40个点,细心的同学会发现其实只埋了36个点 (i < point),为什么只埋36个,不埋满40个,因为,埋满的话,有些点会被埋到外面去了,document.elementsFromPoint就会返回一个空数组。

也有同学会疑问document.elementsFromPoint是一个什么?自己看一下MDN哈点这里

那么在什么时候埋 ?

这是一个很关键的点,我们要在AJAX之后或者DOM加载完之后再埋。


if(document.readyState === 'complete'){
  blankWhite()
}else{
  window.addEventListener('load',function(){
    blankWhite()
  })
}

完整代码


if(document.readyState === 'complete'){
  blankWhite()
}else{
  window.addEventListener('load',function(){
    blankWhite()
  })
}

function blankWhite(){
  let point = 10
  let warpTag = ['HTML', 'BODY']
  let empty = 0
  function isWarp (ele){
    if(warpTag.includes(ele[0].nodeName)){
      empty+=1
    }
  }
  for (let i = 1; i < point; i++) {
    let x = document.elementsFromPoint(i / point * window.innerWidth,  window.innerHeight / 2)
    let y = document.elementsFromPoint( window.innerWidth / 2, i / point * window.innerHeight)
    let k2 = document.elementsFromPoint(i/point * window.innerWidth, i / point * window.innerHeight)
    let k1 = document.elementsFromPoint( (point-i)/point * window.innerWidth, (point-i)/point*window.innerHeight)
    isWarp(x)
    isWarp(y)
    isWarp(k2)
    isWarp(k1)
  }

  if(empty === 36){
    // doimg someThings ....
    // 如果为白屏,可以对白屏做一些你自己要干的事情,比如我们会把错误上传到自己公司的管理后台监测模块,方便我们及时知道白屏出现,以及修复
  }
}

最后

这是我针对自己公司的需求的埋点方案和实现,可能并不适合你,可能你有更好的实现,欢迎交流。

可能你喜欢上面这样埋,哈哈哈(🐺保命)。