成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

微信小程序數(shù)據(jù)統(tǒng)計(jì)和錯(cuò)誤統(tǒng)計(jì)的實(shí)現(xiàn)

jerryloveemily / 1366人閱讀

摘要:同時(shí),還要攔截微信發(fā)生網(wǎng)絡(luò)請求的方法,這樣可以拿到網(wǎng)絡(luò)請求相關(guān)的數(shù)據(jù),最后,為了能統(tǒng)計(jì)到錯(cuò)誤,還需要攔截微信發(fā)生錯(cuò)誤的方法。

某些情況下我們需要對小程序某些用戶的行為進(jìn)行數(shù)據(jù)進(jìn)行統(tǒng)計(jì),比如統(tǒng)計(jì)某個(gè)頁面的UV,
PV等,統(tǒng)計(jì)某個(gè)功能的使用情況等。好讓產(chǎn)品對于產(chǎn)品的整個(gè)功能有所了解。
在網(wǎng)頁里,我們很多人都用過谷歌統(tǒng)計(jì),小程序里也有一些第三方數(shù)據(jù)統(tǒng)計(jì)的庫, 比如騰訊的MTA等等。
但是,第三方的數(shù)據(jù)統(tǒng)計(jì)庫要么功能太簡單,滿足不了需求,要么就是要收費(fèi)。(留下了貧窮的淚水。)
等等,又不是你出錢,怕啥? 貴一點(diǎn)就貴一點(diǎn)呀。

嗯,說的沒錯(cuò)。但是,公司團(tuán)隊(duì)內(nèi)部想實(shí)現(xiàn)一套完整的自己的數(shù)據(jù)統(tǒng)計(jì)系統(tǒng)以滿足自己的需求。所以,還是沒有用第三方的。

所以,具體要統(tǒng)計(jì)些啥?

產(chǎn)品經(jīng)理

想知道用戶都是怎么進(jìn)入我們的小程序的?

用戶在我們小程序里那個(gè)頁面停留的時(shí)間最長?平均用戶停留時(shí)間是多少?

想知道我們最近開發(fā)的那個(gè)功能用的人多不多?

想統(tǒng)計(jì)小程序里的一些按鈕有多少用戶點(diǎn)擊了

開發(fā)自己

總是很難復(fù)現(xiàn)用戶端出現(xiàn)的bug,

要是可以知道用戶端發(fā)生錯(cuò)誤時(shí),知道用戶當(dāng)時(shí)的用的手機(jī)型號,微信版本,網(wǎng)絡(luò)環(huán)境,頁面參數(shù),和錯(cuò)誤信息就好了

想知道我們小程序啟動時(shí)間是多少?

接口在用戶端的平均響應(yīng)時(shí)間是多少ms? 哪些接口報(bào)錯(cuò)了

針對產(chǎn)品經(jīng)理的需求,我們可以知道,Ta想要的是就是數(shù)據(jù)統(tǒng)計(jì)要實(shí)現(xiàn)的功能。對于開發(fā)來說,我們關(guān)注的更多就是錯(cuò)誤統(tǒng)小程序性能這塊的東西。

好,到這里,我們需求是明白了。就是要實(shí)現(xiàn)一套既能統(tǒng)計(jì)普通的埋點(diǎn)數(shù)據(jù),也要能統(tǒng)計(jì)到小程序里一些特殊觸發(fā)的事件,比如appLaunch, appHide 等,還要可以統(tǒng)計(jì)錯(cuò)誤。

好,那先來看看如何實(shí)現(xiàn)產(chǎn)品的需求吧

用戶進(jìn)入小程序可以在 小程序 onLaunch 回調(diào)里拿到參數(shù) 的scene 值,這樣就可以知道用戶是怎么進(jìn)入小程序的了。小case, 難不到我。

嗯,第一個(gè)需求實(shí)現(xiàn)了,那如何統(tǒng)計(jì)第二個(gè)呢?如何統(tǒng)計(jì)某個(gè)頁面的停留時(shí)間呢?

