Faro── 前端的可觀測性#
到目前為止,我們討論的所有可觀測性技術都聚焦在後端:伺服器的 Metrics、應用程式的 Logs、服務之間的 Traces。但使用者體驗的最後一哩路發生在瀏覽器端——頁面載入緩慢、JavaScript 錯誤、佈局閃爍——這些問題後端指標完全看不到。
Grafana Faro 是一個前端可觀測性 SDK,專門用來收集瀏覽器端的錯誤、效能指標和使用者行為,並將它們整合進 Grafana 生態系。
Concepts#
Web Vitals#
Web Vitals 是 Google 定義的一組核心使用者體驗指標,反映的是「真實使用者感受到的效能」。三個最重要的指標:
- LCP(Largest Contentful Paint):頁面主要內容呈現完成的時間。衡量的是「使用者覺得頁面載入好了」的那一刻。目標值在 2.5 秒以內
- INP(Interaction to Next Paint):使用者互動(點擊、按鍵)後,畫面回應的延遲。取代了舊的 FID 指標,衡量的是「點了按鈕後多久有反應」。目標值在 200 毫秒以內
- CLS(Cumulative Layout Shift):頁面元素在載入過程中意外移位的程度。衡量的是「正要點某個東西,它突然跳走了」的惱人體驗。目標值在 0.1 以下
Web Vitals 與後端的延遲指標有本質差異。後端的 P99 延遲可能是 50ms,但使用者感受到的 LCP 可能是 3 秒——因為中間還有 DNS 解析、TCP 連線、TLS 交握、HTML 解析、資源載入、JavaScript 執行、渲染等等環節。
這些指標的價值在於:它們是從真實使用者的瀏覽器中收集的(Real User Monitoring, RUM),反映的是不同網路環境、不同裝置上的真實體驗,而非開發者在高速網路上用高端機器測出的理想值。
Architecture#
Faro 的架構遵循「收集 → 傳輸 → 儲存 → 查詢」的模式:
- Faro Web SDK(瀏覽器端):嵌入在前端應用程式中,收集錯誤、效能指標、使用者行為
- Grafana Alloy(收集端點):作為接收端,接受 Faro SDK 送出的資料,並根據類型路由到不同的後端
- Loki(日誌儲存):儲存前端的錯誤日誌、Console Log、頁面事件
- Tempo(Trace 儲存):儲存前端的 Trace 資料(使用者操作到後端 API 調用的完整鏈路)
- Prometheus / Mimir(Metrics 儲存):儲存從日誌衍生出的指標
Faro SDK 收集的資料是從使用者的瀏覽器發送的,這意味著收集端點(Alloy)必須暴露在公網上。需要考慮速率限制、CORS 設定、以及避免收集敏感的使用者資料(如個資)。
Log-based Metrics#
Faro 有一個巧妙的設計:它不直接產出 Metrics,而是將前端事件以日誌的形式送到 Loki,再透過 Loki 的 Recording Rule 或 Alloy 的處理能力,從日誌中衍生出 Metrics。
例如:
- 前端每次發生 JavaScript 錯誤,Faro 送出一筆錯誤日誌到 Loki
- Loki 的 Recording Rule 統計「每分鐘的前端錯誤次數」,產出一個 Metric
- 這個 Metric 可以用來設定告警:「前端錯誤率超過閾值時通知團隊」
這個架構的好處是減少前端上報的複雜度——SDK 只需要送日誌,不需要在瀏覽器端做聚合計算。所有的聚合和轉換都在後端完成。
Usage#
Alloy 作為收集端點#
在 Faro 的架構中,Alloy 扮演的是前端資料的入口閘道。它接收 Faro SDK 透過 HTTP 送出的 Payload,然後根據資料類型分流:
- 日誌型的資料(錯誤、Console Log、事件)→ 送到 Loki
- Trace 型的資料(前端 Span)→ 送到 Tempo
- 中間可以加入處理邏輯,如過濾、取樣、Label 注入
為什麼不直接從瀏覽器送到 Loki/Tempo?因為 Alloy 提供了一層緩衝和安全控制:速率限制、來源驗證、資料格式轉換。直接暴露 Loki 或 Tempo 的寫入端點到公網,既不安全也不實際。
Faro Web SDK#
Faro Web SDK 是嵌入在前端應用程式中的 JavaScript 程式庫。它在初始化後會自動收集:
- JavaScript 錯誤:未捕獲的例外(Uncaught Exception)、Promise Rejection
- Console Log:console.error、console.warn 等
- Web Vitals:LCP、INP、CLS 等核心效能指標
- 頁面事件:頁面導航、路由切換
- Session 資訊:使用者 Session ID,用來串聯同一使用者的所有事件
Faro SDK 的初始化位置很重要。盡量將它放在應用程式的最早期載入階段,這樣才能捕捉到初始載入過程中的錯誤和效能指標。如果 SDK 在錯誤發生之後才載入,那些錯誤就會遺漏。
SDK 的設計原則是輕量且低侵入:它不會影響應用程式的效能,資料上報採用異步方式,並且在網路不佳時會自動降級(丟棄資料而非阻塞使用者操作)。
Faro Web Tracing#
Faro 的 Tracing 功能將前端與後端的可觀測性完整串連。它基於 OpenTelemetry 的 Web SDK,能夠:
- 為前端的使用者操作(如按鈕點擊)建立 Span
- 自動為 Fetch / XMLHttpRequest 請求建立 Span
- 在 HTTP Header 中注入 Trace Context(W3C Trace Context 格式)
- 後端收到請求時,從 Header 中讀取 Trace Context,繼續串接 Span
這意味著一個完整的 Trace 可以從「使用者點擊按鈕」開始,經過「前端發送 API 請求」、「API Gateway」、「後端服務 A」、「後端服務 B」、「資料庫查詢」,形成一條從瀏覽器到資料庫的完整鏈路。
前端 Tracing 的取樣策略需要額外考慮。前端流量通常遠大於後端(每個使用者的每次操作都可能產生 Trace),如果不做取樣,Trace 資料量會非常驚人。建議從低取樣率開始,根據需求逐步調整。
適用場景#
Faro 最適合的場景:
- Web 應用程式:特別是 SPA(Single Page Application),使用者體驗高度依賴前端效能
- 需要了解真實使用者體驗:不是開發環境的 Lighthouse 分數,而是真實使用者在各種裝置和網路條件下的體驗
- 需要端到端的 Trace:從使用者操作到後端回應的完整鏈路,找出延遲究竟是前端還是後端造成的
- 前端錯誤監控:即時掌握生產環境中的 JavaScript 錯誤,不再依賴使用者回報
前端可觀測性收集的是使用者端的資料,涉及隱私合規問題(如 GDPR)。務必確認:不收集個人識別資訊(PII)、遵守 Cookie 同意機制、資料儲存符合所在地區的法規要求。