lib/airbrake/sneakers.rb
# frozen_string_literal: true
module Airbrake
module Sneakers
# Provides integration with Sneakers.
#
# @see https://github.com/jondot/sneakers
# @since v7.2.0
class ErrorReporter
# @return [Array<Symbol>] ignored keys values of which raise
# SystemStackError when `as_json` is called on them
# @see https://github.com/airbrake/airbrake/issues/850
IGNORED_KEYS = %i[delivery_tag consumer channel].freeze
# rubocop:disable Style/OptionalArguments
def call(exception, worker = nil, context)
# Later versions add a middle argument.
Airbrake.notify(exception, filter_context(context)) do |notice|
notice[:context][:component] = 'sneakers'
notice[:context][:action] = worker.class.to_s
end
end
# rubocop:enable Style/OptionalArguments
private
def filter_context(context)
return context unless context[:delivery_info]
h = context.dup
h[:delivery_info] = context[:delivery_info].reject do |k, _v|
IGNORED_KEYS.include?(k)
end
h
end
end
end
end
Sneakers.error_reporters << Airbrake::Sneakers::ErrorReporter.new
module Airbrake
module Sneakers
# @todo Migrate to Sneakers v2.12.0 middleware API when it's released
# @see https://github.com/jondot/sneakers/pull/364
module Worker
# Sneakers v2.7.0+ renamed `do_work` to `process_work`.
define_method(
::Sneakers::Worker.method_defined?(:process_work) ? :process_work : :do_work,
) do |delivery_info, metadata, msg, handler|
timing = Airbrake::Benchmark.measure do
super(delivery_info, metadata, msg, handler)
end
rescue Exception => exception # rubocop:disable Lint/RescueException
Airbrake.notify_queue(
queue: self.class.to_s,
error_count: 1,
timing: 0.01,
)
raise exception
else
Airbrake.notify_queue(
queue: self.class.to_s,
error_count: 0,
timing: timing,
)
end
end
end
end
Sneakers::Worker.prepend(Airbrake::Sneakers::Worker)