国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

一步一步搭建前端監(jiān)控系統(tǒng):如何記錄用戶行為?

tolerious / 3154人閱讀

摘要:摘要通過(guò)記錄用戶行為,快速?gòu)?fù)現(xiàn)場(chǎng)景。這是搭建前端監(jiān)控系統(tǒng)的第二章,主要是介紹如何統(tǒng)計(jì)報(bào)錯(cuò),跟著我一步步做,你也能搭建出一個(gè)屬于自己的前端監(jiān)控系統(tǒng)。

摘要: 通過(guò)記錄用戶行為,快速?gòu)?fù)現(xiàn)BUG場(chǎng)景。

作者:一步一個(gè)腳印一個(gè)坑

原文:搭建前端監(jiān)控系統(tǒng)(備選)用戶行為統(tǒng)計(jì)和監(jiān)控篇(如何快速定位線上問(wèn)題)

Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有。

一步一步搭建前端監(jiān)控系統(tǒng)系列博客:

一步一步搭建前端監(jiān)控系統(tǒng):JS錯(cuò)誤監(jiān)控篇

一步一步搭建前端監(jiān)控系統(tǒng):如何將網(wǎng)頁(yè)截圖上報(bào)?

一步一步搭建前端監(jiān)控系統(tǒng):接口請(qǐng)求異常監(jiān)控篇

一步一步搭建前端監(jiān)控系統(tǒng):如何定位前端線上問(wèn)題?

一步一步搭建前端監(jiān)控系統(tǒng):如何記錄用戶行為?

背景:市面上的監(jiān)控系統(tǒng)有很多,大多收費(fèi),對(duì)于小型前端項(xiàng)目來(lái)說(shuō),必然是痛點(diǎn)。另一點(diǎn)主要原因是,功能雖然通用,卻未必能夠滿足我們自己的需求, 所以我們自給自足也許是個(gè)不錯(cuò)的辦法。

這是搭建前端監(jiān)控系統(tǒng)的第二章,主要是介紹如何統(tǒng)計(jì)js報(bào)錯(cuò),跟著我一步步做,你也能搭建出一個(gè)屬于自己的前端監(jiān)控系統(tǒng)。

目前已經(jīng)在運(yùn)行的線上Demo:前端監(jiān)控系統(tǒng)

代碼和講解都放在這篇文章里:監(jiān)控系統(tǒng)介紹及代碼

如果實(shí)在嫌部署麻煩,Demo系統(tǒng)可以提供 7天 的監(jiān)控量,我會(huì)長(zhǎng)期維護(hù):一鍵部署

一直以來(lái), 前端上線的項(xiàng)目,對(duì)于前端程序猿來(lái)說(shuō),完全是一個(gè)黑盒子。 項(xiàng)目一旦上線,我們完全不知道用戶在我們的項(xiàng)目里邊做了什么,跳轉(zhuǎn)到哪里,是不是報(bào)錯(cuò)了。一旦線上用戶出現(xiàn)問(wèn)題,而我們又無(wú)法復(fù)現(xiàn)的時(shí)候,才能體會(huì)到什么叫絕望。 不管多么艱難,問(wèn)題總是會(huì)在哪里等著你。所以,如果我們可以把線上的項(xiàng)目變成一個(gè)白盒子,讓我們能夠知道用戶在線上干了什么,復(fù)現(xiàn)不再困難了,對(duì)前端程序員來(lái)說(shuō),是不是一件好事呢。

接下來(lái)我要寫的是一個(gè)重要的功能, 因?yàn)樗鼧O大的提高了我解決問(wèn)題的能力, 也讓對(duì)我的工作產(chǎn)生了很大的影響。

截止到現(xiàn)在,來(lái)看看我已經(jīng)完成了哪些功能:

PV/UV的統(tǒng)計(jì)上報(bào),js錯(cuò)誤的上報(bào)和分析, 接口的統(tǒng)計(jì)上報(bào),頁(yè)面截屏的統(tǒng)計(jì)上報(bào)。 那么,再補(bǔ)上今天要寫的“用戶點(diǎn)擊行為的上報(bào)”, 我們基本上就能夠分析出一個(gè)用戶在頁(yè)面上干了什么。

一、如何記錄線上用戶的行為

