Log filename, line and function name in ruby automatically
Suppose you have a app with a logger:
require 'logger'
module MyApp
Log = Logger.new(STDOUT)
class Foo
def self.hello
Log.info "test message"
end
end
end
MyApp::Foo.hello
When you run it, everything is as usual:
I, [2013-05-11T21:26:40.701590 #4326] INFO -- : test message
Now imagine you have a ton of such messages flooding the output. Wouldn’t be nice if the logger would also include the filename, the line and the function name where the Log output was issued? Well, you can do that in ruby:
require 'logger'
module MyApp
Log = Logger.new(STDOUT)
Log.formatter = proc { |severity, datetime, progname, msg|
"#{severity} #{caller[4]} #{msg}\n"
}
class Foo
def self.hello
Log.info "test message"
end
end
end
MyApp::Foo.hello
If we will run this, we’ll see the following output:
INFO log_test.rb:14:in `hello': test message
How it is done
Ruby has a magic array - caller. It contains the ordered list of the files, lines,
and functions being executed.
class Foo
def self.baz
hello
end
def self.hello
p caller
end
end
Foo.baz #=> ["/home/andrei/Temp/log_test.rb:21:in `baz'", "/home/andrei/Temp/log_test.rb:29:in `<main>'"]
We used that magic array for our logger formatter, and we used its 4th element because the code which calls the logger is 4 levels above in call stack relative to formatter proc.
Note: If you use a different version of logger, you might need to use a different number, not 4. In any case, inspect the caller array and see at which position in that array your code info is located.