Log filename, line and function name in ruby automatically published on 11 May 2013, 2 minute read
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.
Read more posts
- On logic in a Rails app, revisited 6 years later 18 May 2019
- Fitting the "339 bytes of responsive CSS" in a tweet, with a twist 17 May 2019
- Enforcing that a ruby method is called from a specific location 28 Jun 2017
- Unity performance tweaks 20 Mar 2013
← back to homepage