Sidekiq Bugsnag Middleware - ruby-on-rails

Is there a way to integrate Bugsnag to rescue all exceptions for Sidekiq and send notifications? I can't find it in the docs.
def call(_worker, _msg, _queue)
Bugsnag.before_notify_callbacks << lambda do |notif|
notif.add_tab(
:gem_version,
metascrape: Metascrape::VERSION
)
end
yield
rescue ActiveRecord::RecordNotFound => e
Bugsnag.notify e
ensure
Bugsnag.before_notify_callbacks.clear
end
end

Why do you think you need to do anything? The docs indicate it should just work.
Bugsnag ruby works out of the box with Rails, Sidekiq, Resque, DelayedJob (3+), Mailman, Rake and Rack. It should be easy to add support for other frameworks, either by sending a pull request here or adding a hook to those projects.
https://bugsnag.com/docs/notifiers/ruby

Related

Rails ActiveJob - What's the good way to handle exception in ActionMailer::DeliveryJob

I am using ActiveJob + Sidekiq in my Rails project for task processing.
I send my mails directly using MyMailer.some.deliver_later. It will automatically creates a ActionMailer::DeliveryJob task and put it in the Sidekiq queue.
The question is, what's the good to handle exceptions from there?
Best Regards.
According to http://edgeguides.rubyonrails.org/active_job_basics.html, I think the good way is to setup exception error handlers for ActionMailer::DeliveryJob in an initializer, somethinglike:
ActionMailer::DeliveryJob.rescue_from(Net::SMTPSyntaxError) do |exception|
unless ['501 Command parsing failed'].include?(exception.message.strip)
raise exception
end
end

Rails Exception Notification without middleware

I have an Rails 4 application that is entirely comprised of rails runners over cron generated from the whenever gem.
I'd like to be notified if there are any exceptions that occur during the run. The exception_notification gem only runs as rack middleware (web requests only), so it doesn't handle rails runners.
Any ideas? I'm looking to get notified over email or on slack.
You can use ExceptionNotifier.notify_exception in a rescue block to send a notification.
For example:
def rescue_exception(data)
yield
rescue => e
ExceptionNotifier.notify_exception(e, data: data)
end
every :hour do
rescue_exception(runner: 'SomeModel.some_method') do
runner "SomeModel.some_method"
end
end
Please refer to https://github.com/smartinez87/exception_notification#background-notifications. Use data hash to pass additional information about the context.

Ruby - Asynchronous Mailing

I'm quite new to Ruby on Rails and want to send an e-mail asynchronously to make my app respond faster. The synchronous sending works fine and would be my alternative.
I've found some sites and defined the gems 'resque_mailer', 'redis' and 'resque' in my Gemfile and installed them via the bundle install command. My mailer looks like:
class Contact < ActionMailer::Base
include Resque::Mailer
default from: "<private>"
def contact(email, bandName, respondMail, message)
#message = message
#respondMail = respondMail
#bandName = bandName
mail(:to => email,
:subject => "subject")
end
end
The Controller-Call to send the mail looks like:
Contact.contact(band.email, band.name, params[:respondMail].to_s, params[:message].to_s).deliver
If I try to send my mail now asynchronously I'm getting the following error which is caused by the "contact" call:
Timed out connecting to Redis on 127.0.0.1:6379
Unfortunately I've got no idea how to solve this. Can someone please tell me which steps I must make to send a mail asynchronously? If possible there should be no extra database columns.
In order for resque and resque_mailer to work you need to install redis. You can find more about redis here: http://redis.io/download
If you are new to rails, all the external tools and dependencies can be quite overwhelming. If you don't have an application with extreme load you should consider using a simpler job queue like https://github.com/collectiveidea/delayed_job. It does not depend on further external services and uses your current database to store the jobs. The only thing you need to do is to keep the workers up.

why OmniAuth::Strategies::Facebook::NoAuthorizationCodeError is not handled in omniauth on_failure callback?