這也難不倒我,用戶在進(jìn)入頁面時(shí)會觸發(fā)onShow 事件, 同樣,在離開頁面(或者切后臺時(shí))會觸發(fā)onHide事件,我只需要在onShow里記錄一下時(shí)間,同時(shí)在onHide 里也記錄一下時(shí)間,把兩個(gè)時(shí)間一減就可以了。

   Page({
       data: {
        beginTime: 0,
        endTime: 0
       },
       onShow: function() {
         // Do something when page show.
         this.setData({
           beginTime:  new Date().getTime()
         })
       },
       onHide: function() {
         // Do something when page hide.
         let stayTime = new Date().getTime() - this.beginTime;
         // 這個(gè)就是用戶在這個(gè)頁面的停留時(shí)間了
       },
   })

等等,這樣確實(shí)實(shí)現(xiàn)了需求,萬一產(chǎn)品要統(tǒng)計(jì)所有也面的停留時(shí)長? 那我們豈不要在每一個(gè)頁面都這樣寫一遍?有沒有更好的方法呢?

好,接下來就是數(shù)據(jù)統(tǒng)計(jì)實(shí)現(xiàn)的要點(diǎn)了,即攔截微信原生事件,這樣可以在某個(gè)特殊事件觸發(fā)時(shí),做一些我們統(tǒng)計(jì)的事情。同時(shí),還要攔截微信發(fā)生網(wǎng)絡(luò)請求的方法,這樣可以拿到網(wǎng)絡(luò)請求相關(guān)的數(shù)據(jù),最后,為了能統(tǒng)計(jì)到錯(cuò)誤,還需要攔截微信發(fā)生錯(cuò)誤的方法。

1.特殊事件的監(jiān)聽 App(Object object)

注冊小程序。接受一個(gè) Object 參數(shù),其指定小程序的生命周期回調(diào)等。

App() 必須在 app.js 中調(diào)用,必須調(diào)用且只能調(diào)用一次。不然會出現(xiàn)無法預(yù)期的后果。

攔截全局的事件:

下面是小程序官方文檔對于App 注冊方法的文檔:

App({
  onLaunch (options) {
    // Do something initial when launch.
  },
  onShow (options) {
    // Do something when show.
  },
  onHide () {
    // Do something when hide.
  },
  onError (msg) {
    console.log(msg)
  },
  globalData: "I am global data"
}) 

假如我們要在小程序onLaunch 時(shí)打印一句hello Word,我們有哪些方法實(shí)現(xiàn)?

方法1:

直接寫在onLaunch方法里

  onLaunch (options) {
     console.log("hello World")
  }

方法2:

使用 monkey patch方法 猴子補(bǔ)丁(monkey patch)

猴子補(bǔ)丁主要有以下幾個(gè)用處:

在運(yùn)行時(shí)替換方法、屬性等

在不修改第三方代碼的情況下增加原來不支持的功能

在運(yùn)行時(shí)為內(nèi)存中的對象增加patch而不是在磁盤的源代碼中增加

舉個(gè)栗子,假如我們在console.log 方法里都先打印出當(dāng)前的時(shí)間戳,我們可以這樣:

var oldLog = console.log
console.log = function() {
  oldLog.call(this, new Date().getTime())
  oldLog.apply(this, arguments)
}

同理,我們針對onLaunch 進(jìn)行猴子補(bǔ)丁

var oldAp = App
App = function(options) {
  var oldOnLaunch = options.onLaunch
  options["onLaunch"] = function(t) {
    // 做一些我們自己想做的事情
    console.log("hello word....")
    // 調(diào)用原來的onLaunch 方法
    oldOnLaunch.call(this, t)
  }
  
  // 調(diào)用原來的App 方法
  oldApp(options)
  
  // 想像一下,小程序內(nèi)部調(diào)用onLaunch 方法應(yīng)該是這樣子的:
  options.onLaunch(params)
}

// 問題,有的時(shí)候,我們可能沒有注冊某一個(gè)事件,比如頁面的onShow, 所有,我們在替換的時(shí)候還需要判斷一下參數(shù)是否傳了對應(yīng)的方法
Page({
  onLoad (options) {},
  onHide (options) {}
})

// 針對這種情況,我們需要這樣寫
var oldPage = Page
Page = function(options) {
  if (options["onShow"]) {
    // 如過有注冊onShow 這個(gè)回調(diào)
    var oldOnShow = options.onShow
    // onShow 方法調(diào)用時(shí)都是 傳了一個(gè)對象
    options["onShow"] = function(t) {
      // doSomething()
      oldOnShow.call(this, t)
    }
  }
  // 調(diào)用原來的Page 方法。
  oldPage.apply(null, [].slice.call(arguments))
  // 注意: 下面這兩種寫都會報(bào)錯(cuò): VM23356:1 Options is not object: {"0":{}} in pages/Badge.js 問題具體原因暫時(shí)未找到。
  // oldPage.call(null, arguments)
  // oldPage(arguments)
}

