edge
เพิ่มเติมที่ rubyonrails.org: เพิ่มเติมเกี่ยวกับ Ruby on Rails

การรายงานข้อผิดพลาดในแอปพลิเคชัน Rails

เอกสารนี้จะแนะนำวิธีการจัดการข้อผิดพลาดที่เกิดขึ้นในแอปพลิเคชัน Ruby on Rails

หลังจากอ่านเอกสารนี้คุณจะรู้:

1 การรายงานข้อผิดพลาด

Rails error reporter ให้วิธีมาตรฐานในการรวบรวมข้อผิดพลาดที่เกิดขึ้นในแอปพลิเคชันของคุณและรายงานให้บริการหรือตำแหน่งที่คุณต้องการ

Error reporter มีเป้าหมายที่จะแทนที่โค้ดการจัดการข้อผิดพลาดที่ซ้ำซ้อนเช่นนี้:

begin
  do_something
rescue SomethingIsBroken => error
  MyErrorReportingService.notify(error)
end

ด้วยอินเทอร์เฟซที่สอดคล้อง:

Rails.error.handle(SomethingIsBroken) do
  do_something
end

Rails ครอบคลุมการดำเนินการทั้งหมด (เช่นการร้องขอ HTTP, งาน และการเรียกใช้ rails runner) ใน error reporter เพื่อให้ข้อผิดพลาดที่ไม่ได้รับการจัดการที่เกิดขึ้นในแอปของคุณถูกรายงานโดยอัตโนมัติไปยังบริการรายงานข้อผิดพลาดของคุณผ่าน subscribers ของพวกเขา

นั่นหมายความว่าไลบรารีการรายงานข้อผิดพลาดจากบุคคลที่สามไม่จำเป็นต้องแทรก Rack middleware หรือทำการ monkey-patching เพื่อจับข้อผิดพลาดที่ไม่ได้รับการจัดการไว้ ไลบรารีที่ใช้ ActiveSupport ยังสามารถใช้สิ่งนี้เพื่อรายงานคำเตือนที่อาจหายไปในบันทึกได้อย่างไม่เข้ารุก

การใช้ error reporter ของ Rails ไม่จำเป็น วิธีการรับข้อผิดพลาดที่อื่นยังคงทำงานได้

1.1 การสมัครสมาชิกกับ Reporter

ในการใช้ error reporter คุณต้องมี subscriber ซึ่งเป็นอ็อบเจกต์ใด ๆ ที่มีเมธอด report เมื่อเกิดข้อผิดพลาดในแอปของคุณหรือรายงานด้วยตนเอง error reporter ของ Rails จะเรียกเมธอดนี้พร้อมกับอ็อบเจกต์ข้อผิดพลาดและตัวเลือกบางอย่าง

บางไลบรารีการรายงานข้อผิดพลาด เช่น Sentry's และ Honeybadger's จะลงทะเบียน subscriber ให้คุณโดยอัตโนมัติ โปรดอ่านเอกสารของผู้ให้บริการของคุณเพื่อดูรายละเอียดเพิ่มเติม

คุณยังสามารถสร้าง subscriber ที่กำหนดเองได้ เช่น:

# 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

หลังจากกำหนดคลาส subscriber เสร็จ ลงทะเบียนโดยเรียกใช้เมธอด Rails.error.subscribe:

Rails.error.subscribe(ErrorSubscriber.new)

คุณสามารถลงทะเบียน subscribers ได้เท่าที่คุณต้องการ Rails จะเรียกใช้พวกเขาตามลำดับที่ลงทะเบียน

หมายเหตุ: error-reporter ของ Rails จะเรียก subscribers ที่ลงทะเบียนเสมอไม่ว่าสภาพแวดล้อมของคุณจะเป็นอย่างไร อย่างไรก็ตาม บริการรายงานข้อผิดพลาดหลายรายการมักจะรายงานข้อผิดพลาดในโหมดการผลิตเท่านั้นตามค่าเริ่มต้น คุณควรกำหนดค่าและทดสอบการตั้งค่าของคุณในสภาพแวดล้อมต่าง ๆ ตามที่จำเป็น

1.2 การใช้ Error Reporter

มีวิธีที่คุณสามารถใช้ error reporter ได้สามวิธี:

1.2.1 การรายงานและการยึดข้อผิดพลาด

Rails.error.handle จะรายงานข้อผิดพลาดที่เกิดขึ้นในบล็อก และจะ ยึด ข้อผิดพลาดนั้น และโค้ดที่เหลือของคุณนอกบล็อกจะดำเนินการต่อไปเหมือนเดิม

