本文將結合工做,描述一下前端監控系統Sentry搭建過程當中,背景、設計、實現、思考四個方面的感悟及問題。javascript
監控從字面含義來看包含兩方面內容:監,監測的是代碼;控,控制的是質量。監控是工具而不是目的,不是爲了具備功能而監控,而是要經過監控,真正瞭解頁面運行狀況,以達到代碼運行質量可控的目的。html
監控不一樣於統計,統計關注的是一段時間內訪問狀況的一個總和,對於實時性要求並不那麼高,能夠延遲上報、累計上報;監控則偏偏相反,關注的是頁面運行時的狀況。前端
整個大前端角度來說,監控的場景不少。好比:服務端監控接口的穩定性和性能;客戶端監控crash和APP性能;對Web前端來說,更加關注線上運行時的性能和報錯。java
監控對於線上線下來講都是有意義的,線下咱們能夠支持自動化測試,上線前就發現代碼運行時的一些明顯錯誤,這個能夠作爲線下防退化的參考依據。線上環境則更加複雜,不一樣的地域、設備、網絡、瀏覽框架等諸多因素,致使一樣的代碼不一樣環境中運行時,結果可能會參差不齊。咱們但願瞭解這些狀況,評估頁面哪裏須要優化。node
公司內部現有統計平臺,如thunder,spy等通用的平臺,便可以收集性能指標,也能夠收集前端異常信息,可是收集的異常信息大多作統計用途,關注有多少報錯信息,或者某類錯誤有多少類別,通常不會包含具體報錯的詳細信息。sql
前端還有一個特色,靜態資源會混淆後壓縮,若是運行錯誤,拿到的報錯堆棧信息沒有太大含義,只會報第一行報了xx錯誤,假設有sourcemap,咱們也只能藉助Chrome Devtools來看具體是哪兒錯誤,但每每線上的報錯,咱們很難復現。docker
經過前面提到的兩個問題的收集:統計平臺報錯信息收集不夠詳細,沒法根據報錯反解源碼錯誤行數,咱們選擇基於開源Sentry在百度雲上搭建了一套前端異常監控服務。數據庫
Sentry是一個集中式日誌管理系統。能夠作如下事情,並且是相比於其餘系統作的不錯的地方。promise
首先提一下當下流行的Docker(是一個開源的應用容器引擎),Docker有一句口號:Build Once , Run Anywhere. 也就是說一個環境能夠經過一次編譯發佈,在任何支持Docker的環境中能夠快速跑起來,這解決咱們平常部署環境的痛苦。可是你們實踐的時候發現,若是想要將Docker應用於具體的業務實現,是存在困難的——編排、管理和調度等各個方面,都不容易。因此K8S(全稱:kubernetes,基於容器的集羣管理平臺)應運而生,應用於廣大的實際項目中安全
廣告一波自家的提供的雲服務平臺:百度雲。百度雲提供了豐富的基礎服務支持,好比強大的容器服務CCE,域名解析分發服務ITM,數據分析服務Sugar等。咱們能夠基於百度雲提供的服務快速達成想要實現的內容。
自己Sentry支持源碼部署和容器(Docker、K8S)部署兩種方式,考慮到穩定性,想要實現多機器多機房部署、負載均衡、智能調度等實際問題,基於百度雲提供的K8S服務,容器化部署了Sentry,如圖1。
圖1 :Sentry 百度雲部署架構
結合業務,繼續看一下Senty在總體項目中地位置,如圖2。
圖2 :項目總體架構圖
這種架構下的Sentry服務,有幾個優點:
平臺在梳理清楚了上面流程的基礎上,很快就搭建了起來。可是在平臺試運行活成中,監控的每一個環節,不一樣程度的暴露除了一些問題。針對監控的每一個流程環節,再次作了進一步的分析和優化。下面針對主要環節進行說明。
監控信息上報,主要依賴於SDK。之前端爲例,Sentry自己提供了一個SDK,須要在頁面加載過程當中,優先加載,進而實現儘量多的錯誤捕獲。
<html> <head> <title>監控報警</title> <script src="https://xx/sentry.js"></script> </head> <body> ...... <body> </html>複製代碼 |
實踐過程當中,發現打包後的sentry.js 有20K左右,若是放到頂部,對於追求頁面性能的頁面來說,是災難性的,由於JS放在頂部加載會阻塞頁面的渲染。因而這對這種狀況,進行了SDK後置優化。
<html> <head> <title>監控報警</title> <script> let estack = err => { return win[ers].length < 10 ? win[ers].push(err) : false; }; win.onerror = (a, b, c, d, error) => { estack(error); return true; }; win.addEventListener('unhandledrejection', error => { error.preventDefault(); estack(error); return true; }); <script> </head> <body> <script src="https://xx/sentry.plus.js" async ></script> <body> </html>複製代碼 |
經過SDK的改造,大大減小了頁面對於性能方面的擔心,更加放心的使用Sentry服務。
SDK集成以後,日誌採集經過一個POST接口請求實現。頁面運行時,若是報錯,會自動觸發經過接口發送數據。
這時候是否須要支持採樣,成了一個須要考慮的問題。由於若是沒有采樣,同時遇上較大的業務量,極大機率觸發日誌採集功能,大量日誌上報,而有用信息較少。這時候採樣就解決了這個問題。SDK自己是支持採樣的,初始化的時候,只須要進行簡單的配置
Sentry.init({ dsn:'xxx', sample: 0.5 });複製代碼 |
這個抽樣,指的是項目運行時,每次觸發報錯後,是否要進行錯誤上報的一個機率。可是對於追求頁面性能的頁面來說,一般每每但願的是,SDK小流量接入。儘量少的去影響全部頁面。咱們目前頁面基於Php的Smarty模板進行的首屏渲染,因此改造了上報採集的方法:
{%assign var="random" value="{%math equation=rand(1,100)/100%}"|string_format:"%.2f"%} {%assign var="sample" value="0.5"|string_format:"%.2f"%} {%if $random < $sample%} <script type="text/javascript" src="https://xx/sentry.plus.js?v={%$smarty.now%}" crossorigin="anonymous"></script> {%/if%}複製代碼 |
經過改造,又跟進一步減小了監控代碼對業務的影響,業務更加方便的接入。
自己Sentry使用的是PostgreSQL,K8S部署時,數據庫這裏經過配置,使用百度雲提供的數據庫服務。
postgresql: enabled: false nameOverride: sentry-postgresql postgresqlDatabase: sentry postgresqlHost: 192.168.1.1 postgresqlPassword: xxx123 postgresqlPort: 3306 postgresqlUsername: sentrydb複製代碼 |
數據庫的費用也是挺貴的,佔據了總體1/3資源的消費。業務接入的越多,存儲數據量越大,一開始買的50G空間,很快就滿了。
數據到底要不要,我分析了一下:對於報錯自己的數據,尤爲是每一個錯誤的詳細信息,不必存儲那麼久,可是對於報表性質的內容,如報錯整體狀況的同環比,須要存儲更早之前結果的。
第一種方法,土豪的作法:數據庫擴容,繼續增長投入購買。這種就是資金預算投入;
第二種作法:根據現有,收集錯誤的內容,把須要作報表的結果計算後單獨存儲,而後按期數據庫清理,好比能夠起一個腳本,進行按期請裏10天前數據。
這裏有一個小插曲,Sentry官方其實提供了清理數據庫的API,能夠經過命令進行清理:
// 進入容器 docker exec -ti xxxx /bin/bash // 清理 sentry cleanup --days 0複製代碼 |
數據雖然清理了,可是發現PG數據庫的容量沒有釋放,這是由於cleanup的使用delete命令刪除postgresql數據,但postgrdsql對於delete, update等操做,只是將對應行標誌爲DEAD,並無真正釋放磁盤空間。經過如下命令,完全清空。
sudo -u postgres vacuumdb -U postgres -d sentry -t nodestore_node -v -f --analyze複製代碼 |
前面也提到過,Sentry提供了簡單友好的後臺管理系統。項目概況中,能夠體現數據的報表展示。如圖3。
圖3:大盤展示
實踐過程當中,尤爲是給老闆彙報的時候,發現只有這樣的一個展示報表是不夠的。通過調研發現百度雲提供Sugar服務。能夠直接連接數據庫,對想要的數據自定義進行數據聚合,產出對應報表。這個產出需求還在調研中,不過產出的效果是很是使人期待的。配置內容如圖4,預期效果如圖5。
圖4:配置內容
圖5:預期效果
作爲監控的閉環,咱們能夠在Sentry後臺中,根據不一樣的規則,設置郵件報警。Sentry官方建議的郵件服務也不停在變動,最初的Exim4改成了mailgun,綜合考慮費用的問題,咱們最終仍是選擇docker搭建Exim4,而後郵件內容經過申請公司郵件安全組,白名單放開發送郵件的機器。最終實現了錯誤信息及時通知業務的功能。效果如圖6。
圖6:監控效果
以上就是在具體實踐過程當中,關鍵路徑遇到的一些問題,分享給你們。
公司的目的是盈利。一方面公司要控制成本,咱們能夠看到投入QA人力日益削減,另外一方面又須要咱們線上運行的代碼更加穩定,有什麼辦法能夠作到呢?一個高效的方法就是增強監控。
經過監控,能夠快速自主地發現問題。
能夠將收集上來的數據進行分類篩選,而後設置報警告知。根據咱們監控內容,設定不一樣的閾值,當達到閾值的時候,第一時間有效的通知到對應的研發人員,進行分析和修復。
經過監控,能夠全方位瞭解頁面運行狀況。
經過信息收集,能夠獲取到用戶訪問的區域、機型、APP版本等基礎用戶信息,同時也可收集到頁面運行時的性能,要知道性能就是金錢(打開速度必定程度上會影響用戶的去留)。
經過監控,能夠指導後期項目開發。
通過一段時間的沉澱,咱們收集過的錯誤,能夠繪製出一個報表,統計出咱們某段時間內問題產生的緣由、報錯、解決方案。
從研發流程上來看(以下圖所示),咱們的項目不是完成上線就萬事大吉。須要監控頁面線上運行狀況,根據監控的數據及時進行復盤,循環迭代優化,造成持續的研發閉環生態。
以上這些監控的意義,是往後流程機制的指南,是研發同窗的行爲準則,也是老闆、高工某些關鍵時刻作決策的參考內容之一。經過監控,更加直觀地、全方位立體化地瞭解產品。
中臺是公司內部最近技術方面的戰略方向。在我看來:監控能夠輸出一箇中臺的方案,各部門基於中臺服務進行定製化擴展。
其實咱們這裏分享的Sentry系統,就能夠做爲公司內部的一箇中臺服務進行輸出。各部門能夠根據業務去定製SDK,也能夠根據數據需求,自定義報表和報警。整個Sentry黑盒對外提供API服務,由於K8S帶來的便利性,只須要對應部門提供預算,申請機器,往K8S上面增長縮減便可。
市面上其實已經存在不少不一樣種類的監控工具。好比:frontjs、arms、嶽鷹等,可是很遺憾,發現大可能是收費的。公司層面的產品,數據體量相對較大(但這方面的投入每每是值得的),有時數據產出較慢,結果每每階段性地被新產品替代,廠內如今有一些針對前端的監控平臺,諸如:天幕等,可能數據的採集、存儲、過濾、展示、報警等監控過程當中的每一個環節,都須要須要耗費的人力和財力,這些都還缺乏一些中臺的思路。
經過搭建和實現監控的整個過程,一方面充分體會到了雲服務提供的技術給產品帶來的便利,必定是將來的方向;另外一方面,脫離業務的技術是不靠譜的,技術服務於業務,咱們實現的技術必定要在業務中進行驗證,纔會促進技術更加完善,更加解決業務的實際問題。