搜尋
首頁web前端js教程初探埋點系統

初探埋點系統

Sep 15, 2020 pm 04:24 PM
javascript

初探埋點系統

相關學習推薦:javascript影片教學

#前言

最近雜七雜八的事情比較多,難得花時間彌補之前的系列,欠大家的埋設系列現在開始走起來

為什麼需要埋點系統

電影中

前端開發攻城獅開開心心的coding,非常自豪的進行了業務、UI 分離開發,各種設計模式、算法優化輪番上陣,代碼寫的Perfect(勞資代碼天下第一),沒有BUG,程序完美,兼容性No. 1,程式碼能打能抗品質高。下班輕鬆打卡,回家看娃。

現實中

實際上,開發環境與生產環境並不能等同,並且測試的過程再完善,依然會有漏測的情況存在。考慮到使用者使用客戶端環境、網路環境等等一系列的不確定因素存在。

所以在開發過程中一定要記得三大原則(我胡詌的

  1. 沒有完美的程式碼,只有沒發現的BUG
  2. 絕對不要相信測試環境,沒有一種測試環境都涵蓋所有線上情況
  3. 如果線上沒有一點回饋,不要懷疑,問題應該藏得很深、很深

什麼是埋點系統

埋點就像城市中的攝像頭,從產品的角度考慮,它可以監控到用戶在我們產品裡的行為軌跡,為產品的迭代、專案的穩定性提供依據,WHO、WHEN、WHERE、HOW、WHAT 是埋點擷取資料的基礎維度

對前端開發而言,可以監控頁面資源載入效能,異常等等,提供了頁面體驗和健康指數,為後續效能最佳化提供依據,及時回報異常和發生場景。從而能夠及時修正問題,提升專案品質等。

埋點可以大概分為三類:

  1. 無痕埋點 - 無差別收集頁面所有資訊包括頁面進出、事件點擊等等,需要進行資料沖洗才能取得有用資訊
  2. 視覺化埋點 - 根據產生的頁面結構取得特定點位,單獨埋點分析
  3. 業務程式碼手動埋點 - 根據具體複雜的業務,除掉上述兩種不能涵蓋的地方進行業務代碼埋點

程式碼埋點 視覺化埋點 無痕埋點
典型場景 無痕埋點無法覆寫到,例如需要業務資料 簡單規範的頁面場景 #簡單規範的頁面場景,
優勢 業務資料明確 開發成本低,營運人員可直接進行相關埋點配置 無需配置,資料可回溯
不足 資料不可回溯,開發成本高 無法關聯業務數據,資料不可回溯 資料量較大,無法關聯業務資料

大部分情況,我們可以透過無痕埋點收集到所有的資訊數據,再配合可視化埋點,能夠具體定位到某一個點位,這樣大部分的埋點資訊都據此分析出來。

在特殊情況下,可以多加上業務代碼手動埋點,處理一下特別的場景(大部分情況是走強業務與正常的點擊,刷新事件無關需要上報的信息)

埋點SDK 開發

埋點資料收集分析

  • 事件基本資料
    • 事件發生時間
    • 發生時頁面資訊快照
  • 頁面
    • 頁面PV,UV
    • 用戶頁面停留時間
    • 頁面跳轉事件
    • 頁面進入後台
    • 使用者離開頁面
  • 使用者資訊
    • 使用者uid
    • 使用者裝置指紋
    • 裝置資訊
    • ip
    • 定位
  • 使用者操作行為
    • 使用者點選
      • #點選目標
    ##頁面AJAX 請求
  • #請求成功
    • #請求失敗
    • 請求逾時
##頁面報錯

資源載入錯誤

JS 執行報錯
  • 資源載入新效能
    • 圖片腳本
    • 頁面載入效能
    • 上面的資料透過
    • 3 個維度來定義埋點事件
    • ·LEVEL : 描述埋點資料的日誌等級
  • INFO
  • :某些使用者操作,請求成功,資源載入等等正常的資料記錄
      ERROR
    • : JS報錯,介面報錯等等錯誤類型的資料記錄
        DEBUG
      • : 預留開發人員透過手動呼叫的方式回傳排除bug的資料記錄
      • WARN
      • : 預留開發人員透過手動呼叫的方式回傳非正常使用者行為的的資料記錄
      ##CATEGORY
    • :描述埋點資料的分類
    • TRACK
    • : 埋點SDK物件的生命週期管理整個埋點資料。
    • WILL_MOUNT
    • :sdk物件即將初始化加載,產生一個預設ID,追蹤全部相關事件
    • DID_MOUNTED
    • :sdk物件初始化完成,主要獲取設備指紋等等的非同步操作完成
    AJAX
  • : AJAX相關資料
  • ERROR
  • :頁面中的例外相關資料

PERFORMANCE: 關於效能相關資料

初探埋點系統#OPERATION
: 使用者操作相關資料

#EVENT_NAME
:具體的事件名稱

根據上述的維度,我們可以簡單設計如下的架構

##根據上圖的架構,再進行下面的具體程式碼開發

##在瀏覽器中現在主要有2種請求方式,一個是

XMLHttpRequest

, 一個是Fetch代理XMLHttpRequest<pre class='brush:php;toolbar:false;'>function NewXHR() { var realXHR: any = new OldXHR(); // 代理模式里面有提到过 realXHR.id = guid() const oldSend = realXHR.send; realXHR.send = function (body) { oldSend.call(this, body) //记录埋点 } realXHR.addEventListener(&amp;#39;load&amp;#39;, function () { //记录埋点 }, false); realXHR.addEventListener(&amp;#39;abort&amp;#39;, function () { //记录埋点 }, false); realXHR.addEventListener(&amp;#39;error&amp;#39;, function () { //记录埋点 }, false); realXHR.addEventListener(&amp;#39;timeout&amp;#39;, function () { //记录埋点 }, false); return realXHR; }复制代码</pre>代理Fetch<pre class='brush:php;toolbar:false;'> 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 }) }复制代码</pre>監聽頁面的

PV

UV

#在進入頁面時,我們透過演算法產生一個唯一

session id

,作為這次埋點行為的全域id,回報用戶id,裝置指紋,裝置資訊。在使用者未登入的情況下,透過裝置指紋來計算 UV,透過 session id計算 PV異常捕獲

異常就是乾擾程式的正常流程的不尋常事故

RUNTIME ERRORJS中可以通過

window.onerror
  • window.addEventListener('error', callback) 捕捉運行時異常,一般使用window.onerror
      ,它相容性更好。
    • window.onerror = function(message, url, lineno, columnNo, error) {    const lowCashMessage = message.toLowerCase()    if(lowCashMessage.indexOf(&#39;script error&#39;) > -1) {      return
          }    const detail = {      url: url    
            filename: filename,      columnNo: columnNo,      lineno: lineno,      stack: error.stack,      message: message
          }    //记录埋点}复制代码
      Script Error
    • 在這裡我們過濾了
    • Script Error, 它產生的原因主要是頁面中載入的第三方跨域腳本報錯,例如託管在第三方CDN 中的js
    • 腳本。這類問題比較難以檢驗。解決的方法有:
  • 開啟CORS(Cross Origin Resource Sharing,跨域資源共享),如下步驟

修改Access-Control-Allow-Origin: * | 指定網域名稱

#使用###try catch###
  <script scr="crgt.js"></script> //加载crgt脚本,window.crgt = {getUser: () => string}
  try{      window.crgt.getUser();
  }catch(error) {      throw error // 输出正确的错误堆栈
  }复制代码
##########Promise reject#########js### 在非同步異常時無法通過###onerror### 方法捕獲,當Promise 物件在reject 時,同時並沒有進行處理時 會拋出一個 ###unhandledrejection### 的錯誤,並不會被上述的方法所捕獲,所以需要添加單獨的處理事件。 ###
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 两个操作符完成对数据的合并和处理。

数据流

初探埋點系統

项目结构

  • 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培训栏目!

以上是初探埋點系統的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:juejin。如有侵權,請聯絡admin@php.cn刪除
C和JavaScript:連接解釋C和JavaScript:連接解釋Apr 23, 2025 am 12:07 AM

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

從網站到應用程序:JavaScript的不同應用從網站到應用程序:JavaScript的不同應用Apr 22, 2025 am 12:02 AM

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python vs. JavaScript:比較用例和應用程序Python vs. JavaScript:比較用例和應用程序Apr 21, 2025 am 12:01 AM

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C/C在JavaScript口譯員和編譯器中的作用C/C在JavaScript口譯員和編譯器中的作用Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在行動中:現實世界中的示例和項目JavaScript在行動中:現實世界中的示例和項目Apr 19, 2025 am 12:13 AM

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

了解JavaScript引擎:實施詳細信息了解JavaScript引擎:實施詳細信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python vs. JavaScript:學習曲線和易用性Python vs. JavaScript:學習曲線和易用性Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。