As described here, I'm trying to modify the standard rails logger such that it will provide the log level, timestamp and filename + line number of the log statement.
This is what my logger class looks like in config/initializers/logger.rb
:
class ActiveSupport::Logger::SimpleFormatter
def call(severity, time, progname, msg)
"[#{severity} #{time} #{caller(0).first.match(/.*:\d+/)[0]}] #{msg}\n"
end
end
However, this log line ALWAYS produces a log message containing "logger.rb:3
"
Clearly that's wrong. It is printing the filename and line number of the line within the logger.rb file. I need to get the call stack and go up one stack frame and get it from there. How can I do it? Is it even possible?
This solution using caller works in a very simple stand-alone ruby program. But when I run my whole Rails app, caller returns something very different and alien than it does when running it in a standalone ruby file.
Rails does something very funky with The caller variable. It purports to contain the call stack. But it doesn't. It contains references to a lot of other code (presumably rails infrastructure), but no other file from my application -- notably not the file from which this log line is called. See here (snipped version shown below).
/Users/myUser/my_rails_app/config/initializers/logger.rb:16:in `call'
/Users/myUser/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/activesupport-4.0.8/lib/active_support/tagged_logging.rb:21:in `call'
/Users/myUser/.rbenv/versions/1.9.3-p484/lib/ruby/1.9.1/logger.rb:491:in `format_message'
<SNIPPED!>
/Users/myUser/.rbenv/versions/1.9.3-p484/lib/ruby/1.9.1/webrick/httpserver.rb:94:in `run'
/Users/myUser/.rbenv/versions/1.9.3-p484/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'
When I write a simple ruby (without Rails) program to test caller, it works completely as it should:
def foo
puts caller[0]
end
def bar
foo
end
bar
yields:
/Users/myUser/rubyTest.rb:9:in `bar'
Why does this work in standalone Ruby, but fail in rails?