iT邦幫忙

2024 iThome 鐵人賽

DAY 23
2

https://ithelp.ithome.com.tw/upload/images/20241007/20152073gT7XoFuA3D.png

前言

在上一篇文章中,我們了前端監控與可觀測性的重要性,並介紹了可觀測性的三個要素 Trace、Metric 和 Logs。延續了 OpenTelemetry 的觀念,這篇文章要深入探討 Grafana Faro,是一個 Grafana 專為前端應用程式設計的開源監控解決方案。因此接下來會對 Faro 的架構、提供的 instrumentation、實現原理、與 React 的整合進行深入的介紹,希望可以透過這篇文章讓各位讀者陷入 Faro 的魅力之中。

Grafana Faro

https://ithelp.ithome.com.tw/upload/images/20241007/20152073k4istIte0T.png

Grafana Faro 是一個專為前端應用程式可觀察性設計的專案,包含一個可高度設置的 Web SDK,用於實際使用者監控 (RUM)。而 Faro SDK 可以幫助開發者在瀏覽器前端應用程式中植入工具,以捕捉各種可觀測性的訊號。前端的遙測數據可以與後端和基礎設施數據相關聯,實現無縫的全端可觀察性。

以上是官方文件對於 Grafana Faro 的介紹。在上一篇文章中所提及可觀測性工具的功能,在 Faro 中都可以幫我們實現。在 2022 年時,Grafana 開啟了 Faro 這個開源專案,同時作為一個 RUM 的工具,只需在 Web 應用程式中嵌入 SDK 的程式碼,即可收集各種使用者遙測數據。Faro SDK 是基於 OpenTelemetry 的 API 設計,因此收集的資料可以透過 Grafana 提供的 Collector Agent 無痛傳送至後端服務 —— Grafana Labs LGTM 堆疊,最終在 Grafana 的 Dashboard 上將數據進行視覺化呈現。基於以上的內容整理出 Faro 的幾個特點:

  • 多種自動與手動的儀表化功能:Faro 支援自動及手動的儀表化能力,多種收集數據的方式。
  • 監控網頁應用程式效能:透過收集 Web Vitals 指標,提供使用者感知的效能、互動性及視覺穩定性見解。
  • 捕捉未處理的錯誤和被拒絕的 Promise:Faro 有助於發現錯誤,並在原始程式碼上下文中進行錯誤排查。
  • 追蹤使用者活動:能夠記錄使用者 session、關鍵事件、功能使用情況、使用者行程和 KPI 等數據。
  • 收集前端 Logs:通過收集前端 Logs,更深入地了解錯誤、使用者活動以及應用程式的狀態。
  • 與 Grafana Labs LGTM 無縫整合:能與 Grafana 的 Loki、Grafana、Tempo 和 Mimir 整合,提供完整的開源可觀察性解決方案。
  • 簡易嵌入:只需幾行程式碼即可嵌入,並立即開始收集效能指標、Logs、例外狀況、事件和追蹤。
  • 支援 OpenTelemetry-JS 整合:可以捕捉前端追蹤數據,並與 OpenTelemetry-JS 相容。

Grafana Faro 的資料傳輸架構

https://ithelp.ithome.com.tw/upload/images/20241007/20152073Qj12Njys0n.png

想像一下,在 Faro 中取得的資料需要經過一些處理,才能夠在 Grafana 中顯示。然而這一切的流程都可以透過 Grafana 的內部運作進行處理,比對上圖可以了解資料的流向:

  1. 首先,前端應用程式中的 SDK 會收集遙測數據。
  2. 這些遙測數據會由 Faro 發送到 Grafana 的 Agent - Alloy 中,在這裡可以對數據進行處理和篩選,例如設定哪些數據或到某個程度的閾值才須要傳送。並且會將數據進行分類,例如是錯誤、日誌、測量值、事件等。
  3. 而 Grafana 的 Agent - Alloy 會將數據個別分送到 Loki 和 Tempo 中,Trace 的資料會通過 OpenTelemetry Protocol 傳送到 Tempo 中,而 Logs 的資料會傳送到 Loki 中。
  4. 當數據傳送到 Tempo 和 Loki 後,就可以在 Grafana 的 Dashboard 上進行視覺化呈現。

💡TIP:
OpenTelemetry Protocol 是一種開放標準的遙測數據傳輸協議,他定義了遙測數據來源、接收器與遙測後端之間的數據 encoding、傳輸與發送機制。因此 Alloy 所收集的數據也可以傳送到其他符合 OpenTelemetry Protocol 的服務中,例如說 Jaeger、Prometheus 等。