線上用戶的基本行為包括: 訪問(wèn)頁(yè)面, 點(diǎn)擊行為,請(qǐng)求接口行為, js報(bào)錯(cuò)行為, 這幾點(diǎn)基本上能夠清楚的記錄下用戶在線上的所有行為。 當(dāng)然還包括:資源加載行為,滾動(dòng)頁(yè)面行為, 元素進(jìn)入用戶視野等等行為,這些是更為細(xì)節(jié)的行為統(tǒng)計(jì), 也許會(huì)在以后進(jìn)行完善, 但是以上的四種行為已經(jīng)可以完成我們的統(tǒng)計(jì)需求。

訪問(wèn)頁(yè)面, js報(bào)錯(cuò)行為我們已經(jīng)有了,接下來(lái)看看如何統(tǒng)計(jì)點(diǎn)擊行為和請(qǐng)求接口的行為吧。

點(diǎn)擊行為
// 用戶行為日志,繼承于日志基類MonitorBaseInfo
  function BehaviorInfo(uploadType, behaviorType, className, placeholder, inputValue, tagName, innerText) {
    setCommonProperty.apply(this);
    this.uploadType = uploadType;
    this.behaviorType = behaviorType;
    this.className = utils.b64EncodeUnicode(className);
    this.placeholder = utils.b64EncodeUnicode(placeholder);
    this.inputValue = utils.b64EncodeUnicode(inputValue);
    this.tagName = tagName;
    this.innerText = utils.b64EncodeUnicode(encodeURIComponent(innerText));
  }

/**
   * 用戶行為記錄監(jiān)控
   * @param project 項(xiàng)目詳情
   */
  function recordBehavior(project) {
    // 行為記錄開(kāi)關(guān)
    if (project && project.record && project.record == 1) {
      // 記錄行為前,檢查一下url記錄是否變化
      checkUrlChange();
      // 記錄用戶點(diǎn)擊元素的行為數(shù)據(jù)
      document.onclick = function (e) {
        var className = "";
        var placeholder = "";
        var inputValue = "";
        var tagName = e.target.tagName;
        var innerText = "";
        if (e.target.tagName != "svg" && e.target.tagName != "use") {
          className = e.target.className;
          placeholder = e.target.placeholder || "";
          inputValue = e.target.value || "";
          innerText = e.target.innerText.replace(/s*/g, "");
          // 如果點(diǎn)擊的內(nèi)容過(guò)長(zhǎng),就截取上傳
          if (innerText.length > 200) innerText = innerText.substring(0, 100) + "... ..." + innerText.substring(innerText.length - 99, innerText.length - 1);
          innerText = innerText.replace(/s/g, "");
        }
        var behaviorInfo = new BehaviorInfo(ELE_BEHAVIOR, "click", className, placeholder, inputValue, tagName, innerText);
        behaviorInfo.handleLogInfo(ELE_BEHAVIOR, behaviorInfo);
      }
    }
  };

我們先來(lái)看一下點(diǎn)擊行為的代碼,其實(shí)很簡(jiǎn)單,就是重寫一下document的onclick方法,然后把相應(yīng)的元素的屬性,內(nèi)容等等保存起來(lái), 但是,我們費(fèi)了這么大的力氣保存了如此多的日志,就為了簡(jiǎn)單的記錄一下用戶的點(diǎn)擊行為,實(shí)在太浪費(fèi)了。 所以,這個(gè)點(diǎn)擊行為統(tǒng)計(jì)會(huì)被添加到未來(lái)的留存分析當(dāng)中去,到時(shí)候能夠?qū)崿F(xiàn)無(wú)埋點(diǎn)記錄日志的功能,讓我們的監(jiān)控系統(tǒng)更加的強(qiáng)大和豐富。留存分析會(huì)參考GrowingIo, 有興趣可以了解一下。

我們需要記錄下元素的className, tagName, innerText等等,我們需要足夠的的內(nèi)容才能夠確定用戶點(diǎn)擊的是哪個(gè)按鈕。這種方式比較弱智,將會(huì)在以后寫留存分析功能的時(shí)候進(jìn)行完善一下,但是目前足以滿足我們的要求了。

請(qǐng)求接口行為
// 接口請(qǐng)求日志,繼承于日志基類MonitorBaseInfo
  function HttpLogInfo(uploadType, url, status, statusText, statusResult, currentTime) {
    setCommonProperty.apply(this);
    this.uploadType = uploadType;
    this.httpUrl = utils.b64EncodeUnicode(url);
    this.status = status;
    this.statusText = statusText;
    this.statusResult = statusResult;
    this.happenTime = currentTime;
  }