I am using Omniauth for Rails 3.2.3 application.
I have configured the on_failure callback as show below.
OmniAuth.config.on_failure = Proc.new do |env|
UsersController.action(:omniauth_failure).call(env)
end
This handles the error "OmniAuth::Strategies::CallbackError" but not "OmniAuth::Strategies::Facebook::NoAuthorizationCodeError".
How to handle this error?.Surly I can not use rescue_from as the error happens in Rack level.
Any ideas?
Thank you
Ensure that your Facebook Application is not running in "Sandbox Mode"
I've run into the same issue.
By my humble investigation it seems to be a bug in the strategy implemented in the omniauth-facebook gem (and, at a quick glance in several others). This is a nice write-up on exception handling in omniauth. It says that
... OmniAuth strategies [...], if they encounter a problem, call the method fail! and pass in a symbol describing the problem like :invalid_credentials and the exception they encountered. The fail! method ends up calling OmniAuth.config.on_failure and passing in the Rack environment (after doing a few other things like sticking the exception into the environment...
The same can be inferred from an example the original authors kindly provided. In the source it's not emphasized and I haven't found it in the wiki docs, either (but I may have overlooked).
Many strategies, including omniauth-facebook, currently raises the exception which we cannot catch at app level anymore.
#soundar: I wish that it worked this way, as advertised.
#fastcatch: As you pointed out, the strategies are not handling these failure cases correctly.
#Jon Day: I had to patch the Rack App for 'omniauth-facebook' (1.4.0) in order to get the reporting that I needed:
require 'newrelic_rpm'
module OmniAuth
class Builder < ::Rack::Builder
def call_with_error_handling(env)
begin
call_without_error_handling(env)
rescue OmniAuth::Strategies::Facebook::NoAuthorizationCodeError => error
# Do whatever you'd like when rescuing.. I wanted to report to NewRelic.
NewRelic::Agent.notice_error(error, env)
env
end
end
alias_method_chain :call, :error_handling
end
end
I'm not proud of this code, but it is one way to gain control over that exception ;).

How do i integrate Hoptoad with DelayedJob and DaemonSpawn?

I have been happily using the DelayedJob idiom:
foo.send_later(:bar)
This calls the method bar on the object foo in the DelayedJob process.
And I've been using DaemonSpawn to kick off the DelayedJob process on my server.
But... if foo throws an exception Hoptoad doesn't catch it.
Is this a bug in any of these packages... or do I need to change some configuration... or do I need to insert some exception handling in DS or DJ that will call the Hoptoad notifier?
In response to the first comment below.
class DelayedJobWorker < DaemonSpawn::Base
def start(args)
ENV['RAILS_ENV'] ||= args.first || 'development'
Dir.chdir RAILS_ROOT
require File.join('config', 'environment')
Delayed::Worker.new.start
end
Try monkeypatching Delayed::Worker#handle_failed_job :
# lib/delayed_job_airbrake.rb
module Delayed
class Worker
protected
def handle_failed_job_with_airbrake(job, error)
say "Delayed job failed -- logging to Airbrake"
HoptoadNotifier.notify(error)
handle_failed_job_without_airbrake(job, error)
end
alias_method_chain :handle_failed_job, :airbrake
end
end
This worked for me.
(in a Rails 3.0.10 app using delayed_job 2.1.4 and hoptoad_notifier 2.4.11)
Check out the source for Delayed::Job... there's a snippet like:
# This is a good hook if you need to report job processing errors in additional or different ways
def log_exception(error)
logger.error "* [JOB] #{name} failed with #{error.class.name}: #{error.message} - #{attempts} failed attempts"
logger.error(error)
end
I haven't tried it, but I think you could do something like:
class Delayed::Job
def log_exception_with_hoptoad(error)
log_exception_without_hoptoad(error)
HoptoadNotifier.notify(error)
end
alias_method_chain :log_exception, :hoptoad
end
Hoptoad uses the Rails rescue_action_in_public hook method to intercept exceptions and log them. This method is only executed when the request is dispatched by a Rails controller.
For this reason, Hoptoad is completely unaware of any exception generated, for example, by rake tasks or the rails script/runner.
If you want to have Hoptoad tracking your exception, you should manually integrate it.
It should be quite straightforward. The following code fragment demonstrates how Hoptoad is invoked
def rescue_action_in_public_with_hoptoad exception
notify_hoptoad(exception) unless ignore?(exception) || ignore_user_agent?
rescue_action_in_public_without_hoptoad(exception)
end
Just include Hoptoad library in your environment and call notify_hoptoad(exception) should work. Make sure your environment provides the same API of a Rails controller or Hoptoad might complain.
Just throwing it out there - your daemon should require the rails environment that you're working on. It should look something along the lines of:
RAILS_ENV = ARGV.first || ENV['RAILS_ENV'] || 'production'
require File.join('config', 'environment')
This way you can specify environment in which daemon is called.
Since it runs delayed job chances are daemon already does that (it needs activerecord), but maybe you're only requiring minimal activerecord to make delayed_job happy without rails.

Resources