Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Cải Thiện Báo Cáo Lỗi: Thêm Ngữ Cảnh Vào Lớp Ngoại Lệ Trong Honeybadger

Chúng tôi vừa phát hành phiên bản 3.2 của gem honeybadger Ruby, bao gồm một tính năng mới giúp dễ dàng thêm ngữ cảnh vào báo cáo lỗi của bạn.

Tóm tắt

Gem honeybadger hiện hỗ trợ định nghĩa phương thức #to_honeybadger_context trên bất kỳ lớp ngoại lệ nào. Khi một instance của ngoại lệ đó được ném và báo cáo đến Honeybadger, ngữ cảnh của nó sẽ tự động được bao gồm trong báo cáo lỗi:

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' })
# Ngữ cảnh Honeybadger sẽ bao gồm:
# {
#   custom_attribute: {
#     foo: 'bar'
#   }
# }

Ngữ Cảnh Là Gì?

Ngữ cảnh cho phép bạn gửi dữ liệu bổ sung đến Honeybadger khi lỗi xảy ra trong ứng dụng. Trong Rails, bạn có thể đặt ngữ cảnh cho yêu cầu hiện tại bằng phương thức Honeybadger.context, được cung cấp bởi gem Ruby của chúng tôi:

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

Mỗi lỗi xảy ra trong yêu cầu hiện tại (hoặc job nếu bạn đang chạy background worker) sẽ có dữ liệu ngữ cảnh duy nhất của riêng nó.

Dữ liệu ngữ cảnh của bạn có thể là bất cứ thứ gì, nhưng thường bao gồm các thứ như id hoặc email của người dùng đang đăng nhập, một số dữ liệu POST thô hoặc payload liên quan khác để hỗ trợ debug, id của background job, v.v.

Bạn cũng có thể thêm ngữ cảnh cục bộ khi báo cáo lỗi thủ công:

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

Thú vị: trong khi ngữ cảnh có thể là bất cứ thứ gì, Honeybadger có một vài khóa ngữ cảnh "đặc biệt". Ví dụ, nếu bạn bao gồm khóa user_email trong báo cáo lỗi, Honeybadger sẽ tạo báo cáo người dùng bị ảnh hưởng cho mỗi lỗi.

Thêm Ngữ Cảnh Từ Ngoại Lệ

Một số ngữ cảnh cụ thể cho chính ngoại lệ đó, thay vì cho một yêu cầu. Ví dụ, giả sử chúng ta đang thực hiện yêu cầu HTTP bằng gem faraday:

require 'faraday'
conn = Faraday.new(:url => 'https://example.com') do |faraday|
  faraday.response :raise_error # Ném lỗi nếu yêu cầu không thành công
  faraday.adapter Faraday.default_adapter
end
response = conn.get('/does-not-exist') # => Faraday::ResourceNotFound

Code trên ném ngoại lệ sau:

Faraday::ResourceNotFound: the server responded with status 404

Honeybadger sẽ tự động báo cáo lỗi này (giả sử nó được cấu hình để làm vậy), nhưng nó sẽ không có bất kỳ thông tin nào về đối tượng response. Thông tin này sẽ rất hữu ích, đặc biệt cho các lỗi máy chủ không rõ ràng, chẳng hạn như phản hồi 500.

Nhìn vào định nghĩa của Faraday::ResourceNotFound trên GitHub, chúng ta thấy rằng nó thực sự là một loại ClientError, và ClientError định nghĩa một thuộc tính lưu trữ đối tượng response trên mỗi instance.

Sử dụng thông tin này, chúng ta có thể rescue tất cả các instance của Faraday::ClientError và sử dụng Honeybadger.notify để thêm một số dữ liệu response vào ngữ cảnh:

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
  })
  # Xử lý lỗi bổ sung...
end

Điều này cho phép chúng ta báo cáo các yêu cầu thất bại đến Honeybadger cùng với một số thông tin bổ sung về response.

Chúng ta sử dụng pattern này để thêm ngữ cảnh cụ thể cho ngoại lệ khi lỗi xảy ra, và mặc dù nó hoạt động, nhưng nó làm rối code của chúng ta với các câu lệnh rescue và logic thông báo tùy chỉnh, gây lộn xộn và thêm nhiều overhead cho code. Tin tốt: có một cách tốt hơn!

Tính Năng Mới: Ngữ Cảnh Cấp Ngoại Lệ

Thay vì báo cáo lỗi thủ công, ngữ cảnh bây giờ có thể được định nghĩa trên chính lớp ngoại lệ, và Honeybadger sẽ tự động lấy nó, bất kể lỗi cuối cùng được báo cáo ở đâu.

Quay lại ví dụ trước, thay vì thêm một câu lệnh rescue xấu xí, hãy để báo cáo tích hợp sẵn của Honeybadger xử lý ngoại lệ:

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

Thay vào đó, hãy thêm phương thức #to_honeybadger_context vào Faraday::ClientError, đây là một phương thức đặc biệt mà Honeybadger kiểm tra khi bất kỳ ngoại lệ nào được báo cáo:

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

Bằng cách thêm phương thức #to_honeybadger_context vào Faraday::ClientError, chúng ta sẽ nhận được ngữ cảnh response bất cứ khi nào lỗi đó xảy ra, mà không làm rối code của mình!