/**
   * 頁(yè)面接口請(qǐng)求監(jiān)控
   */
  function recordHttpLog() {
    // 監(jiān)聽(tīng)ajax的狀態(tài)
    function ajaxEventTrigger(event) {
      var ajaxEvent = new CustomEvent(event, {
        detail: this
      });
      window.dispatchEvent(ajaxEvent);
    }
    var oldXHR = window.XMLHttpRequest;
    function newXHR() {
      var realXHR = new oldXHR();
      realXHR.addEventListener("abort", function () { ajaxEventTrigger.call(this, "ajaxAbort"); }, false);
      realXHR.addEventListener("error", function () { ajaxEventTrigger.call(this, "ajaxError"); }, false);
      realXHR.addEventListener("load", function () { ajaxEventTrigger.call(this, "ajaxLoad"); }, false);
      realXHR.addEventListener("loadstart", function () { ajaxEventTrigger.call(this, "ajaxLoadStart"); }, false);
      realXHR.addEventListener("progress", function () { ajaxEventTrigger.call(this, "ajaxProgress"); }, false);
      realXHR.addEventListener("timeout", function () { ajaxEventTrigger.call(this, "ajaxTimeout"); }, false);
      realXHR.addEventListener("loadend", function () { ajaxEventTrigger.call(this, "ajaxLoadEnd"); }, false);
      realXHR.addEventListener("readystatechange", function() { ajaxEventTrigger.call(this, "ajaxReadyStateChange"); }, false);
      return realXHR;
    }

    window.XMLHttpRequest = newXHR;
    window.addEventListener("ajaxLoadStart", function(e) {
      var currentTime = new Date().getTime()
      setTimeout(function () {
        var url = e.detail.responseURL;
        var status = e.detail.status;
        var statusText = e.detail.statusText;
        if (!url || url.indexOf(HTTP_UPLOAD_LOG_API) != -1) return;
        var httpLogInfo = new HttpLogInfo(HTTP_LOG, url, status, statusText, "發(fā)起請(qǐng)求", currentTime);
        httpLogInfo.handleLogInfo(HTTP_LOG, httpLogInfo);
      }, 2000)
    });
    window.addEventListener("ajaxLoadEnd", function(e) {
      var currentTime = new Date().getTime()
      var url = e.detail.responseURL;
      var status = e.detail.status;
      var statusText = e.detail.statusText;
      if (!url || url.indexOf(HTTP_UPLOAD_LOG_API) != -1) return;
      var httpLogInfo = new HttpLogInfo(HTTP_LOG, url, status, statusText, "請(qǐng)求返回", currentTime);
      httpLogInfo.handleLogInfo(HTTP_LOG, httpLogInfo);
    });

  }

讓我們來(lái)看看接口行為統(tǒng)計(jì)的代碼先,本來(lái)這個(gè)我想多帶帶拿出來(lái)說(shuō)一說(shuō)的,但是現(xiàn)在么有那么多時(shí)間把它相關(guān)的功能開(kāi)發(fā)出來(lái),所以只寫了一個(gè)簡(jiǎn)版的。

接口行為的統(tǒng)計(jì)包括: 發(fā)起請(qǐng)求,接收請(qǐng)求,接收狀態(tài),請(qǐng)求時(shí)長(zhǎng), 通過(guò)前端對(duì)接口的統(tǒng)計(jì)和分析,我們是可以觀察出線上接口的質(zhì)量,同時(shí)也能夠?qū)η岸说倪壿嬜龀鱿鄳?yīng)的調(diào)整,已達(dá)到頁(yè)面加載的最佳效果。 數(shù)據(jù)庫(kù)字段定義都在分析后臺(tái)的項(xiàng)目里, 可以直接去看。

首先,我們要監(jiān)聽(tīng)頁(yè)面的ajax請(qǐng)求, 如上所示,寫了一段監(jiān)聽(tīng)ajax請(qǐng)求的代碼(我是在網(wǎng)上扒下來(lái)的 thanks), 可以監(jiān)聽(tīng)到頁(yè)面上所有的ajax請(qǐng)求,對(duì)整個(gè)ajax請(qǐng)求過(guò)程進(jìn)行了原子性分析,我們可以監(jiān)聽(tīng)到請(qǐng)求過(guò)程中任何一個(gè)時(shí)段的事件,非常好用。 但是,有一點(diǎn)非常重要, 如果你的項(xiàng)目里邊用的是fetch請(qǐng)求數(shù)據(jù)的話, 那么這些監(jiān)聽(tīng)就無(wú)效了。 因?yàn)閒etch代碼是瀏覽器注入的, 肯定先用監(jiān)控代碼執(zhí)行,然后你再監(jiān)聽(tīng)ajax就一點(diǎn)用都沒(méi)有了。 所以你需要在寫好ajax監(jiān)聽(tīng)之后,重寫fetch代碼, 這樣就可以生效了。好了,這部分并不是這篇幅的重點(diǎn),我們就說(shuō)到這里。

