141

I have been trying to figure out the right way to log a stack trace. I came across this link which states that logger.error $!, $!.backtrace is the way to go but that does not work for me log_error does. As per documentation I do not see how passing a second argument to the error method would work anyway because the ruby logger that rails uses only accepts a single argument.

Strangely (or maybe not) the second argument is accepted without any interpreter complaints. However anything that I pass to it is ignored.

Can anyone explain what I am missing? Any insight into what the second argument to error is for and what is eating it?

Community
  • 1
  • 1
Moiz Raja
  • 5,612
  • 6
  • 40
  • 52

3 Answers3

245

If you look at the source for the BufferedLogger class in ActiveSupport, you'll see that the second argument is 'progname'. This is used only when the first argument is nil and you have either given it no block or the block return a non-true value.

In essence, you can't use the second parameter to output additional stuff.

What you want to do is something more akin to:

begin
  raise
rescue => e
  logger.error e.message
  logger.error e.backtrace.join("\n")
end

Depending on how you have your logging setup, it might be better to iterate through each line of the backtrace and print it separately as certain loggers don't output newlines, in which case you'd do something like:

begin
  raise
rescue => e
  logger.error e.message
  e.backtrace.each { |line| logger.error line }
end
darkliquid
  • 4,003
  • 1
  • 25
  • 17
  • 5
    I would join using "\r\n" to maintain cross-platform compatibility. – James Watkins Feb 14 '14 at 15:04
  • 10
    Wouldn't you use `$/` instead, to be cross-platform compatible? Let Ruby take care of it, as `\r\n` is only specific to a few platforms. – vgoff Jan 06 '15 at 23:03
  • 15
    You may get your message split and unreadable because calling logger multiple times is not thread safe. While the logger itself is thread safe. Usually I join my message in one string then log it. – Morozov Dec 15 '15 at 10:31
  • At the time logger didn't seem to support newlines in log entries, hence the splitting but yes, you are quite right and you should be aware of the limitations of this approach – darkliquid Dec 15 '15 at 11:04
  • +1 @JackWatson absolutely strange answer because it's non-thread safe. It's important thing because we are talking about web apps here – EvAlex Feb 08 '16 at 08:24
27

This is the answer.

begin
  raise
rescue => e
  logger.error ([e.message]+e.backtrace).join($/)
end
kuboon
  • 9,557
  • 3
  • 42
  • 32
5

Based on kuboon's answer I find this logging format to be generic and useful to categorise errors in my logfiles:

begin
  raise
rescue StandardError => e
  Rails.logger.error (["#{self.class} - #{e.class}: #{e.message}"]+e.backtrace).join("\n")
end
AlejandroVD
  • 1,576
  • 19
  • 22