Grafana Faro 提供的測量

Faro 是藉由在需監控的網頁中嵌入 SDK 的方式來收集遙測數據,這樣的行為稱為 Instrumentation。而截至 2024 年 9 月,在 Faro 中提供了以下幾種 Instrumentation :

  • Console instrumentation
  • Error instrumentation
  • Web Vitals instrumentation
  • Session tracking instrumentation
  • View tracking instrumentation
  • Performance instrumentation
  • Tracing instrumentation

console instrumentation

在前端開發時,經常會使用 console.log 的方式來 debug,但這樣的行為基本上只能在開發環境中使用,正式上線後瀏覽器中可能會造成效能、敏感資訊洩漏、開發者工具混亂等問題。使用 Faro 的 console instrumentation 可以代替瀏覽器的控制台,例如調用 console.error 的行為,Faro 會將這些數據作為 log 收集。因此可以協助開發者在確認錯誤上下文、捕捉應用程式或第三方套件所發出的訊息。

💡NOTICE:
由於 console log 非常實用於錯誤排查,建議保持此功能啟用。不過,應謹慎啟用所有 log 等級,因為這會產生大量數據並增加成本。預設情況下,console.debug、console.trace 和 console.log 是停用的,僅在需要時再啟用。

https://ithelp.ithome.com.tw/upload/images/20241007/20152073lmnsvmzVI4.png

error instrumentation

應用程式在運行時,難免會遇到未處理的錯誤,這些錯誤通常是透過 try/catch 捕捉不到的,因此開發者不會即時察覺到問題,而使用者也不一定會回報。使用 Faro 會訂閱 window.onerror 和 onunhandledrejection 事件,自動收集錯誤並提取追蹤紀錄,最後使用 faro.api.pushError() 將錯誤回報至 Grafana Faro Web SDK。

💡NOTICE:
如果在 try/catch 中捕捉到的錯誤,Faro 不會再次捕捉,因此需要開發者自行將錯誤推送到 Faro 中。

const buggyFn = () => {
  throw new Error("Buggy function");
};

try {
  buggyFn();
} catch (err) {
  // Re-throw the error so it can be caught by the instrumentation
  throw err;

  // Alternatively, report it manually
  faro.api.pushError(err);
}

https://ithelp.ithome.com.tw/upload/images/20241007/20152073z83B56NtBY.jpg

Web Vitals instrumentation

在 20、21 天的文章中,我們有深入了解過 Web Vitals 的指標,而 Web Vitals instrumentation 可以幫助我們收集這些指標的數據,並在 Grafana 的 Dashboard 上進行視覺化呈現。他所使用的測量方式是 web-vitals.js 套件,包括 CLS、FCP、FID、LCP、INP、TTFB 等。數據收集後再調用 faro 提拱的 api pushMeasurement 註冊為 Metrics 後,將數據推送到 Grafana Loki 中。

https://ithelp.ithome.com.tw/upload/images/20241007/20152073i0PT8zMjW4.png

Session tracking instrumentation

所謂的 user session 指的是特定的使用者在網頁上操作從開始到結束或 session 過期的生命週期,而 session tracking instrumentation 可以收集單一 session 期間發生的錯誤、Logs 和事件,並將他們關聯起來。

Session 追蹤的運作原理

Faro 會在使用者造訪網頁時自動建立新的 session,或根據追蹤模式選擇使用者上一次的 session。在 Faro 中最長的 session 持續時間可以為 4 小時,然而預設為 45 分鐘;另外當非活躍時間達 15 分鐘後,session 會過期。而一旦過期後 Faro 會自動建立一個新的 session,並更新其中的 metadata,內容會包含新的 session ID 和舊的 session ID。

另外 session 檢查的機制是透過 onSessionChange 方法,會將新與舊的 session meta(oldSession and newSession)作為參數傳入,檢查有效性,如果 oldSession meta 是 null 則被丟棄。另外,會將 x-faro-session-id 的 header 加到每個 HTTP 請求中,作為後段追蹤 session 的依據。

https://ithelp.ithome.com.tw/upload/images/20241007/201520736ZgrHqmoyR.png

Session 追蹤模式