二、如何查詢線上用戶的行為

終于,我們把剩下的兩種行為記錄都成功上傳了,那么該如果把他們都查詢出來(lái)呢。我們先來(lái)看一下頁(yè)面上我查詢出來(lái)的結(jié)果。

因?yàn)槠聊惶。瑹o(wú)法展示所有的記錄,記錄信息包含:行為名稱,行為發(fā)生時(shí)間, 行為發(fā)生頁(yè)面, 錯(cuò)誤信息, 錯(cuò)誤截圖, 以及用戶自定義上傳截圖的時(shí)機(jī)。

說(shuō)到這里有幾個(gè)小問(wèn)題需要注意。

因?yàn)槭怯肑s做探針,記錄日志的時(shí)候很難保證每次記錄都可以把用戶的userId插入進(jìn)去

所以我們給每個(gè)用戶都定義一個(gè)customerKey來(lái)做區(qū)分,如果用戶不卸載app和清理app的緩存, customerKey將保持不變

在查詢用戶的行為記錄的時(shí)候,需要先查詢出用戶所有的customerKey(可能有多個(gè)),再用customerKey進(jìn)行查詢,便可以得到準(zhǔn)確的結(jié)果。

三、如何分析線上用戶的行為

其實(shí)我們做了這么多,記錄了這么多,就是為了這個(gè)目的:分析行為,快速定位問(wèn)題。

那么我們?nèi)绾味ㄎ粏?wèn)題呢,我可以舉例說(shuō)明一下:

JS報(bào)錯(cuò)阻斷行為,我們可以看到發(fā)生錯(cuò)誤的前后行為,就能夠快速準(zhǔn)確定位問(wèn)題。

復(fù)雜的鏈接跳轉(zhuǎn)發(fā)生了錯(cuò)誤。有些錯(cuò)誤是前端頁(yè)面會(huì)經(jīng)過(guò)復(fù)雜的跳轉(zhuǎn),回退之后才發(fā)生的,就算測(cè)試人員也很難測(cè)試出這種問(wèn)題,因?yàn)榫€上的用戶的任何行為都有可能出現(xiàn)。往往我們知道的只是他在最后停留的頁(yè)面發(fā)生了錯(cuò)誤。 如此,經(jīng)過(guò)我們排查行為日志, 就能夠復(fù)現(xiàn)出用戶的行為, 從而復(fù)現(xiàn)BUG

接口異常。 正常情況下,前端的接口都會(huì)設(shè)置超時(shí)時(shí)間的, 但是呢, 后臺(tái)接口排查發(fā)現(xiàn)正常, 而前端就是無(wú)法正常執(zhí)行, 這種問(wèn)題沒(méi)有顯示的錯(cuò)誤現(xiàn)象,而線上的反饋并不能夠準(zhǔn)確,前端只能背鍋了。 而日志記錄是可以把請(qǐng)求發(fā)出時(shí)間和返回時(shí)間記錄下來(lái), 是否超時(shí),看一眼就知道。

線上的用戶根本就不會(huì)反饋異常, 他們能做的只是把最后一眼能看到的東西告訴你。 天知道他們之前經(jīng)歷了什么步驟。 最終的結(jié)果是,前端有問(wèn)題,然后背鍋,哈哈。

總之, 我們知道用戶在頁(yè)面上干了什么, 便不再擔(dān)心問(wèn)題出現(xiàn), 遇見(jiàn)問(wèn)題也不會(huì)再手忙腳亂了。

關(guān)于Fundebug

Fundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java線上應(yīng)用實(shí)時(shí)BUG監(jiān)控。 自從2016年雙十一正式上線,F(xiàn)undebug累計(jì)處理了10億+錯(cuò)誤事件,付費(fèi)客戶有陽(yáng)光保險(xiǎn)、核桃編程、荔枝FM、掌門1對(duì)1、微脈、青團(tuán)社等眾多品牌企業(yè)。歡迎大家免費(fèi)試用!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/106358.html

