Implement ErrorReporter#disable

Ref: https://github.com/rails/rails/pull/43625#discussion_r809532572

It can be used by error reporting service integration when they wish
to handle the error higher in the stack.

For instance Sidekiq has its own error handling interface with a
little bit of extra context information.
This commit is contained in:
Jean Boussier 2022-02-25 13:21:44 +01:00
parent 645239817d
commit 6bbf8d647d
2 changed files with 33 additions and 1 deletions

View File

@ -80,6 +80,21 @@ module ActiveSupport
@subscribers << subscriber
end
# Prevent a subscriber from being notified of errors for the
# duration of the block.
#
# It can be used by error reporting service integration when they wish
# to handle the error higher in the stack.
def disable(subscriber)
disabled_subscribers = (ActiveSupport::IsolatedExecutionState[self] ||= [])
disabled_subscribers << subscriber
begin
yield
ensure
disabled_subscribers.delete(subscriber)
end
end
# Update the execution context that is accessible to error subscribers
#
# Rails.error.set_context(section: "checkout", user_id: @user.id)
@ -98,8 +113,11 @@ module ActiveSupport
end
full_context = ActiveSupport::ExecutionContext.to_h.merge(context)
disabled_subscribers = ActiveSupport::IsolatedExecutionState[self]
@subscribers.each do |subscriber|
subscriber.report(error, handled: handled, severity: severity, context: full_context)
unless disabled_subscribers&.any? { |s| s === subscriber }
subscriber.report(error, handled: handled, severity: severity, context: full_context)
end
rescue => subscriber_error
if logger
logger.fatal(

View File

@ -41,6 +41,20 @@ class ErrorReporterTest < ActiveSupport::TestCase
assert_equal [[error, true, :warning, { section: "public" }]], @subscriber.events
end
test "#disable allow to skip a subscriber" do
@reporter.disable(@subscriber) do
@reporter.report(ArgumentError.new("Oops"), handled: true)
end
assert_equal [], @subscriber.events
end
test "#disable allow to skip a subscribers per class" do
@reporter.disable(ErrorSubscriber) do
@reporter.report(ArgumentError.new("Oops"), handled: true)
end
assert_equal [], @subscriber.events
end
test "#handle swallow and report any unhandled error" do
error = ArgumentError.new("Oops")
@reporter.handle do