2011-05-12 17 views
25

我想讓ExceptionNotifier在延遲作業中發生異常時發送電子郵件,就像其他異常一樣。我怎樣才能做到這一點?如何使ExceptionNotifier在Rails 3中使用delayed_job?

+0

有趣的問題,在尋找我碰到的http://計算器.com/questions/4104093/exception-notification-for-delayed-job和http://groups.google.com/group/delayed_job/browse_thread/thread/646314145a69360b?fwc=1&pli=1 – William 2011-05-12 03:24:28

+0

是的,我見過兩個那些,但我認爲這些解決方案只適用於Rails 2. – 2011-05-12 03:40:16

回答

23

我這樣做是使用Rails 3.2.6,3.0.3的delayed_job和exception_notification 2.6.1寶石

# 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無法發送郵件,沒有人獲救例外。現在代碼解救並記錄它們。

+1

我建議使用https://github.com/smartinez87/exception_notification上的官方異常通知gem – 2011-12-27 03:13:15

+0

好吧,會更新到那個。那時我正在使用rails3 gem,因爲那時正式版本會引發一些rails 3問題。 – 2011-12-27 14:47:04

+0

+1此方法適用於Rails 3.2.6,延遲作業3.0.3和異常通知2.6.1。起初,我認爲使用內置鉤子添加一個錯誤方法將是一種更簡潔的方法,但是必須爲每個工作類定義它,並且通常爲「PerformableMethod」定義它並不工作,這是由於委託是如何工作的用過的。 – Nathan 2012-07-07 20:04:14

2

對於exception_notification 3.0.0變化:

ExceptionNotifier::Notifier.background_exception_notification(error) 

到:

ExceptionNotifier::Notifier.background_exception_notification(error).deliver 
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) 
+0

是一個相當過時的答案('09)。其實'log_exception_without_notification'甚至不存在於最後的版本 – 2013-12-09 18:51:17

+1

@AlterLagos我認爲你誤解了alias_method_chain。 – kuboon 2014-10-10 06:29:29

+0

更新和簡化 – brauliobo 2015-05-21 00:03:10

4

添加到@MattiasWadman答案,因爲exception_notification 4.0 there's a new way to handle manual notify。因此,而不是:

ExceptionNotifier::Notifier.background_exception_notification(error) 

使用

ExceptionNotifier.notify_exception(error) 
+0

這也將在後臺處理? – 2013-12-24 09:12:49

+1

@DaniëlZwijnenburg該方法被delayed_job調用,所以是 – 2013-12-24 18:44:01

3

另一種方式來處理異常(如放一個初始化):

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 
+0

我認爲這是最乾淨的解決方案。 BTW的其他解決方案將來不會工作,因爲alias_method_chain在Rails 5中已被棄用 – remo 2017-02-02 14:37:12

相關問題