相關(guān)文章

  • 步一搭建前端監(jiān)控系統(tǒng)如何定位前端線上問(wèn)題?

    摘要:一直以來(lái),前端的線上問(wèn)題很難定位,因?yàn)樗l(fā)生于用戶的一系列操作之后。當(dāng)然,這些問(wèn)題并非不能克服,讓我們來(lái)一起看看如何去定位線上的問(wèn)題吧。地址參考一步一步搭建前端監(jiān)控系統(tǒng)錯(cuò)誤監(jiān)控篇一步一步搭建前端監(jiān)控系統(tǒng)接口請(qǐng)求異常監(jiān)控篇 摘要: 記錄用戶行為,排查線上BUG。 作者:一步一個(gè)腳印一個(gè)坑 原文:如何定位前端線上問(wèn)題(如何排查前端生產(chǎn)問(wèn)題) Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所...

    aaron 評(píng)論0 收藏0
  • 步一搭建前端監(jiān)控系統(tǒng)如何將網(wǎng)頁(yè)截圖上報(bào)?

    摘要:目前已經(jīng)在運(yùn)行的線上前端監(jiān)控系統(tǒng)代碼和講解都放在這篇文章里監(jiān)控系統(tǒng)介紹及代碼用戶對(duì)前端程序員來(lái)說(shuō),就是一個(gè)黑匣子。 摘要: 通過(guò)錄屏或者截圖,快速?gòu)?fù)現(xiàn)BUG場(chǎng)景。 作者:一步一個(gè)腳印一個(gè)坑 原文:搭建前端監(jiān)控系統(tǒng)(備選)Js截圖上報(bào)篇 Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有。 PS:本文關(guān)于Fundebug錄屏功能的內(nèi)容有些不準(zhǔn)確的地方,比如錄屏并非通過(guò)截圖實(shí)現(xiàn)的,錄屏插件...

    Martin91 評(píng)論0 收藏0
  • 步一搭建前端監(jiān)控系統(tǒng):JS錯(cuò)誤監(jiān)控

    摘要:摘要徒手寫錯(cuò)誤監(jiān)控。為什么用定時(shí)器呢,因?yàn)樵趩雾?yè)應(yīng)用中,路由的切換和地址欄的變化是無(wú)法被監(jiān)控的,我確實(shí)沒(méi)有想到特別好的辦法來(lái)監(jiān)控,所以用了這種方式,如果有人有更好的辦法,請(qǐng)給我留言,謝謝。 摘要: 徒手寫JS錯(cuò)誤監(jiān)控。 作者:一步一個(gè)腳印一個(gè)坑 原文:搭建前端監(jiān)控系統(tǒng)(二)JS錯(cuò)誤監(jiān)控篇 Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有。 背景:市面上的監(jiān)控系統(tǒng)有很多,大多收費(fèi),對(duì)于...

    EdwardUp 評(píng)論0 收藏0
  • 步一搭建前端監(jiān)控系統(tǒng):接口請(qǐng)求異常監(jiān)控

    摘要:參考一步一步搭建前端監(jiān)控系統(tǒng)錯(cuò)誤監(jiān)控篇用插件記錄網(wǎng)絡(luò)請(qǐng)求異常關(guān)于專注于微信小程序微信小游戲支付寶小程序和線上應(yīng)用實(shí)時(shí)監(jiān)控。 摘要: 如何監(jiān)控HTTP請(qǐng)求錯(cuò)誤? 作者:一步一個(gè)腳印一個(gè)坑 原文:搭建前端監(jiān)控系統(tǒng)(四)接口請(qǐng)求異常監(jiān)控篇 Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有。 背景:市面上的監(jiān)控系統(tǒng)有很多,大多收費(fèi),對(duì)于小型前端項(xiàng)目來(lái)說(shuō),必然是痛點(diǎn)。另一點(diǎn)主要原因是,功能雖然...

    dreamtecher 評(píng)論0 收藏0
  • 前端之從零開(kāi)始系列

    摘要:只有動(dòng)手,你才能真的理解作者的構(gòu)思的巧妙只有動(dòng)手,你才能真正掌握一門技術(shù)持續(xù)更新中項(xiàng)目地址求求求源碼系列跟一起學(xué)如何寫函數(shù)庫(kù)中高級(jí)前端面試手寫代碼無(wú)敵秘籍如何用不到行代碼寫一款屬于自己的類庫(kù)原理講解實(shí)現(xiàn)一個(gè)對(duì)象遵循規(guī)范實(shí)戰(zhàn)手摸手,帶你用擼 Do it yourself!!! 只有動(dòng)手,你才能真的理解作者的構(gòu)思的巧妙 只有動(dòng)手,你才能真正掌握一門技術(shù) 持續(xù)更新中…… 項(xiàng)目地址 https...

    Youngdze 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<