怎樣定位前端線上問題,一直以來,都是很頭疼的問題,因為它發生於用戶的一系列操作之后。錯誤的原因可能源於機型,網絡環境,接口請求,復雜的操作行為等等,在我們想要去解決的時候很難復現出來,自然也就無法解決。 當然,這些問題並非不能克服,讓我們來一起看看如何去監控並定位線上的問題吧。
這是搭建前端監控系統的第六章,主要是介紹如何使用js進行頁面截圖,跟着我一步步做,你也能搭建出一個屬於自己的前端監控系統。
============================================================================
============================================================================
用戶對前端程序員來說,就是一個黑匣子。 如果用戶上報了一個錯誤,前端程序員就是兩眼一抹黑,因為很多錯誤是沒法復現的。我問過很多前端工程師,他們的回答都是,如果你沒法復現Bug,我怎么去解決這個Bug呢。 那么有沒有一個辦法可以解決用戶和前端程序員之間的障礙呢, 讓用戶對我們來說,不再是黑匣子,而是透明化。用戶的頁面長什么樣,他們都做了什么操作,發生了什么錯誤,我們都能夠清晰的知道,那么,再有問題上報的時候,我就會很有信心的說一句: I Can Fix it !
最近試用了一下Fundebug,進入首頁,第一條便是 黑科技!支持錄屏。 這下就驚呆我了,js做前端監控,居然還能錄屏? 你丫這是要逆天啊? 所以,趕緊注冊了賬號,進行試用。
經過各種配置后,進行測試發布,發現毫無效果,所以詢問客服。 回答是: 目前錄制功能有bug,所以默認為關閉狀態,將配置屬性silentVideo設置為false即可。
果不其然,經過客服的細心指導,終於成功了。 圖一為電腦版chrome瀏覽器,可以正常進行屏幕錄制。 圖二為手機app自帶的webview瀏覽器,第一次點擊顯示灰屏,第二次點擊顯示為電腦版的錄屏。經過測試,除了chrome之外,其他瀏覽器均不支持。這讓我想起一個可以進行js截屏的庫JSCapture, 也是只支持chrome瀏覽器的。我猜想,Fundebug用的應該就是這個黑科技。 Fundebug也表示並非真的視頻,應該是多做了幾幀截屏,然后順序切換,看着像視頻了。
雖然是黑科技,但是也面臨着幾個比較大的問題:
一、因為支持的瀏覽器只有chrome,而chrome又是兼容性做得最好的瀏覽器了,很多問題在這個瀏覽器上根本不會發生, 所以這個黑科技還是有待來日,也許會得到更多瀏覽器的支持之后,才能真正的發揮作用。不得不感慨一句:唉,兼容性-前端程序員一生的宿命。
二、就算屏幕錄制解決了,上傳了一個至少有個幾幀的仿視頻,這個流量大小可是很嚴重問題了,雖然Fundebug說是經過特殊處理壓縮后,一個視頻只有幾十KB,我總覺得不是很靠譜,感覺比較難以實現(待驗證)
三、我自己的手機是iphone6 Plus, 當Fundebug在我的手機上進行屏幕捕捉的時候,手機都會卡頓很久。 我之前曾嘗試在iphone6上用js進行截圖,但是也會出現卡頓現象,這一點在微信瀏覽器上表現極為明顯,甚至會導致微信重新刷新頁面。 好在iphone6以上的版本,截屏的效率都很高,不會再出現卡頓了
所以,Fundebug的黑科技是不能夠普及的,但是我們可以換個思路來記錄用戶的行為。
之前,我曾經考慮過一個需求,記錄下用戶的每個行為,訪問頁面的截圖,點擊按鈕的局部截圖,這樣,在錯誤發生的時候,就能清清楚楚的知道用戶在頁面上做了什么,但是由於截圖上傳需要耗費的流量確實太大,所以這個想法不得不放棄了。 今天,我看了Fundebug的黑科技,卻給了一些啟發。 我將針對以上提出的三個難點,完善頁面上用戶行為追蹤功能。
用戶行為追蹤功能
一、 上傳截圖,流量消耗過大怎么辦,對圖片資源進行極致壓縮。
進行截圖后,需要上傳的數據很大,因為是圖片數據,多則大幾百Kb, 少則也有個上百Kb, 這么大的流量,對用戶端,損耗確實過大。
首先,對js截圖進行了幾種測試,如圖:
以上截圖方式的參數如下:
參數 截圖方式一 截圖方式二 截圖方式三
壓縮前/后長度 28764/10787 93076/34903 168312/63118
圖片壓縮率 72% 40% 0%
截圖大小 21Kb 68.2Kb 123Kb
綜上分析,截圖方式一, 壓縮率高,雖然截圖不是很清晰,但是,也能夠看得出,線上用戶頁面是什么樣子的。
而且,也解決了,在低端機上截圖消耗性能過大的弊端,二十幾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錯誤關聯起來。 完成用戶行為追蹤功能。
本來我以為 前端Js錯誤監控模塊終結了, 但是發現還需要放上重要的一篇
下一章: 搭建前端監控系統(五)用戶行為統計和監控