1. 程式人生 > >一步一步搭建前端監控系統:如何將網頁截圖上報?

一步一步搭建前端監控系統:如何將網頁截圖上報?

摘要: 通過錄屏或者截圖,快速復現BUG場景。

Fundebug經授權轉載,版權歸原作者所有。

PS:本文關於Fundebug錄屏功能的內容有些不準確的地方,比如錄屏並非通過截圖實現的,錄屏外掛的BUG也已經修復了,錄屏並非只支援Chrome,錄屏資料並不大,錄屏效能也優化了很多。

**背景:**市面上的監控系統有很多,大多收費,對於小型前端專案來說,必然是痛點。另一點主要原因是,功能雖然通用,卻未必能夠滿足我們自己的需求,所以我們自給自足也許是個不錯的辦法。

這是搭建前端監控系統的第二章,主要是介紹如何統計js報錯,跟著我一步步做,你也能搭建出一個屬於自己的前端監控系統。

目前已經在執行的線上Demo:前端監控系統

程式碼和講解都放在這篇文章裡: 監控系統介紹及程式碼

使用者對前端程式設計師來說,就是一個黑匣子。 如果使用者上報了一個錯誤,前端程式設計師就是兩眼一抹黑,因為很多錯誤是沒法復現的。我問過很多前端工程師,他們的回答都是,如果你沒法復現Bug,我怎麼去解決這個Bug呢。 那麼有沒有一個辦法可以解決使用者和前端程式設計師之間的障礙呢, 讓使用者對我們來說,不再是黑匣子,而是透明化。使用者的頁面長什麼樣,他們都做了什麼操作,發生了什麼錯誤,我們都能夠清晰的知道,那麼,再有問題上報的時候,我就會很有信心的說一句: I Can Fix it !

最近試用了一下

Fundebug,進入首頁,第一條便是 黑科技!支援錄屏。 這下就驚呆我了,js做前端監控,居然還能錄屏? 你丫這是要逆天啊? 所以,趕緊註冊了賬號,進行試用。

經過各種配置後,進行測試釋出,發現毫無效果,所以詢問客服。 回答是: 目前錄製功能有bug,所以預設為關閉狀態,將配置屬性silentVideo設定為false即可。(PS:Fundebug的錄屏BUG已經修復了)

果不其然,經過客服的細心指導,終於成功了。 圖一為電腦版chrome瀏覽器,可以正常進行螢幕錄製。 圖二為手機app自帶的webview瀏覽器,第一次點選顯示灰屏,第二次點選顯示為電腦版的錄屏。經過測試,除了chrome之外,其他瀏覽器均不支援。這讓我想起一個可以進行js截圖的庫JSCapture, 也是隻支援chrome瀏覽器的。我猜想,Fundebug用的應該就是這個黑科技。 Fundebug也表示並非真的視訊,應該是多做了幾幀截圖,然後順序切換,看著像視訊了。(PS:Fundebug的錄屏功能並非通過截圖實現的)

雖然是黑科技,但是也面臨著幾個比較大的問題:

一、因為支援的瀏覽器只有chrome,而chrome又是相容性做得最好的瀏覽器了,很多問題在這個瀏覽器上根本不會發生, 所以這個黑科技還是有待來日,也許會得到更多瀏覽器的支援之後,才能真正的發揮作用。不得不感慨一句:唉,相容性-前端程式設計師一生的宿命。(PS:Fundebug的錄屏功能並非只支援Chrome)

二、就算螢幕錄製解決了,上傳了一個至少有個幾幀的仿視訊,這個流量大小可是很嚴重問題了,雖然Fundebug說是經過特殊處理壓縮後,一個視訊只有幾十KB,我總覺得不是很靠譜,感覺比較難以實現(待驗證)。(PS:Fundebug的錄屏資料經過優化和壓縮,因此並不大)

三、我自己的手機是iphone6 Plus, 當Fundebug在我的手機上進行螢幕捕捉的時候,手機都會卡頓很久。 我之前曾嘗試在iphone6上用js進行截圖,但是也會出現卡頓現象,這一點在微信瀏覽器上表現極為明顯,甚至會導致微信重新重新整理頁面。 好在iphone6以上的版本,截圖的效率都很高,不會再出現卡頓了。(PS:Fundebug的錄屏效能經過持續優化)

所以,Fundebug的黑科技是不能夠普及的,但是我們可以換個思路來記錄使用者的行為。

之前,我曾經考慮過一個需求,記錄下使用者的每個行為,訪問頁面的截圖,點選按鈕的區域性截圖,這樣,在錯誤發生的時候,就能清清楚楚的知道使用者在頁面上做了什麼,但是由於截圖上傳需要耗費的流量確實太大,所以這個想法不得不放棄了。 今天,我看了Fundebug的黑科技,卻給了一些啟發。 我將針對以上提出的三個難點,完善頁面上使用者行為追蹤功能。

