使用 Sentry 對應用進行監控,少 bug 少加班

Mr_Jing 發表於 2021-10-19

為什麼我們需要應用監控

大家是否有過這樣的體驗:

產品新功能上線幾周後,客戶提工單反饋問題。研發同學經排查確認是 bug,且會產生髒資料。最終,修復 bug + 上線花了大半天,而編寫修復指令碼 + 修復資料耗費了一週。

發現 bug 的時機

如果發現 bug 的時機越早,那麼修復成本就越低

通過對應用中的錯誤或異常進行監控和自動反饋,有助於我們儘早發現隱蔽的問題,提升產品質量和研發效率。

日誌系統不等同應用監控系統

可能有同學會說:程式的錯誤和異常在我們的日誌系統裡面都有呀,為什麼還需要專門的應用監控系統?

確實,日誌中事無鉅細地記錄了大量的執行過程和異常資訊。不過,這些資訊可能也存在重複、無效、缺乏聯絡的弊端。而且,日誌主要是在研發同學排查問題時使用,很少被用於主動監控和告警,日常存在著大量的錯誤資訊一直未被關注和處理。

Sentry:一款受歡迎的應用監控產品

Sentry 是一款開源的應用監控產品,使用 Python、JavaScript、HTML、CSS 打造。在 GitHub 上有 29k Stars,是應用監控領域 Stars 數排行最高的開源專案,其官網宣稱有 1 百萬名開發者和 7 萬個組織在使用 Sentry。除了提供開源產品外,其幕後的公司也提供付費的 SaaS 服務:sentry.io。2021 年該公司宣佈獲得了 6000 萬美元的 D 輪融資,該輪融資使 Sentry 的總資金達到 1.27 億美元,融資後估值為 10 億美元。確實是一款值得關注的產品。

Sentry 有以下重要特點:

  • 產品體驗好,功能完善

    sentry-demo

  • 接入工作量少

    官方和開源社群提供了各種主流開發語言和框架的 SDK,便於開發者接入,大多幾十行程式碼內即可完成。

    SDKs

  • Sentry 專注於 Error、Exception、Crash

    可以檢視到具體的錯誤資訊和呼叫棧,能快速定位問題程式碼。

    js-error

  • 提供豐富的上下文資訊

    SDK 會自動上報基礎資訊,也支援上報自定義的資訊,便於排查問題。

    context

  • 自動合併重複問題

    重複的報錯被自動合併且累計次數,避免開發者在大量重複冗餘的資訊尋找 bug 的蛛絲馬跡。

    issues

  • 主動郵件告警

    不用再等“客戶告警”後才開始排查問題。

自部署 Sentry 的缺點

  • 部署依賴繁多

    利用官方的提供的 Github 倉庫,基於 Docker 和 Docker Compose 確實可以一鍵部署、開箱即用。不過,當看到 30 個容器列在面前時,還是會覺得躊躇。

    containers

  • 需自行保障高可用

    如上,Sentry 使用了眾多元件,比如:ZooKeeper、Nginx、Redis、Memcached、Kafka、PostgreSql、ClickHouse 等,要自行運維這些元件並保障高可用,並不是容易的事情。

避免 Sentry 引發雪崩

引入新的技術或者工具,或多或少都會增加系統的複雜度和執行風險。

我們之前出過一次嚴重問題:某個日均三千萬介面請求量的服務發生故障,大量的錯誤資訊湧向 Sentry 伺服器,導致 Sentry 響應嚴重延遲,其 Redis 佇列記憶體容量接近佔滿,而 Nginx 也全都響應 504 Gateway Timeout。恰好該故障的服務由於請求 Sentry 服務端未設定超時時間,導致 HTTP 請求同步阻塞,反倒拖垮了服務本身。