result = Rails.error.handle do
  1 + '1' # ยกเลิก TypeError
end
result # => nil
1 + 1 # จะถูกดำเนินการ

หากไม่มีข้อผิดพลาดที่เกิดขึ้นในบล็อก 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 จะรายงานข้อผิดพลาดให้กับ subscribers ที่ลงทะเบียนทั้งหมดและจะยกเลิกข้อผิดพลาดนั้น หมายความว่าโค้ดที่เหลือของคุณจะไม่ถูกดำเนินการต่อ ```ruby Rails.error.record do 1 + '1' # ยกเลิก TypeError end 1 + 1 # ไม่ได้รัน


ถ้าไม่มีข้อผิดพลาดที่เกิดขึ้นในบล็อก `Rails.error.record` จะส่งคืนผลลัพธ์ของบล็อก

#### รายงานข้อผิดพลาดด้วยตนเอง

คุณยังสามารถรายงานข้อผิดพลาดด้วยตนเองได้โดยเรียกใช้ [`Rails.error.report`](https://api.rubyonrails.org/classes/ActiveSupport/ErrorReporter.html#method-i-report):

```ruby
begin
  # โค้ด
rescue StandardError => e
  Rails.error.report(e)
end

ตัวเลือกใด ๆ ที่คุณส่งผ่านจะถูกส่งต่อไปยังผู้สมัครรับข้อผิดพลาดทั้งหมด

1.3 ตัวเลือกการรายงานข้อผิดพลาด

API การรายงานทั้ง 3 (#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' # ยกเลิก TypeError
end
1 + 1 # TypeErrors ไม่ใช่ IOError ดังนั้นจะ *ไม่* รัน

ที่นี่ TypeError จะไม่ถูกจับได้โดยตัวรายงานข้อผิดพลาดของ Rails แต่จะรายงานเฉพาะอินสแตนซ์ของ IOError และลูกสายของมันเท่านั้น ข้อผิดพลาดอื่น ๆ จะถูกยกเลิกเหมือนเดิม

1.5 ตั้งค่า Context ทั่วโลก

นอกจากการตั้งค่า context ผ่านตัวเลือก context คุณยังสามารถใช้ #set_context API ได้ เช่น:

Rails.error.set_context(section: "checkout", user_id: @user.id)

Context ใด ๆ ที่ตั้งค่าด้วยวิธีนี้จะถูกผสานกับตัวเลือก context

Rails.error.set_context(a: 1)
Rails.error.handle(context: { b: 2 }) { raise }
# Context ที่รายงานคือ: {:a=>1, :b=>2}
Rails.error.handle(context: { b: 3 }) { raise }
# Context ที่รายงานคือ: {: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 middleware คุณอาจพบว่าข้อผิดพลาดถูกรายงานหลายครั้ง คุณควรลบกลไกอื่น ๆ หรือปรับฟังก์ชันการรายงานข้อผิดพลาดของคุณเพื่อให้ข้ามการรายงานข้อผิดพลาดที่เคยเห็นแล้ว

ข้อเสนอแนะ

คุณสามารถช่วยปรับปรุงคุณภาพของคู่มือนี้ได้

กรุณาช่วยเพิ่มเติมหากพบข้อผิดพลาดหรือข้อผิดพลาดทางความจริง เพื่อเริ่มต้นคุณสามารถอ่านส่วน การสนับสนุนเอกสาร ของเราได้

คุณอาจพบเนื้อหาที่ไม่สมบูรณ์หรือเนื้อหาที่ไม่ได้อัปเดต กรุณาเพิ่มเอกสารที่ขาดหายไปสำหรับเนื้อหาหลัก โปรดตรวจสอบ Edge Guides ก่อนเพื่อตรวจสอบ ว่าปัญหาได้รับการแก้ไขหรือไม่ในสาขาหลัก ตรวจสอบ คู่มือแนวทาง Ruby on Rails เพื่อดูรูปแบบและกฎเกณฑ์

หากคุณพบข้อผิดพลาดแต่ไม่สามารถแก้ไขได้เอง กรุณา เปิดปัญหา.

และสุดท้าย การสนทนาใด ๆ เกี่ยวกับ Ruby on Rails เอกสารยินดีต้อนรับที่สุดใน เว็บบอร์ดอย่างเป็นทางการของ Ruby on Rails.