เราเพิ่งปล่อยเวอร์ชัน 3.2 ของ honeybadger Ruby Gem ซึ่งรวมฟีเจอร์ใหม่ที่ทำให้เพิ่ม Context ให้ Error Reports ง่ายขึ้น
tl;dr
honeybadger gem ตอนนี้รองรับการกำหนดเมธอด #to_honeybadger_context บน Exception Class ใดๆ เมื่อ Instance ของ Exception นั้นถูก Raise และรายงานไป Honeybadger Context ของมันจะถูกรวมอยู่ใน Error Report อัตโนมัติ:
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 จะรวม:
# {
# custom_attribute: {
# foo: 'bar'
# }
# }
Context คืออะไร?
Context ช่วยให้คุณส่งข้อมูลเพิ่มเติมไป Honeybadger เมื่อเกิดข้อผิดพลาดในแอปพลิเคชัน ใน Rails คุณสามารถตั้งค่า Context สำหรับ Request ปัจจุบันด้วยเมธอด Honeybadger.context ซึ่ง Gem Ruby ของเราให้มา:
Honeybadger.context({ user_email: 'user@example.com' })
ทุก Error ที่เกิดใน Request ปัจจุบัน (หรือ Job ถ้าคุณรัน Background Worker) จะมี Context Data เฉพาะตัวของมันเอง
Context Data ของคุณอาจเป็นอะไรก็ได้ แต่บ่อยครั้งรวมถึงสิ่งๆ เช่น User ID หรือ Email ของ User ที่ Login อยู่, Raw POST Data หรือ Payload ที่เกี่ยวข้องอื่นๆ เพื่อช่วย Debug, ID ของ Background Job ฯลฯ
คุณยังสามารถเพิ่ม Local Context เมื่อรายงาน Error ด้วยตนเอง:
Honeybadger.notify(exception, context: { user_email: 'user@example.com' })
ข้อเท็จจริงน่าสนใจ: แม้ Context จะเป็นอะไรก็ได้ Honeybadger มี Context Keys "พิเศษ" บ้าง เช่น ถ้าคุณรวม Key user_email ไปกับ Error Reports Honeybadger จะสร้างรายงานผู้ใช้ที่ได้รับผลกระทบสำหรับแต่ละ Error
เพิ่ม Context จาก Exceptions
Context บางส่วนเฉพาะเจาะจงต่อ Exception เอง มากกว่าต่อ Request ตัวอย่างเช่น สมมติเราทำ HTTP Request ด้วย Faraday Gem:
require 'faraday'
conn = Faraday.new(url: 'https://example.com') do |faraday|
faraday.response :raise_error # Raise error ถ้า Request ไม่สำเร็จ
faraday.adapter Faraday.default_adapter
end
response = conn.get('/does-not-exist') # => Faraday::ResourceNotFound
โค้ดข้างต้น Raise Exception ต่อไปนี้:
Faraday::ResourceNotFound: the server responded with status 404
Honeybadger จะรายงาน Error นี้อัตโนมัติ (ถ้ากำหนดค่าไว้) แต่จะไม่มีข้อมูลเกี่ยวกับ Object response ข้อมูลนี้จะดีถ้ามี โดยเฉพาะสำหรับ Server Errors ที่ไม่ชัดเจน เช่น 500 Response
ดู Definition ของ Faraday::ResourceNotFound บน GitHub จะเห็นว่ามันเป็นประเภทของ ClientError และ ClientError กำหนด Attribute ที่เก็บ Response Object ไว้บนแต่ละ Instance
ใช้ข้อมูลนี้ เราสามารถ Rescue ทุก Instance ของ Faraday::ClientError และใช้ Honeybadger.notify เพื่อเพิ่ม Response Data เข้า Context:
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
สิ่งนี้ช่วยให้เรารายงาน Failed Requests ไป Honeybadger พร้อมข้อมูลเพิ่มเติมเกี่ยวกับ Response
เราใช้ Pattern นี้สำหรับเพิ่ม Exception-specific Context เมื่อเกิด Error และแม้จะทำงานได้ แต่มันทำให้โค้ดของเราเต็มไปด้วย Rescue Statements และ Custom Notification Logic ซึ่งทำให้ Messy และเพิ่ม Overhead ให้โค้ดมาก ข่าวดีคือ: มีวิธีที่ดีกว่า!
ฟีเจอร์ใหม่: Exception-level Context
แทนที่จะรายงาน Error ด้วยตนเอง Context ตอนนี้สามารถกำหนด บน Exception Class เอง ได้ และ Honeybadger จะรับมันอัตโนมัติ ไม่ว่าจะรายงาน Error ที่ไหน
กลับมาดูตัวอย่างก่อนหน้า แทนที่จะเพิ่ม rescue Statement ที่醜陋 เรามาให้ Built-in Reporting ของ Honeybadger จัดการ Exception แทน:
response = conn.get('/does-not-exist') # => Faraday::ResourceNotFound
แทนที่จะเพิ่ม เรามาเพิ่มเมธอด #to_honeybadger_context ให้ Faraday::ClientError ซึ่งเป็นเมธอดพิเศษที่ Honeybadger ตรวจสอบเมื่อ Exception ใดถูกรายงาน:
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 เราจะได้ Response Context ทุกครั้งที่ Error นั้นเกิดขึ้น โดยไม่ต้องทำให้โค้ดของเรา Messy!