From 6c4d7d53f7356717894269b5fc9095621c9e8014 Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Thu, 21 Nov 2024 11:27:40 -0800 Subject: [PATCH] feat: skip middleware, plugins, and exception reporting when exceptions are disabled (#646) --------- Co-authored-by: Roel Bondoc --- lib/honeybadger/agent.rb | 5 ++ lib/honeybadger/init/hanami.rb | 2 +- lib/honeybadger/init/rails.rb | 8 ++- lib/honeybadger/plugins/active_job.rb | 2 +- lib/honeybadger/plugins/delayed_job.rb | 1 + lib/honeybadger/plugins/faktory.rb | 1 + lib/honeybadger/plugins/karafka.rb | 8 ++- lib/honeybadger/plugins/rails.rb | 2 +- lib/honeybadger/plugins/resque.rb | 1 + lib/honeybadger/plugins/shoryuken.rb | 1 + lib/honeybadger/plugins/sidekiq.rb | 84 +++++++++++++------------ lib/honeybadger/plugins/sucker_punch.rb | 1 + lib/honeybadger/plugins/thor.rb | 1 + 13 files changed, 67 insertions(+), 50 deletions(-) diff --git a/lib/honeybadger/agent.rb b/lib/honeybadger/agent.rb index 4f8811ced..39f74e34c 100644 --- a/lib/honeybadger/agent.rb +++ b/lib/honeybadger/agent.rb @@ -125,6 +125,11 @@ def initialize(opts = {}) # @return [String] UUID reference to the notice within Honeybadger. # @return [false] when ignored. def notify(exception_or_opts = nil, opts = {}, **kwargs) + if !config[:'exceptions.enabled'] + debug { 'disabled feature=notices' } + return false + end + opts = opts.dup opts.merge!(kwargs) diff --git a/lib/honeybadger/init/hanami.rb b/lib/honeybadger/init/hanami.rb index ac00a365c..3965e5d09 100644 --- a/lib/honeybadger/init/hanami.rb +++ b/lib/honeybadger/init/hanami.rb @@ -8,7 +8,7 @@ Honeybadger.load_plugins! -if Hanami::VERSION >= '2.0' +if Hanami::VERSION >= '2.0' && Honeybadger.config[:'exceptions.enabled'] Hanami.app.instance_eval do config.middleware.use Honeybadger::Rack::UserFeedback config.middleware.use Honeybadger::Rack::UserInformer diff --git a/lib/honeybadger/init/rails.rb b/lib/honeybadger/init/rails.rb index 2180c71ba..5c806bcb3 100644 --- a/lib/honeybadger/init/rails.rb +++ b/lib/honeybadger/init/rails.rb @@ -14,9 +14,11 @@ class Railtie < ::Rails::Railtie initializer 'honeybadger.install_middleware' do |app| honeybadger_config = Honeybadger::Agent.instance.config - app.config.middleware.insert(0, Honeybadger::Rack::ErrorNotifier) - app.config.middleware.insert_before(Honeybadger::Rack::ErrorNotifier, Honeybadger::Rack::UserInformer) if honeybadger_config[:'user_informer.enabled'] - app.config.middleware.insert_before(Honeybadger::Rack::ErrorNotifier, Honeybadger::Rack::UserFeedback) if honeybadger_config[:'feedback.enabled'] + if honeybadger_config[:'exceptions.enabled'] + app.config.middleware.insert(0, Honeybadger::Rack::ErrorNotifier) + app.config.middleware.insert_before(Honeybadger::Rack::ErrorNotifier, Honeybadger::Rack::UserInformer) if honeybadger_config[:'user_informer.enabled'] + app.config.middleware.insert_before(Honeybadger::Rack::ErrorNotifier, Honeybadger::Rack::UserFeedback) if honeybadger_config[:'feedback.enabled'] + end end config.before_initialize do diff --git a/lib/honeybadger/plugins/active_job.rb b/lib/honeybadger/plugins/active_job.rb index 12eec561f..941881d37 100644 --- a/lib/honeybadger/plugins/active_job.rb +++ b/lib/honeybadger/plugins/active_job.rb @@ -51,7 +51,7 @@ def context(job) # rubocop:disable Metrics/MethodLength end execution do - ::ActiveJob::Base.set_callback(:perform, :around, &ActiveJob.method(:perform_around)) + ::ActiveJob::Base.set_callback(:perform, :around, &ActiveJob.method(:perform_around)) if Honeybadger.config[:'exceptions.enabled'] if config.load_plugin_insights?(:active_job) ::ActiveSupport::Notifications.subscribe(/(enqueue_at|enqueue|enqueue_retry|enqueue_all|perform|retry_stopped|discard)\.active_job/, Honeybadger::ActiveJobSubscriber.new) diff --git a/lib/honeybadger/plugins/delayed_job.rb b/lib/honeybadger/plugins/delayed_job.rb index b7bddb92e..da23c2fdd 100644 --- a/lib/honeybadger/plugins/delayed_job.rb +++ b/lib/honeybadger/plugins/delayed_job.rb @@ -15,6 +15,7 @@ module Honeybadger end execution do + return unless Honeybadger.config[:'exceptions.enabled'] require 'honeybadger/plugins/delayed_job/plugin' ::Delayed::Worker.plugins << Plugins::DelayedJob::Plugin end diff --git a/lib/honeybadger/plugins/faktory.rb b/lib/honeybadger/plugins/faktory.rb index 63b6ab9d9..a13401f3e 100644 --- a/lib/honeybadger/plugins/faktory.rb +++ b/lib/honeybadger/plugins/faktory.rb @@ -15,6 +15,7 @@ def call(worker, job) requirement { defined?(::Faktory) } execution do + return unless Honeybadger.config[:'exceptions.enabled'] ::Faktory.configure_worker do |faktory| faktory.worker_middleware do |chain| chain.prepend Middleware diff --git a/lib/honeybadger/plugins/karafka.rb b/lib/honeybadger/plugins/karafka.rb index e17e30eca..a7d84f536 100644 --- a/lib/honeybadger/plugins/karafka.rb +++ b/lib/honeybadger/plugins/karafka.rb @@ -8,9 +8,11 @@ module Plugins execution do require 'honeybadger/karafka' - errors_listener = ::Honeybadger::Karafka::ErrorsListener.new - ::Karafka.monitor.subscribe(errors_listener) - ::Karafka.producer.monitor.subscribe(errors_listener) if ::Karafka.respond_to?(:producer) + if Honeybadger.config[:'exceptions.enabled'] + errors_listener = ::Honeybadger::Karafka::ErrorsListener.new + ::Karafka.monitor.subscribe(errors_listener) + ::Karafka.producer.monitor.subscribe(errors_listener) if ::Karafka.respond_to?(:producer) + end if config.load_plugin_insights?(:karafka) ::Karafka.monitor.subscribe(::Honeybadger::Karafka::InsightsListener.new) diff --git a/lib/honeybadger/plugins/rails.rb b/lib/honeybadger/plugins/rails.rb index 60c920af5..3f7fbe14d 100644 --- a/lib/honeybadger/plugins/rails.rb +++ b/lib/honeybadger/plugins/rails.rb @@ -64,7 +64,7 @@ def self.source_ignored?(source) ::ActionDispatch::ShowExceptions.prepend(ExceptionsCatcher) end - if defined?(::ActiveSupport::ErrorReporter) # Rails 7 + if Honeybadger.config[:'exceptions.enabled'] && defined?(::ActiveSupport::ErrorReporter) # Rails 7 ::Rails.error.subscribe(ErrorSubscriber) end end diff --git a/lib/honeybadger/plugins/resque.rb b/lib/honeybadger/plugins/resque.rb index 85e6363f0..8ec04aca2 100644 --- a/lib/honeybadger/plugins/resque.rb +++ b/lib/honeybadger/plugins/resque.rb @@ -64,6 +64,7 @@ def payload_class_with_honeybadger end execution do + return unless Honeybadger.config[:'exceptions.enabled'] ::Resque::Job.send(:include, Installer) end end diff --git a/lib/honeybadger/plugins/shoryuken.rb b/lib/honeybadger/plugins/shoryuken.rb index 3f6e3a45c..d15f10cde 100644 --- a/lib/honeybadger/plugins/shoryuken.rb +++ b/lib/honeybadger/plugins/shoryuken.rb @@ -40,6 +40,7 @@ def notification_params(body) requirement { defined?(::Shoryuken) } execution do + return unless Honeybadger.config[:'exceptions.enabled'] ::Shoryuken.configure_server do |config| config.server_middleware do |chain| chain.add Middleware diff --git a/lib/honeybadger/plugins/sidekiq.rb b/lib/honeybadger/plugins/sidekiq.rb index f81685dcc..ceb266da3 100644 --- a/lib/honeybadger/plugins/sidekiq.rb +++ b/lib/honeybadger/plugins/sidekiq.rb @@ -73,60 +73,62 @@ def call(worker, msg, queue, _redis) requirement { defined?(::Sidekiq) } execution do - ::Sidekiq.configure_server do |sidekiq| - sidekiq.server_middleware do |chain| - chain.prepend Middleware + if Honeybadger.config[:'exceptions.enabled'] + ::Sidekiq.configure_server do |sidekiq| + sidekiq.server_middleware do |chain| + chain.prepend Middleware + end end - end - if defined?(::Sidekiq::VERSION) && ::Sidekiq::VERSION > '3' - ::Sidekiq.configure_server do |sidekiq| + if defined?(::Sidekiq::VERSION) && ::Sidekiq::VERSION > '3' + ::Sidekiq.configure_server do |sidekiq| - sidekiq_default_configuration = (::Sidekiq::VERSION > '7') ? - ::Sidekiq.default_configuration : Class.new + sidekiq_default_configuration = (::Sidekiq::VERSION > '7') ? + ::Sidekiq.default_configuration : Class.new - sidekiq.error_handlers << lambda { |ex, sidekiq_params, sidekiq_config = sidekiq_default_configuration| - params = sidekiq_params.dup - if defined?(::Sidekiq::Config) - if params[:_config].is_a?(::Sidekiq::Config) # Sidekiq > 6 and < 7.1.5 - params[:_config] = params[:_config].instance_variable_get(:@options) - else # Sidekiq >= 7.1.5 - params[:_config] = sidekiq_config.instance_variable_get(:@options) + sidekiq.error_handlers << lambda { |ex, sidekiq_params, sidekiq_config = sidekiq_default_configuration| + params = sidekiq_params.dup + if defined?(::Sidekiq::Config) + if params[:_config].is_a?(::Sidekiq::Config) # Sidekiq > 6 and < 7.1.5 + params[:_config] = params[:_config].instance_variable_get(:@options) + else # Sidekiq >= 7.1.5 + params[:_config] = sidekiq_config.instance_variable_get(:@options) + end end - end - job = params[:job] || params + job = params[:job] || params - job_retry = job['retry'.freeze] + job_retry = job['retry'.freeze] - if (threshold = config[:'sidekiq.attempt_threshold'].to_i) > 0 && job_retry - # We calculate the job attempts to determine the need to - # skip. Sidekiq's first job execution will have nil for the - # 'retry_count' job key. The first retry will have 0 set for - # the 'retry_count' key, incrementing on each execution - # afterwards. - retry_count = job['retry_count'.freeze] - attempt = retry_count ? retry_count + 1 : 0 + if (threshold = config[:'sidekiq.attempt_threshold'].to_i) > 0 && job_retry + # We calculate the job attempts to determine the need to + # skip. Sidekiq's first job execution will have nil for the + # 'retry_count' job key. The first retry will have 0 set for + # the 'retry_count' key, incrementing on each execution + # afterwards. + retry_count = job['retry_count'.freeze] + attempt = retry_count ? retry_count + 1 : 0 - max_retries = (::Sidekiq::VERSION > '7') ? - ::Sidekiq.default_configuration[:max_retries] : sidekiq.options[:max_retries] - # Ensure we account for modified max_retries setting - default_max_retry_attempts = defined?(::Sidekiq::JobRetry::DEFAULT_MAX_RETRY_ATTEMPTS) ? ::Sidekiq::JobRetry::DEFAULT_MAX_RETRY_ATTEMPTS : 25 - retry_limit = job_retry == true ? (max_retries || default_max_retry_attempts) : job_retry.to_i + max_retries = (::Sidekiq::VERSION > '7') ? + ::Sidekiq.default_configuration[:max_retries] : sidekiq.options[:max_retries] + # Ensure we account for modified max_retries setting + default_max_retry_attempts = defined?(::Sidekiq::JobRetry::DEFAULT_MAX_RETRY_ATTEMPTS) ? ::Sidekiq::JobRetry::DEFAULT_MAX_RETRY_ATTEMPTS : 25 + retry_limit = job_retry == true ? (max_retries || default_max_retry_attempts) : job_retry.to_i - limit = [retry_limit, threshold].min + limit = [retry_limit, threshold].min - return if attempt < limit - end + return if attempt < limit + end - opts = { parameters: params } - if config[:'sidekiq.use_component'] - opts[:component] = job['wrapped'.freeze] || job['class'.freeze] - opts[:action] = 'perform' if opts[:component] - end + opts = { parameters: params } + if config[:'sidekiq.use_component'] + opts[:component] = job['wrapped'.freeze] || job['class'.freeze] + opts[:action] = 'perform' if opts[:component] + end - Honeybadger.notify(ex, opts) - } + Honeybadger.notify(ex, opts) + } + end end end diff --git a/lib/honeybadger/plugins/sucker_punch.rb b/lib/honeybadger/plugins/sucker_punch.rb index c919a383e..d67f8fca6 100644 --- a/lib/honeybadger/plugins/sucker_punch.rb +++ b/lib/honeybadger/plugins/sucker_punch.rb @@ -6,6 +6,7 @@ module Honeybadger requirement { defined?(::SuckerPunch) } execution do + return unless Honeybadger.config[:'exceptions.enabled'] if SuckerPunch.respond_to?(:exception_handler=) # >= v2 SuckerPunch.exception_handler = ->(ex, klass, args) { Honeybadger.notify(ex, { :component => klass, :parameters => args }) } else diff --git a/lib/honeybadger/plugins/thor.rb b/lib/honeybadger/plugins/thor.rb index 726e64a45..b8247e370 100644 --- a/lib/honeybadger/plugins/thor.rb +++ b/lib/honeybadger/plugins/thor.rb @@ -25,6 +25,7 @@ def invoke_command_with_honeybadger(*args) requirement { defined?(::Thor.no_commands) } execution do + return unless Honeybadger.config[:'exceptions.enabled'] ::Thor.send(:include, Thor) end end