当 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 => failed_job.class.name
以上是关于当 ActionMailer 遇到错误时,如何让 Delayed_Job 通知 Airbrake?的主要内容,如果未能解决你的问题,请参考以下文章
Rails 4 ActionMailer - 如何在使用 Deliver_later 时捕获连接和 SMTP 错误
使用Devise配置ActionMailer以允许来自不同用户的电子邮件。