Faro 提供兩種 session 追蹤模式,並使用 persistent 屬性來設定:

  • 追蹤 session 模式:Session 資訊儲存在 Local Storage 中,讓 session 在頁面重新載入後仍能使用,並可以在同一瀏覽器的不同瀏覽上下文之間同步 session。如果使用者關閉瀏覽器並稍後回訪,Faro 會繼續使用同一個 session。此模式無法區分不同使用者,因此多位使用者使用同一瀏覽器時,會共享相同的 session ID。
  • 短暫 session 模式:為預設模式,Session 資訊儲存在 Session Storage 中,session 資訊僅能在同一標籤頁或視窗內持續。當使用者關閉標籤頁或開啟新的標籤頁時,會創建新的 session,無法在回訪時繼續使用上一個 session。

Session 取樣

在大流量的網站中,如果每個 session 都進行追蹤,會產生大量的數據,可能會造成應用程式的效能或成本問題,因此 Faro 提供了取樣率的功能,可以控制數據的收集量,並基於效能、統計學的有效性、成本和使用者影響的考量,選擇合適的取樣率。
而有被 Faro 取樣的 session 才會被收集並傳送到後端服務,未被取樣的 session 數據會被捨棄。在 Faro 中,取樣率可以透過 samplingRate 屬性來設定,數值為 0~1,預設為 1,也就是所有 session 都會被取樣。而選擇取樣的時機在於:

  1. 頁面加載時:當 Faro 初始化並檢查 Web 儲存中的 session 是否有效。
  2. Session 延長時:當 Faro 自動創建新 session 或手動呼叫 setSession(...) 時。

前後端取樣一致性

如果在前端應用程式中設定取樣率,而後端服務中也自行設定取樣率,會讓資料變得很雜碎或是分析結果偏差,甚至是追蹤困難,所以為了保持前後端資料的一致性,Faro 建議在後端服務中使用 parent based sampling 的取樣策略,而前端進行追蹤時會告知底層追蹤系統取樣結果,並設定 W3C 的 sampled 標誌來通知後續工具記錄 span。若後端使用 OpenTelemetry 進行 Instrumentation,則建議設置 parent-based,以保持前後端資料的一致性。

💡TIP:
Parent-based sampling 是在分散式追蹤系統中,使用父 span 的取樣決策來決定子 span 的取樣決策,這樣可以保持前後端資料甚至整個請求鍊的一致性。

View tracking instrumentation

View tracking instrumentation 的核心作用是將 view meta 的變化作為事件進行回報,使得開發者能夠精確地追蹤應用程式中每個 view 的變更時刻。這一功能主要解決了 SPA 在切換路由時不會觸發頁面重新載入的問題,確保即使在無刷新的情況下也能捕捉到 view 的變化。
而 View instrumentation 深入了解使用者在不同 view 中的行為和可能遇到的問題,並與 Logs 和其他事件進行關聯分析,從而提供更全面的使用者體驗洞察,適合於 RUM 資料的收集與分析。

Faro 提供了靈活的 API,調用 setView 方法為不同的頁面或組件定自定義的 view。例如:

  • 註冊和登入頁面作為身份驗證 view
  • 首頁作為主頁 view
  • 使用者列表頁和使用者個人資料頁作為使用者 view

Performance instrumentation

是基於 Web 的 Performance API 實現的,會針對 PerformanceNavigationTimingPerformanceResourceTiming 進行監控,當頁面進行導覽(頁面加載或選染)或資源載入(如圖片、JavaScript、CSS 等)時,會自動收集相關效能數據。
在調用 Web API 後會再進行一系列的計算或加強後以 faro.performance.navigation 和 faro.performance.resource 的事件回報,而每個事件都會有建立唯一的 ID:faroResourceId 和 faroNavigationId,用以將資源與導覽事件關聯起來,才能在 session 中排列順序。
以下是關於兩個 API 分別會收集的數據:

  • faro.performance.navigation: 包含頁面導覽的相關數據,如頁面加載時間、DOM 處理時間、TTFB 等關鍵效能指標以及頁面類型(如 reload)、URL、協議等資訊,還有詳細的時間分解,如 DNS 查詢、TLS 協商時間等。
  • faro.performance.resource: 包含資源加載的相關數據,如單個資源(如 API 請求)的詳細加載資訊、以及資源 URL、加載時間、狀態碼,還有詳細的網絡時間分解,如 TCP 握手、DNS 查詢時間等。

https://ithelp.ithome.com.tw/upload/images/20241007/20152073QKJKqtT0mz.png
https://ithelp.ithome.com.tw/upload/images/20241007/201520733OPbSisxKc.png

Tracing instrumentation

