Forum: Ruby on Rails Hook into Exception Chain

9a1b1136b42f179b246b9d3eb66fc996?d=identicon&s=25 Christoph B. (christoph_b)
on 2013-11-12 15:41
(Received via mailing list)
Hi there,

I'm using Log4r in my rails projects. On log.error an email is sent
using
the EmailOutputter.
I know changed the EmailOutputter to include a global var in the subject
(MDC) since the subject is normally static.

I want to set this var to the exception message, so it is sent as the
subject.

Can anyone tell me how to do this in rails?

Basically:

raise e or some other cause
> -> Log4r::MDC.put('subject', e.message)
> continue with the exception


I found *rescue_from* but it just gives it to the handler and then
stops.

Thanks a lot,
Christoph
0d56133042e4814c1b2255ea655f2361?d=identicon&s=25 Jeff Burlysystems (jburly)
on 2013-11-12 19:08
(Received via mailing list)
Hi Christoph,

All you need to do is re-raise the exception after you're done using it
in
your rescue_from, so something along the lines of:

$ cat ./app/controllers/foo_controller.rb
...
  rescue_from Exception do |e|
    # do something with e before re-raising it ...
    Rails.logger.debug("TEST: before re-raising ... e=#{e.inspect}")
    raise e
  end
...

  def testfoo
    x = 'bar' if 1/0
    ....
  end
....

$ curl -sLi http://foo.localhost/testfoo
...

$ cat ./log/development.log
...
[c55f5] TEST: before re-raising ... e=#<ZeroDivisionError: divided by 0>
[c55f5] Completed 500 Internal Server Error in 17ms
[c55f5]
ZeroDivisionError (divided by 0):
  app/controllers/foo_controller.rb:89:in `/'
  app/controllers/foo_controller.rb:89:in `testfoo'
...

Jeff
9a1b1136b42f179b246b9d3eb66fc996?d=identicon&s=25 Christoph B. (christoph_b)
on 2013-11-12 20:28
(Received via mailing list)
Hi Jeff, thanks for your reply!

I found the article here:
http://www.simonecarletti.com/blog/2009/11/re-rais...

And he mentions that re-raising does not work since rails won't catch it
anymore..
has this been changed since?

I generally thought there might be a better way, as usually re-raising
exceptions is considered to be bad :)

Thanks a lot,
Christoph
0d56133042e4814c1b2255ea655f2361?d=identicon&s=25 Jeff Burlysystems (jburly)
on 2013-11-12 21:26
(Received via mailing list)
Hi Christoph,

My (simple) example was just trying to give you an idea of how to do
what
you were asking using rescue_from.

And note that the log does show that the re-raising worked as expected,
where we did something with the caught exception first (ie write a debug
TEST line to the log) before then re-raising it and letting the rails
env
stack handle it (ie log shows the stacktrace including the orig line
where
the bug is in the code, ...).

As for "a better way", it always depends on what you're ultimately
trying
to accomplish and the tradeoffs for getting there.

But if you really did want to use rescue_from for any/all
exceptions/errors
that could occur, then at a minimum you're going to want to make sure
that
what you do with that caught exception (ie your Log4r::MDC... call)
doesn't
itself result in any exceptions/errors.  One way would be to wrap that
work
in a begin ... rescue Exception => e2 ... end ... before then re-raising
the originally caught exception.

Jeff
9a1b1136b42f179b246b9d3eb66fc996?d=identicon&s=25 Christoph B. (christoph_b)
on 2013-11-12 21:33
(Received via mailing list)
Thanks a lot Jeff,

Yeah I saw it works, that's why I wondered about the linked post..

Anyway, I'm just trying to basically get emails that contain the
exception/error message in the subject so it's easier to sort
if there are many error mails.

Of course the rescue_from method only targets one specific case - the
one
where I get a rails exception.
But I think I cannot do it by monkey patching log4r as rails already
sends
a complete (and formatted) string to
log.error making it hard to extract the relevant message.

I'll see how I can use it, but I think I can get there somehow :)

Thank a lot for your suggestion!
Christoph
9a1b1136b42f179b246b9d3eb66fc996?d=identicon&s=25 Christoph B. (christoph_b)
on 2013-11-15 11:27
(Received via mailing list)
I've used the above approach now

However, this only works for controller actions.
I've got some cronjobs in the project (lib folder) as well as a sinatra
app
that is mounted within the rails app.

Is there any way I could catch the exceptions in these parts as well?

Thanks,
Christoph
81b61875e41eaa58887543635d556fca?d=identicon&s=25 Frederick Cheung (Guest)
on 2013-11-16 22:38
(Received via mailing list)
On Friday, November 15, 2013 10:26:10 AM UTC, sol wrote:
>
> I've used the above approach now
>
> However, this only works for controller actions.
> I've got some cronjobs in the project (lib folder) as well as a sinatra
> app that is mounted within the rails app.
>
> Is there any way I could catch the exceptions in these parts as well?
>
> For a cronjob type thing it's up to you to wrap your script with something
that will log the error. My cronjobs normally end up looking like

TaskWrapper('some job') do
  #work here
end

and elsewhere

def TaskWrapper
  begin
    yield
  rescue Exception => ex
    #do something with the exception
    raise
  end
end

I use rescue Exception because for once I think it's appropriate that
things like SyntaxError are caught so that I can be notified about them

For the sinatra (or even the rails case) you could write a rack
middleware
that would look something like

class ErrorNotifier
  def initialize(app)
    @app = app
  end

  def call(env)
    begin
      @app.call(env)
    rescue Exception => ex
      #do something with the exception
      raise
   end
  end
end


You could also render an error message if you want to override that.

You might also be interested in the exception handling stuff described
at
http://blog.plataformatec.com.br/2012/01/my-five-f...

Fred
9a1b1136b42f179b246b9d3eb66fc996?d=identicon&s=25 Christoph B. (christoph_b)
on 2013-11-18 11:44
(Received via mailing list)
Thanks a lot! That's useful
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.