使用者行為追蹤功能

一、 上傳截圖,流量消耗過大怎麼辦,對圖片資源進行極致壓縮。

進行截圖後,需要上傳的資料很大,因為是圖片資料,多則大幾百Kb, 少則也有個上百Kb, 這麼大的流量,對使用者端,損耗確實過大。

首先,對js截圖進行了幾種測試,如圖:

以上截圖方式的引數如下:

參考截圖方式一截圖方式二截圖方式三
壓縮前/後長度28764/1078793076/34903168312/63118
圖片壓縮率72%40%0%
截圖大小21Kb68.2Kb123Kb

綜上分析,截圖方式一, 壓縮率高,雖然截圖不是很清晰,但是,也能夠看得出,線上使用者頁面是什麼樣子的。

而且,也解決了,在低端機上截圖消耗效能過大的弊端,二十幾Kb的流量,也是我們完全能夠接受的大小了。

由此可見,該方式能夠完全能夠滿足我們追蹤使用者行為的需求。

二、如果使用者量非常多, 使用者頻繁的上傳,也是一個大問題

所以,我的建議是分散流量,讓每個使用者為我們貢獻至少一次頁面截圖:

① 每個使用者都在隨機的頁面,隨機的時間上傳一個頁面截圖,以及一個點選區域截圖,有且僅上傳一次,一個使用者的生命週期中只貢獻一次頁面截圖

② 每個使用者發生某一類錯誤時,也只需上傳一個截圖即可,多個型別的錯誤,則上傳多個截圖。這樣可以大量節省使用者的上傳次數。

③ 使用者的截圖資料很大, 時間長了需要很大的硬碟空間, 所以我的建議是,每個流程頁面,只需要對應一個(點選區域截圖,同理)。 每個使用者的某一種型別的錯誤頁面也只對應一個(方便定位錯誤原因)

如何截圖,如何壓縮上傳資源的大小

// js處理截圖
this.screenShot = function(cntElem, callback) {
    var shareContent = cntElem; //需要截圖的包裹的(原生的)DOM 物件
    var width = shareContent.offsetWidth; //獲取dom 寬度
    var height = shareContent.offsetHeight; //獲取dom 高度
    var canvas = document.createElement("canvas"); //建立一個canvas節點
    var scale = 0.6; //定義任意放大倍數 支援小數
    canvas.style.display = "none";
    canvas.width = width * scale; //定義canvas 寬度 * 縮放
    canvas.height = height * scale; //定義canvas高度 *縮放
    canvas.getContext("2d").scale(scale, scale); //獲取context,設定scale
    var opts = {
        scale: scale, // 新增的scale 引數
        canvas: canvas, //自定義 canvas
        logging: false, //日誌開關,便於檢視html2canvas的內部執行流程
        width: width, //dom 原始寬度
        height: height,
        useCORS: true // 【重要】開啟跨域配置
    };
    html2canvas(cntElem, opts).then(function(canvas) {
        var dataURL = canvas.toDataURL();
        var tempCompress = dataURL.replace("data:image/png;base64,", "");
        var compressedDataURL = Base64String.compress(tempCompress);
        callback(compressedDataURL);
    });
};

要做成這件事,必須依賴兩個js庫的幫忙了。

html2Canvas 執行html頁面截圖, lz-string 執行對字串長度的壓縮,使用方式,如上方程式碼所示。

由於使用者行為追蹤功能可以由使用者選擇性開起, 所以,建議這兩個js庫檔案有客戶端引入, 這樣就可以減少探針程式碼的大小, 如此,我們就需要定義一個載入js檔案的小工具

// 載入js檔案的小工具
this.loadJs = function(url, callback) {
    var script = document.createElement("script");
    script.async = 1;
    script.src = url;
    script.onload = callback;
    var dom = document.getElementsByTagName("script")[0];
    dom.parentNode.insertBefore(script, dom);
    return dom;
};
// html2Canvas 庫檔案載入完成後,通知全域性變數,lz-string 同理
utils.loadJs("//html2canvas.hertzen.com/dist/html2canvas.min.js", function() {
    html2CanvasLoaded = true;
});

OK, 資料都已經準備妥當,剩下的就是要把這些資料儲存起來,並和使用者行為,以及js錯誤關聯起來。 完成使用者行為追蹤功能。

PS:本文關於Fundebug錄屏功能的內容有些不準確的地方,比如錄屏並非通過截圖實現的,錄屏外掛的BUG也已經修復了,錄屏並非只支援Chrome,錄屏資料並不大,錄屏效能也優化了很多。

關於Fundebug

Fundebug專注於JavaScript、微信小程式、微信小遊戲、支付寶小程式、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了10億+錯誤事件,付費客戶有陽光保險、核桃程式設計、荔枝FM、掌門1對1、微脈、青團社等眾多品牌企業。歡迎