1 錯誤報告
Rails 錯誤報告器 提供一個標準方法來收集應用程式中發生的例外狀況,並將它們報告給您偏好的服務或位置。
錯誤報告器的目標是取代像這樣樣板化的錯誤處理程式碼
begin
do_something
rescue SomethingIsBroken => error
MyErrorReportingService.notify(error)
end
使用一致的介面
Rails.error.handle(SomethingIsBroken) do
do_something
end
Rails 將所有執行(例如 HTTP 要求、工作和 rails runner
呼叫)包裝在錯誤報告器中,因此應用程式中引發的任何未處理錯誤都會透過訂閱者自動報告給您的錯誤報告服務。
這表示第三方錯誤回報函式庫不再需要插入 Rack 中介軟體或進行任何猴子修補,就能擷取未處理的例外狀況。使用 ActiveSupport 的函式庫也可以使用此功能,非侵入式地回報以前會遺失在記錄中的警告。
不需要使用 Rails 的錯誤回報器。所有其他擷取錯誤的方法仍然有效。
1.1 訂閱回報器
若要使用錯誤回報器,您需要一個訂閱者。訂閱者是具有 report
方法的任何物件。當應用程式中發生錯誤或手動回報錯誤時,Rails 錯誤回報器會使用錯誤物件和一些選項呼叫此方法。
一些錯誤回報函式庫,例如 Sentry 和 Honeybadger,會自動為您註冊訂閱者。有關更多詳細資訊,請參閱您的供應商文件。
您也可以建立自訂訂閱者。例如
# config/initializers/error_subscriber.rb
class ErrorSubscriber
def report(error, handled:, severity:, context:, source: nil)
MyErrorReportingService.report_error(error, context: context, handled: handled, level: severity)
end
end
定義訂閱者類別後,透過呼叫 Rails.error.subscribe
方法來註冊它
Rails.error.subscribe(ErrorSubscriber.new)
您可以註冊任意數量的訂閱者。Rails 會依序呼叫它們,順序為註冊順序。
Rails 錯誤回報器會始終呼叫已註冊的訂閱者,與您的環境無關。但是,許多錯誤回報服務預設只會回報生產環境中的錯誤。您應該根據需要在各個環境中設定和測試您的設定。
1.2 使用錯誤回報器
您可以使用錯誤回報器的三種方式
1.2.1 回報並吞入錯誤
Rails.error.handle
會回報區塊內引發的任何錯誤。然後,它會吞入錯誤,區塊外的其他程式碼會繼續正常執行。
result = Rails.error.handle do
1 + '1' # raises TypeError
end
result # => nil
1 + 1 # This will be executed
如果區塊中沒有引發錯誤,Rails.error.handle
會傳回區塊的結果,否則會傳回 nil
。您可以提供 fallback
來覆寫此設定
user = Rails.error.handle(fallback: -> { User.anonymous }) do
User.find_by(params[:id])
end
1.2.2 回報並重新引發錯誤
Rails.error.record
會向所有註冊的訂閱者回報錯誤,然後重新引發錯誤,表示您的程式碼的其餘部分不會執行。
Rails.error.record do
1 + '1' # raises TypeError
end
1 + 1 # This won't be executed
如果區塊中沒有引發錯誤,Rails.error.record
會傳回區塊的結果。
1.2.3 手動回報錯誤
您也可以透過呼叫 Rails.error.report
手動回報錯誤。
begin
# code
rescue StandardError => e
Rails.error.report(e)
end
您傳遞的任何選項都會傳遞給錯誤訂閱者。
1.3 錯誤回報選項
所有 3 個回報 API(#handle
、#record
和 #report
)都支援下列選項,然後傳遞給所有註冊的訂閱者
handled
:一個Boolean
,用來表示是否已處理錯誤。預設設定為true
。#record
會將其設定為false
。severity
:一個Symbol
,用來描述錯誤的嚴重性。預期的值為::error
、:warning
和:info
。#handle
會將其設定為:warning
,而#record
會將其設定為:error
。context
:一個Hash
,用來提供有關錯誤的更多內容,例如請求或使用者詳細資料source
:一個String
,用來說明錯誤的來源。預設來源為"application"
。由內部函式庫回報的錯誤可能會設定其他來源;例如,Redis 快取函式庫可能會使用"redis_cache_store.active_support"
。您的訂閱者可以使用來源來忽略您不感興趣的錯誤。
Rails.error.handle(context: { user_id: user.id }, severity: :info) do
# ...
end
1.4 根據錯誤類別篩選
使用 Rails.error.handle
和 Rails.error.record
,您也可以選擇僅報告特定類型的錯誤。例如
Rails.error.handle(IOError) do
1 + '1' # raises TypeError
end
1 + 1 # TypeErrors are not IOErrors, so this will *not* be executed
在此,TypeError
錯誤不會被 Rails 錯誤報告器捕獲。僅會報告 IOError
及其子類的實例。任何其他錯誤都會照常引發。
1.5 全域設定內容
除了透過 context
選項設定內容外,您也可以使用 #set_context
API。例如
Rails.error.set_context(section: "checkout", user_id: @user.id)
任何以此方式設定的內容都會與 context
選項合併
Rails.error.set_context(a: 1)
Rails.error.handle(context: { b: 2 }) { raise }
# The reported context will be: {:a=>1, :b=>2}
Rails.error.handle(context: { b: 3 }) { raise }
# The reported context will be: {:a=>1, :b=>3}
1.6 適用於函式庫
錯誤報告函式庫可以在 Railtie
中註冊其訂閱者
module MySdk
class Railtie < ::Rails::Railtie
initializer "my_sdk.error_subscribe" do
Rails.error.subscribe(MyErrorSubscriber.new)
end
end
end
如果您註冊了一個錯誤訂閱者,但仍有其他錯誤機制,例如 Rack 中介軟體,您可能會多次報告錯誤。您應該移除其他機制或調整報告功能,使其跳過報告它之前已看過的例外情況。
回饋
我們鼓勵您協助改善本指南的品質。
如果您看到任何錯字或事實錯誤,請協助我們修正。若要開始,您可以閱讀我們的 文件貢獻 部分。
您也可能會發現不完整或過時的內容。請務必為主程式新增任何遺漏的文件。請務必先查看 Edge Guides,以驗證問題是否已在主分支中修復。查看 Ruby on Rails 指南指南,了解樣式和慣例。
如果您發現需要修復的問題,但無法自行修補,請 開啟問題。
最後,歡迎在 官方 Ruby on Rails 論壇 上討論有關 Ruby on Rails 文件的任何問題。