26

我希望 ExceptionNotifier 在延迟作业中发生异常时发送电子邮件,就像其他异常一样。我怎样才能做到这一点?

4

6 回答 6

23

我使用 Rails 3.2.6、delayed_job 3.0.3 和exception_notification 2.6.1 gem执行此操作

# In config/environments/production.rb or config/initializers/delayed_job.rb

# Optional but recommended for less future surprises.
# Fail at startup if method does not exist instead of later in a background job 
[[ExceptionNotifier::Notifier, :background_exception_notification]].each do |object, method_name|
  raise NoMethodError, "undefined method `#{method_name}' for #{object.inspect}" unless object.respond_to?(method_name, true)
end

# Chain delayed job's handle_failed_job method to do exception notification
Delayed::Worker.class_eval do 
  def handle_failed_job_with_notification(job, error)
    handle_failed_job_without_notification(job, error)
    # only actually send mail in production
    if Rails.env.production?
      # rescue if ExceptionNotifier fails for some reason
      begin
        ExceptionNotifier::Notifier.background_exception_notification(error)
      rescue Exception => e
        Rails.logger.error "ExceptionNotifier failed: #{e.class.name}: #{e.message}"
        e.backtrace.each do |f|
          Rails.logger.error "  #{f}"
        end
        Rails.logger.flush
      end
    end
  end 
  alias_method_chain :handle_failed_job, :notification 
end

在所有环境中加载此代码以在包更新等之后在它们进入生产之前捕获错误可能是一个好主意。我通过拥有一个config/initializers/delayed_job.rb文件来做到这一点,但您可以为每个config/environments/*环境复制代码。

另一个技巧是调整延迟的作业配置,默认情况下你可能会在作业失败时收到很多重复的异常邮件。

# In config/initializers/delayed_job_config.rb
Delayed::Worker.max_attempts = 3

更新delayed_job我在守护进程静默退出时遇到了一些问题,结果是ExceptionNotifier无法发送邮件并且没有人挽救异常。现在代码拯救并记录它们。

于 2011-08-06T15:43:17.520 回答
6

添加到@MattiasWadman 答案,因为 exception_notification 4.0有一种处理手动 notify 的新方法。所以而不是:

ExceptionNotifier::Notifier.background_exception_notification(error)

采用

ExceptionNotifier.notify_exception(error)
于 2013-12-09T18:55:44.003 回答
4

处理异常的另一种方法(作为初始化程序):

class DelayedErrorHandler < Delayed::Plugin

  callbacks do |lifecycle|

    lifecycle.around(:invoke_job) do |job, *args, &block|

      begin
        block.call(job, *args)
      rescue Exception => e

        # ...Process exception here...

        raise e
      end
    end
  end
end

Delayed::Worker.plugins << DelayedErrorHandler
于 2015-08-25T18:46:28.170 回答
3

alias_method_chainRails 5 中不再存在。

这是使用 Ruby 2 执行此操作的新(正确)方法prepend

# In config/initializers/delayed_job.rb
module CustomFailedJob
  def handle_failed_job(job, error)
    super
    ExceptionNotifier.notify_exception(error, data: {job: job})
  end
end

class Delayed::Worker
  prepend CustomFailedJob
end
于 2018-05-15T16:01:01.437 回答
2

对于 exception_notification 3.0.0 更改:

ExceptionNotifier::Notifier.background_exception_notification(error)

到:

ExceptionNotifier::Notifier.background_exception_notification(error).deliver
于 2013-01-08T18:07:32.713 回答
0

更简单和更新的答案:

# Chain delayed job's handle_failed_job method to do exception notification
Delayed::Worker.class_eval do
  def handle_failed_job_with_notification job, error
    handle_failed_job_without_notification job, error
    ExceptionNotifier.notify_exception error,
      data: {job: job, handler: job.handler} rescue nil
  end 
  alias_method_chain :handle_failed_job, :notification
end

并在控制台上测试:

Delayed::Job.enqueue (JS=Struct.new(:a){ def perform; raise 'here'; end }).new(1)
于 2013-08-13T13:35:54.027 回答