上述的幾個 Instrumentation 都是屬於 logs 或 metrics 的數據,分類於 Web Instrumentation 中,而 tracing instrumentation 是屬於 trace 的數據,主要收集使用者每次與網頁互動的資訊,而為了將前端的追蹤與 API 的追蹤串聯起來,會依賴追蹤 propagator 的機制,預設使用 W3CTraceContextPropagator,將 traceparent 的 HTTP 的 header 添加到所有 API 使用的 fetch 請求中。而預設情況下,Tracing 使用以下 OpenTelemetry 工具:

  • @opentelemetry/instrumentation-fetch
  • @opentelemetry/instrumentation-xml-http-request

NOTICE:
由於 OpenTelemetry 的關係,traceparent 只會發送至與當前視窗相同來源的請求中。

最後再由 faro.api.pushTraces() 函數將數據推送到 Tempo 中,預設包含的 Tracing instrumentation 有:

  • user interaction instrumentation: 記錄觸發事件的持續時間、發生的使用者互動類型以及涉及的元素。
  • document load instrumentation: 測量網頁初始化加載靜態資源的時間。
  • fetch instrumentation: 測量使用 Fetch API 的請求回應時間。
  • XMLHttpRequest instrumentation: 測量使用 XMLHttpRequest 的請求回應時間,與 fetch instrumentation 測量的參數相同。

使用情境

若有一個前端會呼叫 API 並將數據儲存在資料庫中的應用程式,可以利用 Tracing instrumentation 來:

  • 追蹤當使用者點擊按鈕時應用程式發生了什麼,哪些 API 被調用,請求耗費的時間等。
  • 將應用程式前端的操作與 API 中發生的操作進行關聯。
  • 確定特定 HTTP 請求所耗費的時間,以及該請求中不同事件的時間,例如域名查找等。

Grafana Faro 與 React 的整合

Grafana 專案的前端本身是以 React 為基礎,因此 Grafana Faro 提供了與 React 的高度整合,其中為此開發了 faro-react 的套件,簡化整合流程,並提供以下功能::

  • React Router 整合:支援 v6 和 v4/v5.x,發送所有路由變更的事件,包括 Data Router API。
  • Error boundary:增強錯誤的 stack 追蹤,並提供自訂 pushError 行為的設置選項。
  • 元件 profiler 工具:捕捉元件的渲染次數、安裝/卸載時間等詳細資訊。
  • 支援 Server side rendering (SSR): React Router V6 版本中新增的 Data Router,因此可在 SSR 的環境下正常運行。

💡NOTICE:
使用 profiler 可能會影響應用程式的效能,因此不建議在正式環境中使用。

與其他 SaaS 服務的比較

在 Grafana Faro 出世之前已經有其他相對成熟的前端監控 SaaS 服務(如 New Relic, Sentry 等),但比起其他前端監控服務,Grafana Faro 有以下特點:

  1. 開源: Faro 是完全開源的,所以可以自由修改和擴展。
  2. 自行託管: 可以在自己的基礎設施上部署,保持對數據的完全控制。
  3. 成本效益: 無需支付昂貴的 SaaS 訂閱費用。
  4. 生態系統結合: 與 Grafana 生態系統的其他工具無縫接軌。
  5. OpenTelemetry 整合: 可以與 OpenTelemetry 整合,將數據傳送到其他服務中,例如說 Jaeger、Prometheus 等。

筆者語錄:
總和以上的介紹,Grafana Faro 為前端開發者提供了一個強大、靈活且經濟實惠的監控解決方案。雖然功能尚未非常完善,但依據目前所提供的功能已經可以滿足大部分的監控需求。再加上 Grafana 的生態系統,可以與其他工具如 Loki、Tempo 等整合,提供完整的開源可觀察性解決方案。另外,以其開源的特性,未來的發展性非常高,值得持續關注。

參考資料

ithelp.ithome.com.tw

ithelp.ithome.com.tw

https://grafana.com/oss/faro/

https://github.com/grafana/faro-web-sdk/blob/adbb672f86fe8158022cb93a2802edf6219e6655/packages/web-tracing/src/types.ts

https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/

https://blog.mayflower.de/15107-grafana-faro-frontend-observability.html


上一篇
靠 Grafana 吃飯的第二十二天 - 前端除了監控還需要可觀測性
下一篇
靠 Grafana 吃飯的第二十四天 - Grafana Faro 前端可觀測性的實踐法
系列文
論前端工程師如何靠 Grafana 吃飯:從 Grafana App 到前端可觀測性30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言