Home >Web Front-end >JS Tutorial >A preliminary exploration of the buried point system

A preliminary exploration of the buried point system

coldplay.xixi
coldplay.xixiforward
2020-09-15 16:24:552635browse

A preliminary exploration of the buried point system

Related learning recommendations: javascript video tutorial

Preface

There have been a lot of miscellaneous things recently , it’s rare to take the time to make up for the previous series, and the series that owes you the points is now starting to take off

Why is the point system needed

In the movie

Front-end development siege Shi Kai happily codes, and is very proud of the separate development of business and UI. Various design patterns and algorithm optimizations have been implemented in turn. The code is perfect (the best labor code in the world), there are no BUGs, the program is perfect, and the compatibility is No. 1. The code can be typed and resisted with high quality. You can easily clock in after get off work and go home to take care of your baby.

In reality

In fact, the development environment and the production environment are not the same, and no matter how perfect the testing process is, there will still be missed tests. Considering the existence of a series of uncertain factors such as the user's client environment, network environment, etc. So you must remember the three major principles during the development process (

My nonsense

)

    There is no perfect code, only undiscovered BUGs
  1. Never trust the test environment
  2. , no test environment covers all online situationsIf there is no feedback online, don’t doubt it, the problem should be Hidden very deep, very deep
  3. What is a buried point system

Buried points are like cameras in the city. From a product perspective, it can monitor the user’s movements in our products The behavioral trajectories in it provide a basis for product iteration and project stability.

WHO, WHEN, WHERE, HOW, and WHAT are the basic dimensions of data collection

. For front-end development, you can monitor page resource loading performance, exceptions, etc., provide page experience and health index, provide a basis for subsequent performance optimization, and report exceptions and occurrence scenarios in a timely manner. This enables timely correction of problems and improvement of project quality.

Buried points can be roughly divided into three categories:

    Traceless buried points
  1. - All information on the page is collected indiscriminately, including page entry and exit, event clicks, etc. Data flushing is required to obtain useful information
  2. Visual buried points
  3. - Obtain specific points based on the generated page structure, and analyze the points separately
  4. Business code Manual burying
  5. - According to the specific complex business, remove the above two areas that cannot be covered and bury the business code
Typical scenariosAdvantages Insufficient

In most cases, we can collect all the information data through traceless buried points, and then cooperate with the visual buried points to specifically locate a certain point, so that most of the buried point information can be analyzed accordingly.

In special circumstances, you can add more business codes to manually bury the points to deal with special scenarios (in most cases, strong business has nothing to do with normal clicks and refresh events, and information that needs to be reported)

Buried Point SDK Development

Buried Point Data Collection and Analysis

  • Basic Event Data
    • Event Occurrence Time
    • Snapshot of Page Information at the Time of Occurrence
  • Page
    • Page PV, UV
    • User page stay time
    • Page jump event
    • Page enters the background
    • User leaves page
  • User information
    • User uid
    • User device fingerprint
    • Device information
    • ip
    • Positioning
  • User operation behavior
    • User click
      • Click target
  • Page AJAX request
    • Request successful
    • Request failed
    • Request timeout
  • Page error
    • Resource loading error
    • JS running error
  • New resource loading performance
  • Picture
  • Script
  • Page loading performance

The above data defines hidden events through 3 dimensions

  • ·LEVEL : Describe the log level of buried data
    • INFO: Some user operations, request success, resource loading, etc. normal data records
    • ERROR : Data records of JS errors, interface errors, etc.
    • DEBUG: Reserved for developers to return data records to eliminate bugs through manual calls
    • WARN: Reserved for developers to return data records of abnormal user behavior through manual calls
  • CATEGORY: Description Classification of buried point data
    • TRACK: The life cycle of the buried point SDK object manages the entire buried point data.
      • WILL_MOUNT: The sdk object is about to be initialized and loaded, a default ID is generated, and all related events are tracked
      • DID_MOUNTED: The sdk object is initialized, and the main acquisition Asynchronous operations of device fingerprints, etc. are completed
    • AJAX: AJAX related data
    • ERROR: Exception related in the page Data
    • PERFORMANCE: Performance-related data
    • OPERATION: User operation-related data
  • EVENT_NAME: Specific event name

