頂級開源專案 Sentry 20.x JS-SDK 設計藝術(概述篇)

為少發表於2021-03-10

SDK 開發

  1. 頂級開源專案 Sentry 20.x JS-SDK 設計藝術(理念與設計原則篇)
  2. 頂級開源專案 Sentry 20.x JS-SDK 設計藝術(開發基礎篇)

系列

  1. Snuba:Sentry 新的搜尋基礎設施(基於 ClickHouse 之上)
  2. Sentry 10 K8S 雲原生架構探索,Vue App 1 分鐘快速接入
  3. Sentry(v20.x)玩轉前/後端監控與事件日誌大資料分析,使用 Helm 部署到 K8S 叢集
  4. Sentry(v20.x) JavaScript SDK 三種安裝載入方式
  5. Sentry(v20.x) JavaScript SDK 配置詳解
  6. Sentry(v20.x) JavaScript SDK 手動捕獲事件基本用法
  7. Sentry(v20.x) JavaScript SDK Source Maps詳解
  8. Sentry(v20.x) JavaScript SDK 故障排除
  9. Sentry(v20.x) JavaScript SDK 1分鐘上手效能監控
  10. Sentry(v20.x) JavaScript SDK 效能監控之管理 Transactions
  11. Sentry(v20.x) JavaScript SDK 效能監控之取樣 Transactions
  12. Sentry(v20.x) JavaScript SDK Enriching Events(豐富事件資訊)
  13. Sentry(v20.x) JavaScript SDK Data Management(問題分組篇)

概述

下面是一個實現新的 Sentry SDK 的指南。它涵蓋了事件提交的協議,以及客戶端的典型外觀和行為準則。

編寫一個SDK

SDK 的核心是一組實用程式,用於捕獲有關應用程式中異常狀態的資料。給定此資料後,它將構建併傳送 JSON 有效負載並將其傳送到 Sentry 伺服器。