為了規避此類問題,有以下做法:

  • 保障 Sentry 服務端高可用

    這點最重要,但實際我們並未做好。目前我們自部署的 Sentry 是一個單點,並沒有叢集或冗餘。如果要實現高可用,那麼付出的金錢成本會較高,甚至可能超過了使用 Sentry SaaS 付費服務的成本。由於 Sentry 官方並未提供中國區的服務,HTTP 請求到國外的速度並不理想,使用官方 SaaS 服務也不見得是太好的選擇。

  • 設定 timeout

    使用 Sentry SDK 時,一定要設定向 Sentry 伺服器傳送請求的超時時間,建議 3 秒以下。

  • 設定 sample_rate

    使用 Sentry SDK 時,可以設定取樣率0.00 表示拒絕傳送任何事件,1.00 表示傳送全部事件。建議前期設定較小的值,然後視應用的 PV 大小進行調整。使用取樣率可能會帶來這樣的負面影響:零星的錯誤可能未上報,導致一直未被發現。

  • 及時熔斷
    假如當 Sentry 伺服器不堪重負時,應該避免應用繼續請求 Sentry 了。比如:可以手動將取樣率設定為 0.00
  • 使用非同步方式(async)傳送請求

    如果 SDK 支援非同步傳送請求,那就使用,避免同步阻塞。

  • 隔離生產環境的 Sentry

    運維同事隔離部署了兩套 Sentry,一套是體驗環境,供開發環境/測試環境/預釋出環境的應用接入使用;另外一套是正式環境,供生產環境/私有化環境的應用接入使用。如果要試驗 Sentry 的功能或調整 Sentry 的配置,那我們會先在體驗環境的 Sentry 中進行,確認沒有問題後,才會調整生產環境的 Sentry,藉此保障生產環境 Sentry 的穩定性。

  • 通過佇列來緩衝請求至 Sentry 的併發壓力

    假設應用的請求量和併發量都巨大,當出現嚴重故障時每個請求處理都發生錯誤,那麼即使在 SDK 中設定了較低的取樣率(比如:0.01),可能請求到 Sentry 的併發量依舊超過其有限承載。為了避免這個問題,我們在流量最大的服務中做了如下嘗試:我們增加了一個佇列,將服務的錯誤事件先入列,啟動了少量的消費程式去消費該佇列緩緩上報錯誤至 Sentry 服務端。並且應用程式中做了處理,即使該佇列容量佔滿也不會影響正常業務(只是丟棄錯誤事件)。實踐證明,這種中轉緩衝的方式非常有效,不過也增加了接入 Sentry 工作量,大家可自行取捨。

Sentry 使用小技巧

  • 上報 Environment

    filter-env

    在不同環境通過 SDK 配置不同的標識,比如:Development、Test、Release、Production、Privatisation,這樣方便的識別和過濾問題。

  • 自定義 Tags

    SDK 會自動幫忙上報一些基礎的 Tag,同時我們也能新增一些自定義的 Tag(比如:租戶、專案等業務資訊),利於排查問題。

    tags

    Tag 可用於過濾:

    filter-tag

    Tag 可用於統計:

    tag-stats

  • 自動標記已解決

    有些 bug 已修復並上線,但是研發同學一般都不記得在 Sentry 手動標記已解決;還存在第三方服務異常等不需要處理的問題,也不太會去手動標記。使用“Auto Resolve”功能,當多久內未再出現該問題後,系統會自動幫忙標記為已解決,很方便。

    auto-resolve

  • 合併問題

    絕大多數重複問題,Sentry 都能自動識別併合並。不過偶爾還是存在例外,比如:錯誤資訊中存在一些隨機的內容,那麼 Sentry 可能會以為是不同型別的錯誤,進而未合併,導致重複的問題一直郵件告警,很是煩人。通過設定“Fingerprint Rules”,強制指定同類錯誤的“指紋”,這樣就能讓這些錯誤進行合併了。

    fingerprint-rules

  • 識別並處理真正的問題,避免“狼來了”

    別動不動就拋異常或者記 error。舉個例子:“您上傳的檔案格式不正確,請按要求上傳正確格式的檔案。”,其實這是一個正常的業務提示,如果將它作為錯誤上報到 Sentry,那並沒有什麼意義,最終也不會進行處理。如果這樣的“噪音”越積越多,那麼會降低研發同學對真正問題的敏感度。郵件天天收到一堆假的“狼來了”,當“狼”真來了時,我們可能未採取行動,導致引發事故。當你聽到假的“狼來了”時,正確的做法是讓它閉嘴,而不是捂住自己的耳朵。比如:修改程式碼,不要拋異常,或者將 error 改為 warning。總之,別讓它上報至 Sentry,別讓它干擾我們識別真正的問題。

Sentry 還提供了“效能分析”、“麵包屑”、“識別可疑提交”等眾多有用的功能,值得大家去探索和使用。

我們部門半年來使用 Sentry 的情況

  • 已接入 9 個應用或服務
  • 累計識別出數十個隱蔽問題(去重後)
  • 已有 3 個服務達成零問題
  • 2 次識別到了第三方服務商的異常,並及時反饋給對方處理
  • 2 次及時發現了釋出故障並緊急處理

總結

對應用進行監控可以主動發現隱蔽的問題,提升產品質量。Sentry 是一款受歡迎的應用監控開源產品,擁有豐富且有用的特性,我們選擇使用它的同時,也採取了很多措施,避免因為引入它導致產生負面影響。我們在使用過程中積累了一點心得,最後也獲得了不錯的使用效果,分享給大家,祝大家 bug 少少,效率高高。