Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

การเพิ่มบริบทให้กับคลาสข้อยกเว้น

เมื่อเร็วๆ นี้เราได้จัดส่ง ฮันนี่แบดเจอร์เวอร์ชัน 3.2 Ruby Gem ซึ่งมีฟีเจอร์ใหม่ที่ช่วยให้เพิ่มบริบทในรายงานข้อผิดพลาดได้ง่ายขึ้น

tl;dr

ฮันนี่แบดเจอร์ gem รองรับการกำหนด #to_honeybadger_context วิธีการในคลาสข้อยกเว้นใด ๆ เมื่อมีการแจ้งข้อยกเว้นดังกล่าวและรายงานไปยัง Honeybadger บริบทของข้อยกเว้นนั้นจะถูกรวมไว้ในรายงานข้อผิดพลาดโดยอัตโนมัติ:

class MyError < StandardError
  attr_reader :custom_attribute

  def initialize(err, custom_attribute)
    @custom_attribute = custom_attribute
    super(err)
  end

  def to_honeybadger_context
    {
      custom_attribute: custom_attribute
    }
  end
end

raise MyError.new("Something went wrong", { foo: 'bar' })
# Honeybadger context will include:
# {
#   custom_attribute: {
#     foo: 'bar'
#   }
# }

บริบทคืออะไร

บริบทช่วยให้คุณส่งข้อมูลเพิ่มเติมไปยัง Honeybadger เมื่อเกิดข้อผิดพลาดในแอปพลิเคชันของคุณ ใน Rails คุณสามารถตั้งค่าบริบทสำหรับคำขอปัจจุบันโดยใช้ Honeybadger.context วิธีการซึ่งให้บริการโดยอัญมณีทับทิมของเรา:

Honeybadger.context({
  user_email: 'user@example.com'
})

ทุกข้อผิดพลาดที่เกิดขึ้นในคำขอปัจจุบัน (หรืองานหากคุณกำลังเรียกใช้งานเบื้องหลัง) จะมีข้อมูลบริบทเฉพาะของตัวเอง

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

คุณยังเพิ่มบริบทในเครื่องได้เมื่อรายงานข้อผิดพลาดด้วยตนเอง:

Honeybadger.notify(exception, context: {
  user_email: 'user@example.com'
})

ข้อเท็จจริงที่น่าสนุก:แม้ว่าบริบทจะเป็นอะไรก็ได้ แต่ฮันนี่แบดเจอร์ก็มีคีย์บริบท "พิเศษ" สองสามคีย์ ตัวอย่างเช่น หากคุณใส่ user_email พร้อมรายงานข้อผิดพลาดของคุณ Honeybadger จะสร้างรายงานของผู้ใช้ที่ได้รับผลกระทบสำหรับแต่ละข้อผิดพลาด

การเพิ่มบริบทจากข้อยกเว้น

บริบทบางอย่างมีความเฉพาะเจาะจงสำหรับตัวข้อยกเว้นเอง แทนที่จะเป็นคำขอ ตัวอย่างเช่น สมมติว่าเรากำลังส่งคำขอ HTTP โดยใช้ faraday gem:

require 'faraday'

conn = Faraday.new(:url => 'https://example.com') do |faraday|
  faraday.response :raise_error # Raises an error if the request isn't successful
  faraday.adapter  Faraday.default_adapter
end

response = conn.get('/does-not-exist') # => Faraday::ResourceNotFound

รหัสด้านบนทำให้เกิดข้อยกเว้นดังต่อไปนี้:

Faraday::ResourceNotFound: the server responded with status 404

Honeybadger จะรายงานข้อผิดพลาดนี้โดยอัตโนมัติ (สมมติว่ามีการกำหนดค่าให้ทำเช่นนั้น) แต่จะไม่มีข้อมูลใดๆ เกี่ยวกับ response วัตถุ. ข้อมูลนี้น่าจะดี โดยเฉพาะอย่างยิ่งสำหรับข้อผิดพลาดของเซิร์ฟเวอร์ที่ไม่ค่อยชัดเจน เช่น การตอบกลับ 500 ครั้ง

ดูคำจำกัดความของ Faraday::ResourceNotFound บน GitHub เราเห็นว่าจริง ๆ แล้วมันเป็นประเภท ClientError และ ClientError กำหนดแอตทริบิวต์ที่เก็บวัตถุตอบสนองในแต่ละอินสแตนซ์

เมื่อใช้ข้อมูลนี้ เราสามารถกู้คืน Faraday::ClientError . ทุกอินสแตนซ์ได้ และใช้ Honeybadger.notify เพื่อเพิ่มข้อมูลการตอบกลับไปยังบริบท:

begin
  response = conn.get('/does-not-exist')
rescue Faraday::ClientError => err
  Honeybadger.notify(err, context: {
    response_status:  err.response.status,
    response_headers: err.response.headers
  })
  # Additional error handling...
end

ซึ่งช่วยให้เราสามารถรายงานคำขอที่ล้มเหลวไปยัง Honeybadger พร้อมกับข้อมูลเพิ่มเติมเกี่ยวกับการตอบกลับ

เราใช้รูปแบบนี้เพื่อเพิ่มบริบทเฉพาะข้อยกเว้นเมื่อมีข้อผิดพลาดเกิดขึ้น และในขณะที่มันทำงาน มันทำให้โค้ดของเรายุ่งเหยิงด้วยคำสั่งช่วยเหลือและตรรกะการแจ้งเตือนที่กำหนดเอง ซึ่งยุ่งเหยิงและเพิ่มโอเวอร์เฮดให้กับโค้ดของเรา ข่าวดี:มีวิธีที่ดีกว่า!

คุณลักษณะใหม่:บริบทระดับข้อยกเว้น

แทนที่จะรายงานข้อผิดพลาดด้วยตนเอง ตอนนี้สามารถกำหนดบริบทได้ ในคลาสข้อยกเว้นเอง และ Honeybadger จะหยิบมันขึ้นมาโดยอัตโนมัติไม่ว่าจะมีการรายงานข้อผิดพลาดที่ใด

ทบทวนตัวอย่างก่อนหน้านี้ แทนที่จะเพิ่ม rescue . ที่น่าเกลียด คำสั่ง ปล่อยให้การรายงานในตัวของ Honeybadger จัดการกับข้อยกเว้น:

response = conn.get('/does-not-exist') # => Faraday::ResourceNotFound

ให้เพิ่ม #to_honeybadger_context . แทน วิธีการ Faraday::ClientError ซึ่งเป็นวิธีพิเศษที่ Honeybadger ตรวจสอบเมื่อมีการรายงานข้อยกเว้น:

Faraday::ClientError.class_eval do
  def to_honeybadger_context
    {
      response_status:  err.response.status,
      response_headers: err.response.headers
    }
  end
end

โดยการเพิ่ม #to_honeybadger_context วิธีการ Faraday::ClientError เราจะได้รับบริบทการตอบสนองทุกครั้งที่เกิดข้อผิดพลาดโดยไม่ทำให้โค้ดของเรารก!