預計可用於生產環境的 SDK 包括以下各項:

  • DSN配置
  • 優雅故障(例如 Sentry 伺服器不可達)
  • 設定屬性(例如 tagsextra data
  • 支援 LinuxWindowsOS X(如果適用)

以下情況需要基於 Feature 的支援:

  • 如果有 Cookie 資料可用,則預設情況下不會傳送
  • 如果有 POST 資料,則預設情況下不會傳送

此外,強烈建議您使用以下功能:

  • 自動錯誤捕獲(例如,未捕獲的異常處理程式 uncaught exception
  • 日誌框架整合
  • 非阻塞事件提交
  • 上下文資料助手(例如,設定當前使用者,記錄麵包屑)
  • 事件取樣
  • Honor SentryHTTP 429 Retry-After header
  • 事件前和事件後傳送鉤子
  • 堆疊跟蹤中的區域性變數值(在可能的平臺上)
  • 為每個事件傳送一個 environment。如果使用者沒有檢測到或設定任何值,則應該使用 production

請參閱 features 頁面,以獲取有關常見的 Sentry SDK 功能的描述。

終端使用者的用法

通常,對於終端使用者來說,使用 SDK 包括三個步驟,無論使用哪種語言,這三個步驟看起來幾乎是相同的:

  1. SDK 的初始化(有時對使用者隱藏):

JavaScript

Sentry.init({dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'});

Python

Sentry.init({dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'});
  1. 捕獲事件:

JavaScript

var resultId = Sentry.captureException(myException);

Python

result_id = sentry_sdk.capture_exception(my_exception);
  1. 使用事件捕獲的結果:

JavaScript

alert(`Your exception was recorded as ${resultId}`);

Python

print('Your exception was recorded as %s', result_id);

理想情況下,init 允許多種配置方法。第一個引數應該總是 DSN 值(如果可能的話):

JavaScript

Sentry.init({
    'dsn': 'https://examplePublicKey@o0.ingest.sentry.io/0',
    'foo': 'bar'
})

請注意:
SDK 應接受一個空的 DSN 作為有效配置。
如果未初始化 SDK,或者使用空 DSN 初始化了 SDK,則 SDK 不應通過網路傳送任何資料,例如捕獲的異常。 根據平臺的不同,SDK 可能會避免執行不必要的初始化工作,並將其執行時佔用空間降至最低。

此外,你應該提供全域性函式來捕捉基本訊息或異常:

  • Sentry.captureMessage(message)
  • Sentry.captureException(exception)

解析DSN

鼓勵SDK通過建構函式允許任意選項,但必須允許第一個引數作為DSN字串。該字串包含以下位:

'{PROTOCOL}://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}{PATH}/{PROJECT_ID}'

您將向其傳送請求的最終端點按照以下方式構造:

 {BASE_URI} = '{PROTOCOL}://{HOST}{PATH}'

'{BASE_URI}/api/{PROJECT_ID}/{ENDPOINT}/'

Sentry 提供以下端點:

  • /envelope/ 用於使用 Envelopes 的任何提交。
  • /store/ 用於提交簡單的 JSON 事件。
  • /minidump/ 用於包含 minidumpmultipart 請求。
  • /unreal/ 用於虛幻引擎4崩潰報告。
  • /security/ 用於瀏覽器 CSP 報告,通常在瀏覽器而不是 SDK 中進行配置。

有關如何組成適當的請求有效負載的資訊,請檢視相應的端點。

例如,給定以下建構函式:

Sentry.init({dsn: 'https://public@sentry.example.com/1'})

您應該解析以下設定:

  • URI = https://sentry.example.com
  • Public Key = public
  • Project ID = 1

對於純 JSON 有效負載的最終 POST 請求隨後將傳輸到:

'https://sentry.example.com/api/1/store/'

請注意:
DSNsecret 部分是可選的,目前已被棄用。如果提供的 Sentry 的未來版本將完全忽略它,clients 仍然應該尊重它。 DSN 解析程式碼不得要求設定 secret key

認證

預期將與訊息正文(message body)一起傳送身份驗證標頭(authentication header),該訊息標頭用作所有權識別符號(ownership identifier):

X-Sentry-Auth: Sentry sentry_version=7,
  sentry_client=<client version, arbitrary>,
  sentry_timestamp=<current timestamp>,
  sentry_key=<public api key>,
  sentry_secret=<secret api key>

僅當 DSN 中包含 secret key 部分時,才必須包含 sentry_secret。協議的未來版本將完全棄用 secret key

請注意:
您應該在標頭的 User-Agent 部分中包含 SDK 版本字串,如果 auth 標頭中未傳送 sentry_client ,則將使用該字串。

在無法傳送自定義 X-Sentry-Auth 標頭的情況下,可以通過查詢字串傳送以下值:

?sentry_version=7&sentry_key=<public api key>&sentry_secret=<secret api key>...

sentry_key

  • 必需的。public key 應作為 SDK 配置的一部分提供。

sentry_version

  • 必需的。協議版本。該協議的當前版本為 7

sentry_client

  • 標識 SDK(包括其版本)的任意字串。典型的模式是 client_name/client_version

例如,Python SDK 可能會將其作為 raven-python/1.0 傳送。

sentry_timestamp

  • Unix 時間戳,表示生成此事件的時間。

sentry_secret

  • 應該作為 SDK 配置的一部分提供的金鑰。

key 已被有效棄用,但由於某些較早的 Sentry 版本在大多數情況下都需要它,因此 SDK 仍應暫時釋放該 key。該 secret key 將在Sentry的未來版本中完全淘汰。

HTTP Headers

我們建議始終傳送以下標頭:

  • content-type
  • content-length

根據 CORS 的策略,允許以下附加頭:

  • x-sentry-auth
  • x-requested-with
  • x-forwarded-for
  • origin
  • referer
  • accept
  • authentication
  • authorization
  • content-encoding
  • transfer-encoding

請求壓縮

強烈建議 SDK 在將請求正文傳送到伺服器之前先對其進行壓縮,以保持資料量較小。首選方法是傳送 content-encoding 標頭。 RelaySentry 接受以下內容編碼:

  • gzip:使用 LZ77 壓縮演算法。
  • deflate:使用 zlib 結構與 deflate 壓縮演算法。
  • br:使用 Brotli 演算法。

傳輸編碼

建議僅對非常大的請求使用傳輸編碼(Transfer Encoding)。 將標頭設定為 transfer-encoding: chunked,這可以省略 content-length 標頭,並要求將請求主體包裝到 chunk 標頭中。

有關更多詳細資訊,請參見 MDN

讀取響應

成功後,您將從伺服器收到一個 HTTP 響應,其中包含 JSON 有效負載以及有關已提交有效負載的資訊:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "fc6d8c0c43fc4630ad850ee518f1b9d0"
}

請注意 Sentry 將使用的響應程式碼。始終檢查 200 響應,這將確認訊息已交付。一個小級別的驗證會立即發生,這可能會導致不同的響應程式碼(和訊息)。

處理錯誤

我們強烈建議您的 SDK 妥善處理來自 Sentry 伺服器的故障。 具體來說,SDK 必須遵守 429 狀態程式碼,並且在 Retry-After 之前不要嘗試傳送。如果 Sentry 不可用,則 SDK 應該丟棄事件,而不是重試。

要在開發過程中除錯錯誤,請檢查響應標頭和響應正文。 例如,您可能會收到類似於以下內容的響應:

HTTP/1.1 400 Bad Request
Content-Type: application/json
X-Sentry-Error: failed to read request body

{
  "detail":"failed to read request body",
  "causes":[
    "failed to decode zlib payload",
    "corrupt deflate stream"
  ]
}

X-Sentry-Error 標頭和響應正文並不總是包含一條訊息,但是它們仍然可以幫助除錯客戶端。發出時,它們將包含精確的錯誤訊息,這對於識別根本原因很有用。

請注意:
我們不建議即使錯誤響應標頭中宣告瞭 Retry-AfterSDK 也不會在發生錯誤時自動重試事件提交。如果請求一次失敗,則很有可能在下一次嘗試時再次失敗。重試次數過多可能會導致進一步的速率限制或 Sentry 伺服器的阻塞。

併發(作用域 Scope 和集線器 Hub)

SDK 應該通過 hubsscopes 的概念來提供標準化的併發處理。統一 API 文件的“併發性”一章中對此進行了更詳細的說明。

整合層

SDK 在可能的情況下應該在較低的層次上整合,這樣可以捕獲儘可能多的執行時。這意味著,如果 SDK 可以直接掛鉤執行時或框架,這比要求使用者子類化特定基類(或混合使用 helper)更可取。例如,Python SDK 將在框架中對核心功能進行 monkey 補丁,以自動拾取錯誤並整合作用域處理。

我是為少
微信:uuhells123
公眾號:黑客下午茶
加我微信(互相學習交流),關注公眾號(獲取更多學習資料~)

相關文章