search
HomeWeb Front-endJS TutorialA preliminary exploration of the buried point system

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
    • <srcipt src="another%20domain/main.js" cossorigin="anonymous"></srcipt>
    • 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. If there is any infringement, please contact admin@php.cn delete
Javascript Data Types : Is there any difference between Browser and NodeJs?Javascript Data Types : Is there any difference between Browser and NodeJs?May 14, 2025 am 12:15 AM

JavaScript core data types are consistent in browsers and Node.js, but are handled differently from the extra types. 1) The global object is window in the browser and global in Node.js. 2) Node.js' unique Buffer object, used to process binary data. 3) There are also differences in performance and time processing, and the code needs to be adjusted according to the environment.

JavaScript Comments: A Guide to Using // and /* */JavaScript Comments: A Guide to Using // and /* */May 13, 2025 pm 03:49 PM

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python vs. JavaScript: A Comparative Analysis for DevelopersPython vs. JavaScript: A Comparative Analysis for DevelopersMay 09, 2025 am 12:22 AM

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Python vs. JavaScript: Choosing the Right Tool for the JobPython vs. JavaScript: Choosing the Right Tool for the JobMay 08, 2025 am 12:10 AM

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript: Understanding the Strengths of EachPython and JavaScript: Understanding the Strengths of EachMay 06, 2025 am 12:15 AM

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScript's Core: Is It Built on C or C  ?JavaScript's Core: Is It Built on C or C ?May 05, 2025 am 12:07 AM

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript Applications: From Front-End to Back-EndJavaScript Applications: From Front-End to Back-EndMay 04, 2025 am 12:12 AM

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Python vs. JavaScript: Which Language Should You Learn?Python vs. JavaScript: Which Language Should You Learn?May 03, 2025 am 12:10 AM

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.