According to the above dimensions, we can simply design the following architecture

A preliminary exploration of the buried point system

According to the architecture of the above figure, proceed to the following specific code development

Proxy request

There are currently 2 main types in the browser There are three request methods, one is XMLHttpRequest, and the other is Fetch.

Agent XMLHttpRequest

function NewXHR() {  var realXHR: any = new OldXHR(); // 代理模式里面有提到过
  realXHR.id = guid()  const oldSend = realXHR.send;

  realXHR.send = function (body) {
    oldSend.call(this, body)    //记录埋点
  }
  realXHR.addEventListener('load', function () {    //记录埋点
  }, false);
  realXHR.addEventListener('abort', function () {    //记录埋点
  }, false);

  realXHR.addEventListener('error', function () {    //记录埋点
  }, false);
  realXHR.addEventListener('timeout', function () {    //记录埋点
  }, false);  return realXHR;
}复制代码

Agent Fetch

 const oldFetch = window.fetch;  function newFetch(url, init) {    const fetchObj = {      url: url,      method: method,      body: body,
    }
    ajaxEventTrigger.call(fetchObj, AJAX_START);    return oldFetch.apply(this, arguments).then(function (response) {      if (response.ok) {       //记录埋点
      } else {       //上报错误
      }      return response
    }).catch(function (error) {
      fetchObj.error = error        //记录埋点      
        throw error
    })
  }复制代码

Listen to the PV of the page, UV

before entering page, we use an algorithm to generate a unique session id, which serves as the global ID for this burying behavior, and reports the user ID, device fingerprint, and device information. When the user is not logged in, UV is calculated through the device fingerprint and PV is calculated through the session id.

Exception capture

Exception is an unusual accident that interferes with the normal flow of the program

RUNTIME ERROR

Can be passed in JS window.onerror and window.addEventListener('error', callback) capture runtime exceptions. Generally, window.onerror is used, which has better compatibility.

window.onerror = function(message, url, lineno, columnNo, error) {    const lowCashMessage = message.toLowerCase()    if(lowCashMessage.indexOf('script error') > -1) {      return
    }    const detail = {      url: url    
      filename: filename,      columnNo: columnNo,      lineno: lineno,      stack: error.stack,      message: message
    }    //记录埋点}复制代码

Script Error

Here we filter Script Error, which is mainly caused by errors reported by third-party cross-domain scripts loaded in the page, such as those hosted on js script in third-party CDN. This type of problem is more difficult to troubleshoot. The solution is:

  • Open CORS (Cross Origin Resource Sharing, cross-domain resource sharing), follow the following steps
    • 05f1bd78c9bf8ef485ba6d27b73916f72cacc6d41bbb37262a98f745aa00fbf0
    • ModifyAccess-Control-Allow-Origin: * | Specify domain name
  • Use try catch
      <script scr="crgt.js"></script> //加载crgt脚本,window.crgt = {getUser: () => string}
      try{      window.crgt.getUser();
      }catch(error) {      throw error // 输出正确的错误堆栈
      }复制代码

Promise reject

js Unable to pass when asynchronous exception onerror Method capture, when the Promise object is rejected and not processed at the same time An unhandledrejection error will be thrown and will not be caught by the above method, so a separate handling event needs to be added.

window.addEventListener("unhandledrejection", event => {  throw event.reason
});复制代码

资源加载异常

在浏览器中,可以通过 window.addEventListener('error', callback) 的方式监听资源加载异常,比如 js 或者 css 脚本文件丢失。

window.addEventListener(&#39;error&#39;, (event) => {  if (event.target instanceof HTMLElement) {    const target = parseDom(event.target, [&#39;src&#39;]);    const detail = {      target: target,      path: parseXPath(target),
    }    //  记录埋点
  }
}, true)复制代码

监听用户行为

通过 addEventListener click 监听 click 事件

