当 ActionMailer 遇到错误时,如何让 Delayed_Job 通知 Airbrake?

Posted

技术标签:

【中文标题】当 ActionMailer 遇到错误时,如何让 Delayed_Job 通知 Airbrake?【英文标题】:How to make Delayed_Job notify Airbrake when an ActionMailer runs into an error? 【发布时间】:2012-09-22 21:32:44 【问题描述】:

DelayedJob 文档提到了钩子,包括错误钩子,但仅限于自定义 Job 子类的上下文中。

This similar question(没有答案)说向邮件程序类添加相同的钩子不起作用。

有什么诀窍?

更新:

一般来说,我想看看如何为使用 object.delay.action() 语法触发的作业添加挂钩,但我看不到 ____Job 类的明显链接。

【问题讨论】:

这里更新和更简单的答案:***.com/questions/11766368/… 【参考方案1】:

我也在寻找这个问题的解决方案,我找到了this gist。

我不知道它来自哪里(在 Google 上找到),但是它似乎做得很好,很简单,并且似乎遵循了一个我什至不知道的 DelayedJob 的插件系统。 ..

这是一个使用部分以前的猴子补丁代码的轻微改进:

# https://gist.github.com/2223758
# modified

module Delayed
  module Plugins
    class Airbrake < Plugin
      module Notify
        def error(job, error)
          ::Airbrake.notify_or_ignore(
            :error_class   => error.class.name,
            :error_message => "#error.class.name: #error.message",
            :parameters    => 
              :failed_job => job.inspect,
            
          )
          super if defined?(super)
        end
      end

      callbacks do |lifecycle|
        lifecycle.before(:invoke_job) do |job|
          payload = job.payload_object
          payload = payload.object if payload.is_a? Delayed::PerformableMethod
          payload.extend Notify
        end
      end
    end
  end
end

Delayed::Worker.plugins << Delayed::Plugins::Airbrake

它将添加错误消息和有效负载,以便在 Airbrake 中可用。

【讨论】:

我也不知道这个插件系统。我会看看。如果这在我的系统中有效,我会尽快将接受的答案切换为您的。 我真的很喜欢这种方法。我找不到作为 gem 发布的版本,因此感谢分享,我将其打包为 gem 以供其他人轻松使用。如果您想写访问权限等,请告诉我! github.com/benjaminoakes/delayed-plugins-airbrake 这是最佳答案,因为它适用于所有作业,它不是猴子补丁,而且您不必记得添加当您添加 delay 的新用法时挂钩。另外,我会使用 @benjamin-oakes gem,但我使用的是 party_foul 而不是 airbrake。【参考方案2】:

有一个 DJ-honeybadger 宝石。 gem 当然是积极维护的,这比使用猴子补丁要好得多。诚然,当猴子补丁出现时,没有宝石可以做到这一点。

https://github.com/honeybadger-io/delayed_job_honeybadger

【讨论】:

谢谢,这个问题是针对 Airbrake 的,但这是一个类似的很好的答案。 (现在还有一个 Airbrake gem)。 github.com/benjaminoakes/delayed-plugins-airbrake 你是对的@JordanFeldstein,问题是针对 Airbrake。有趣的是,我对 Honeybadger 使用了相同的 hack,并且效果很好。我猜 Airbrake 和 Honeybadger 的 API 可以响应相同的调用(非常好) 这个插件现在已经被最新版本的 Honeybadger 弃用了。【参考方案3】:

当作业失败时,让delayed_job 向Airbrake 发送警报的最简单方法可能是猴子补丁delayed_job。这允许您连接到delayed_job 的内部,并稍微修改它以在出现问题时向Airbrake 发出警报。

不幸的是,具体如何执行取决于您使用的延迟作业版本以及您使用的 Airbrake 版本;它还可能还取决于您希望在 delay_job 处理中挂接到系统的确切位置。

但是,我见过的最简单的例子可能是对 handle_failed_job 方法进行猴子修补,如 here 所示。请注意,尽管此示例使用旧的 Hoptoad 系统进行警报,因此如果您使用的是现代 Airbrake gem,则需要将执行实际通知的代码更改为 here 所述。

【讨论】:

谢谢你提醒我。我最终遇到了相同的猴子补丁解决方案。上面截取的代码。【参考方案4】:

最好的方法是使用全局挂钩。 2011 年有人 proposed 这个,但看起来他们还没有实现。

同时,这可以用来修补东西:

# Patch delayed job to report runtime errors to Airbrake
module Delayed
  class Worker

    protected

    def handle_failed_job_with_airbrake(job, error)
      ::Airbrake.notify(
        :error_class   => error.class.name,
        :error_message => "#error.class.name: #error.message",
        :parameters    => 
          :failed_job => job.inspect,
        
      )

      handle_failed_job_without_airbrake(job, error)
    end

    alias_method_chain :handle_failed_job, :airbrake

  end
end

【讨论】:

由于 Airbrake 显示参数的方式,我建议不要发送job.inspect,而是传递一个哈希值。首先解析失败作业的内容:failed_job = YAML.load(job.handler)。然后将其实例参数解析为哈希,您可以将其传递给:parameters 进行airbrake:failed_job.instance_variables.inject() |hsh,v| hsh[v.to_s.gsub(/[^\w]/, '')] = failed_job.instance_variable_get(v); hsh 您可能还想在:parameters 中包含作业的类名::class =&gt; failed_job.class.name

以上是关于当 ActionMailer 遇到错误时,如何让 Delayed_Job 通知 Airbrake?的主要内容,如果未能解决你的问题,请参考以下文章

Rails 4 ActionMailer - 如何在使用 Deliver_later 时捕获连接和 SMTP 错误

如何在开发中禁用 ActionMailer?

使用Devise配置ActionMailer以允许来自不同用户的电子邮件。

ArgumentError:已请求 SMTP-AUTH 但缺少用户名 + ActionMailer

使用 ActionMailer 的电子邮件注册确认

SQL 你如何让 udf 在错误时返回 null?