通過上面的方法,我們可以攔截了 App 方法注冊的一些全局方法,比如 onLaunch , onShow, onHide, 和Page 注冊的事件如 onShow, onHide, onLoad, onPullDownRefresh, 等頁面注冊事件。

2.網(wǎng)絡(luò)請求的監(jiān)聽

思路: 攔截微信的請求事件。

 let Request = {
      request: function (e) {
        let success = e[0].success,
          fail = e[0].fail,
          beginTime = smaUtils.getTime(),
          endTime = 0
        // 攔截請求成功方法
        e[0].success = function () {
          endTime = smaUtils.getTime()
          const performance = {
            type: constMap.performance,
            event: eventMap.wxRequest,
            url: e[0].url,
            status: arguments[0].statusCode,
            begin: beginTime,
            end: endTime,
            total: endTime - beginTime
          }
          smaUtils.logInfo("success performance:", performance)
          // 這里做上報(bào)的事情
          // SMA.performanceReport(performance)
          success && success.apply(this, [].slice.call(arguments))
        }
        // 攔截請求失敗方法
        e[0].fail = function () {
          endTime = smaUtils.getTime()
          const performance = {
            type: constMap.performance,
            event: eventMap.wxRequest,
            url: e[0].url,
            status: arguments[0].statusCode,
            begin: beginTime,
            end: endTime,
            total: endTime - beginTime
          }
          smaUtils.logInfo("fail performance:", performance)
          // 這里做上報(bào)的事情
          // SMA.performanceReport(performance)
          fail && fail.apply(this, [].slice.call(arguments))
        }
      },
   }
 
 
    // 替換微信相關(guān)屬性
    let oldWx = wx,
      newWx = {}
    for (var p in wx) {
      if (Request[p]) {
        let p2 = p.toString()
        newWx[p2] = function () {
          Request[p2](arguments)
          // 調(diào)用原來的wx.request 方法
          oldWx[p2].apply(oldWx, [].slice.call(arguments))
        }
      } else {
        newWx[p] = oldWx[p]
      }
    }
    // eslint-disable-next-line
    wx = newWx

疑惑:為什么要使用替換整個(gè)wx對象的方法呢? 不直接用我們的request 方法 替換 wx.request 方法

var oldRequest = wx.request
wx.request = function(e) {
  // doSomething();
  console.log("請求攔截操作...")
  oldRequest.call(this, e); // 調(diào)用老的request方法
}
// 結(jié)果報(bào)錯(cuò)了:
//  TypeError: Cannot set property request of [object Object] which has only a getter

3.錯(cuò)誤的監(jiān)聽

3.1 攔截App里注冊的 onError事件

var oldAp = App
App = function(options) {
  var oldOnError = options.onErrr
  options["onErrr"] = function(t) {
    // 做一些我們自己想做的事情
    console.log("統(tǒng)計(jì)錯(cuò)誤....", t)
    // 調(diào)用原來的onLaunch 方法
    oldOnError.call(this, t)
  }
  
  // 調(diào)用原來的App 方法
  oldApp(options)
}

3.2 攔截 conole.error

 console.error = function() {
      var e = [].slice.call(arguments)
      if (!e.length) { return true }
      const currRoute = smaUtils.getPagePath()
      // 統(tǒng)計(jì)錯(cuò)誤事件
      // SMA.errorReport({event: eventMap.onError, route: currRoute, errrMsg: arguments[0]})
      smaUtils.logInfo("捕捉到error 事件,", e)
      oldError.apply(console, e)
  }

至此,我們已經(jīng)有能力在小程序發(fā)起請求時(shí),發(fā)生錯(cuò)誤時(shí),生命周期或者特殊函數(shù)回調(diào)時(shí),我們都能在里面做一些我們想要的數(shù)據(jù)統(tǒng)計(jì)功能了。

說了這么多大家估計(jì)也看累了。鑒于篇幅,具體的代碼就不在這里貼了。