window.addEventListener(&#39;click&#39;, (event) => {    //记录埋点}, true)复制代码

在这里通过组件的 displaName 来定位元素的位置,displaName 表示组件的文件目录,比如 src/components/Form.js 文件导出的组件 FormItem 通过 babel plugin 自动添加属性 @components/Form.FormItem,或者使用者主动给组件添加 static 属性 displayName

页面路由变化

  • hashRouter 监听页面hash变化,对hash进行解析
window.addEventListener(&#39;hashchange&#39;, event => {  const { oldURL, newURL } = event;  const oldURLObj = url.parseUrl(oldURL);  const newURLObj = url.parseUrl(newURL);  const from = oldURLObj.hash && url.parseHash(oldURLObj.hash);  const to = newURLObj.hash && url.parseHash(newURLObj.hash);  if(!from && !to ) return;  // 记录埋点})复制代码

监听页面离开

通过 addEventListener beforeunload 监听离开页面事件

window.addEventListener(&#39;beforeunload&#39;, (event) => {    //记录埋点})复制代码

SDK 架构

class Observable {    constructor(observer) {
        observer(this.emit)
    }
    emit = (data) => {        this.listeners.forEach(listener => {
            listener(data)
        })
    }
    listeners = [];
    
    subscribe = (listener) => {        this.listeners.push(listeners);        return () => {            const index = this.listeners.indexOf(listener);            if(index === -1) {                return false
            }            
            this.listeners.splice(index, 1);            return true;
        }
     }
}复制代码
const clickObservable = new Observable((emit) => {    window.addEventListener(&#39;click&#39;, emit)
})复制代码

然而在处理 ajax,需要将多种数据组合在一起,需要进行 merg 操作,则显得没有那么优雅,也很难适应后续复杂的数据流的操作。

const ajaxErrorObservable = new Observable((emit) => {    window.addEventListener(AJAX_ERROR, emit)
})const ajaxSuccessObservable = new Observable((emit) => {    window.addEventListener(AJAX_SUCCESS, emit)
})const ajaxTimeoutObservable = new Observable((emit) => {    window.addEventListener(AJAX_TIMEOUT, emit)
})复制代码

可以选择 RxJS 来优化代码

export const ajaxError$ = fromEvent(window, &#39;AJAX_ERROR&#39;, true)export const ajaxSuccess$ = fromEvent(window, &#39;AJAX_SUCCESS&#39;, true)export const ajaxTimeout$ = fromEvent(window, &#39;AJAX_TIMEOUT&#39;, true)复制代码
ajaxError$.pipe(
    merge(ajaxSuccess$, ajaxTimeout$), 
    map(data=> (data) => ({category: &#39;ajax&#39;, data; data}))
    subscribe(data => console.log(data))复制代码

通过 merge, map 两个操作符完成对数据的合并和处理。

数据流

A preliminary exploration of the buried point system

项目结构

  • core
    • event$ 数据流合并
    • snapshot 获取当前设备快照,例如urluserIDrouter
    • track 埋点类,组合数据流和日志。
  • logger
    • logger 日志类
      • info
      • warn
      • debug
      • error
  • observable
    • ajax
    • beforeUpload
    • opeartion
    • routerChange
    • logger
    • track

参考

  • www.alibabacloud.com/help/zh/doc…

结尾

自建埋点系统是一个需要前后端一起合作的事情,如果人力不足的情况下,建议使用第三方分析插件,例如 Sentry 就能足够满足大部分日常使用

但还是建议多了解,在第三方插件出现不能满足业务需求的时候,可以顶上。

想了解更多编程学习,敬请关注php培训栏目!


Code buried points
Visual buried points Traceless buried points
Invisible buried points cannot be covered, for example, if business data is required Simple and standardized page scenarios Simple and standardized page scenarios,
Clear business data Low development cost, operators can directly configure relevant buried points No configuration required, data can be traced back
The data cannot be traced back, and the development cost is high Cannot be associated with business data, the data cannot be traced back The amount of data is large, and the business data cannot be associated

The above is the detailed content of A preliminary exploration of the buried point system. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.im. If there is any infringement, please contact admin@php.cn delete