最終實(shí)現(xiàn)的數(shù)據(jù)統(tǒng)計(jì)模塊大致實(shí)現(xiàn)了以下功能:

普通埋點(diǎn)信息上報(bào)功能

錯(cuò)誤信息上報(bào)功能

性能數(shù)據(jù)上報(bào)功能

具體的上報(bào)時(shí)機(jī)支持配置

支持指定網(wǎng)絡(luò)環(huán)境上報(bào)

支持統(tǒng)計(jì)數(shù)據(jù)緩存到微信本地功能

整個(gè)統(tǒng)計(jì)代碼的配置文件如下:

const wxaConfig = {
  project: "myMiniProgram", // 項(xiàng)目名稱
  trackUrl: "https://youhost.com/batch", // 后臺數(shù)據(jù)統(tǒng)計(jì)接口
  errorUrl: "https://youhost.com/batch",  // 后臺錯(cuò)誤上報(bào)接口
  performanceUrl: "https://youhost.com/batch", // 后臺性能上報(bào)接口
  version: "0.1",
  prefix: "_wxa_",
  priority: ["track", "performance", "error"], // 發(fā)送請求的優(yōu)先級,發(fā)送時(shí),會依次發(fā)送
  useStorage: true, // 是否開啟storage緩存
  debug: false, // 是否開啟調(diào)試(顯示log)
  autoTrack: true, // 自動上報(bào) onShow, onHide, 分享等 內(nèi)置事件
  errorReport: false, // 是否開啟錯(cuò)誤上報(bào)
  performanceReport: false, // 接口性能上報(bào)
  maxReportNum: 20, // 當(dāng)次上報(bào)最大條數(shù)
  intervalTime: 15,  // 定時(shí)上報(bào)的時(shí)間間隔,單位 s, 僅當(dāng)開啟了定時(shí)上報(bào)有效。
  networkList: ["wifi", "4g", "3g"], // 允許上報(bào)的網(wǎng)絡(luò)環(huán)境
  opportunity: "pageHide" // pageHide、appHide、realTime(實(shí)時(shí)上報(bào))、timing(定時(shí)上報(bào)) 上報(bào)的時(shí)機(jī),四選一
}
export default wxaConfig

具體上報(bào)時(shí),上報(bào)的數(shù)據(jù)結(jié)構(gòu)大致長這樣:

項(xiàng)目已傳到GitHub -> GitHub傳送門-wxa

如果這篇文章幫到你了,覺得不錯(cuò)的話來點(diǎn)個(gè)Star吧

你們是如何實(shí)現(xiàn)小程序數(shù)據(jù)統(tǒng)計(jì)的呢? 歡迎在評論里留言交流~~

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105015.html

相關(guān)文章

  • 監(jiān)控信小程序wx.request請求失敗

    摘要:微信小程序運(yùn)維中心提供了錯(cuò)誤日志記錄,但功能還是比較有限。有時(shí)候一個(gè)微信小程序可能會用到多個(gè)第三方服務(wù),從多個(gè)域名獲取數(shù)據(jù)。要使用監(jiān)控,你需要去網(wǎng)站注冊賬號并創(chuàng)建一個(gè)微信小程序監(jiān)控項(xiàng)目,然后按照提示接入插件。 在微信小程序里,與后臺服務(wù)器交互的主要接口函數(shù)是wx.request(),用于發(fā)起 HTTPS 網(wǎng)絡(luò)請求。其重要性不言而喻。然而,卻經(jīng)常遇到請求失敗的問題,筆者特意谷歌wx.re...

    lpjustdoit 評論0 收藏0
  • 2017年云巴產(chǎn)品更新合集

    摘要:更新修正協(xié)議下默認(rèn)關(guān)閉時(shí)會取消訂閱本次訂閱的所有物聯(lián)網(wǎng)整體方案篇年,云巴利用實(shí)時(shí)跨平臺雙向物聯(lián)網(wǎng)云端系統(tǒng)的產(chǎn)品優(yōu)勢,積極迎接物聯(lián)網(wǎng)新時(shí)代,為客戶定制物聯(lián)網(wǎng)整體解決方案。 SDK 篇 Android SDK 更新 ·Android Release 1.8.5在demo中去除掉小米、華為平臺的jar包,讓用戶自行下載 ·Android SDK 1.8.6對新版華為推送做了適配。 JavaS...

    Airmusic 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<