Log4r is a logging library inspired by Apache Foundation’s Log4j, “but is not a direct implementation or clone.” Of course this doesn’t change the fact that log4r is a very efficient, fast, and easy to use library. I’m going give a quick tutorial how to add logging capabilities to your Ruby scripts using Log4r. First, let’s get everything we need installed and then I’ll show how I added logging capabilities to fibonacci Ruby script I’ve written in a previous post.
We have two basic ways of installing the log4r library. We can either install directly by grabbing the source or we can install using ruby-gems.
To install using the source head on over to the Sourceforge download page.
Extract the .zip or .tar.gz, enter the directory, and issue the install command
~$unzip log4r-1.0.5.zip ~$ cd log4r-1.0.5/ ~/log4r-1.0.5$ sudo ruby install.rb
To install using ruby-gems, first make sure you have gems installed:
~$ sudo apt-get install rubygems
Then install the library:
~$ sudo gem install Log4jr
This should get you everything you need to get started. Now, lets look at the previously written
script:
#!/usr/bin/ruby
require 'time'
puts "starting fibonacci"
def fib(num)
if(num < 2)
return 1
else
return fib(num-1) + fib(num-2)
end
end
if ARGV[0] != nil
if (ARGV[0].to_i >= 35)
puts "This might take a bit...."
end
start = Time.now
puts fib(ARGV[0].to_i)
stop = Time.now - start
puts "Finding the fib of #{ARGV[0]} took:"
puts stop
puts "seconds"
end
We will need to add:
require 'log4r' include Log4r
to the top to get access to the Log4r library.
Then we will need to create a logger. We’ll do this by adding another method to setup the global
logger. You can do this by adding:
def setupLogger() # create a logger @logger = Logger.new 'logger' @logger.outputters = Outputter.stdout @logger.debug "Logger is now setup" end
to just before the fib() method call in your script.
Normally, I would set this up in an initialize method (for those unfamiliar with Ruby, this is like a
constructor method), but we’ll keep this simple for later examples.
I’m also going to replace all of the standard out (ie “puts”) messages, and
replace them to be logged with the DEBUG logger. Replace all ‘puts’ messages with “@logger.debug”.
For instance:
puts "Finding the fib of #{ARGV[0]} took: #{stop} seconds"
should now look like this:
@logger.debug "Finding the fib of #{ARGV[0]} took: #{stop} seconds"
Of course, we still want feedback from our program so let’s change the logger to output directly
to the console. You can actually see that this is already being done with this line:
@logger.outputters = Outputter.stdout
After all of your edits, your script should now look like this:
#!/usr/bin/ruby
require 'time'
require 'log4r'
include Log4r
def setupLogger()
# create a logger
@logger = Logger.new 'logger'
@logger.outputters = Outputter.stdout
@logger.debug "Logger is now setup"
end
def fib(num)
if(num < 2)
return num
else
return fib(num-1) + fib(num-2)
end
end
#start of main script
@logger.debug "starting fibonacci"
if ARGV[0] != nil
if (ARGV[0].to_i >= 35)
@logger.debug "This might take a bit...."
end
setupLogger()
start = Time.now
@logger.debug fib(ARGV[0].to_i)
stop = Time.now - start
@logger.debug "Finding the fib of #{ARGV[0]} took: "
@logger.debug "#{stop}"
@logger.debug "seconds"
end
If you try and run your script at this point you’ll notice an “undefined method `info’ for nil:NilClass (NoMethodError)” error. This is because you haven’t setup the logger before you started debugging. Lets move this log line to after the setupLogger() method call:
...
#start of main script
if ARGV[0] != nil
if (ARGV[0].to_i >= 35)
@logger.debug "This might take a bit...."
end
setupLogger()
@logger.debug "starting fibonacci"
start = Time.now
@logger.debug fib(ARGV[0].to_i)
stop = Time.now - start
@logger.debug "Finding the fib of #{ARGV[0]} took: "
@logger.debug "#{stop}"
@logger.debug "seconds"
end
If you run your script now, it should work. Here is output from my run:
~$ ruby fib-log.rb 10 DEBUG logger: Logger is now setup DEBUG logger: starting fibonacci DEBUG logger: Fixnum: 55 DEBUG logger: Finding the fib of 10 took: DEBUG logger: 0.000828 DEBUG logger: seconds
As you can see, adding a logger to your existing script is very easy, and you can get even more
fancy with the types of logs you wish to create. Since there are multiple
levels of logging (DEBUG< INFO < WARN < ERROR < FATAL), you can customize which level’s you use by changing the second qualifier (ie. @logger.debug could become @logger.info). Lets do that for
a couple of lines.
Change
@logger.debug "Logger is now setup"
to
@logger.info "Logger is now setup"
and change
@logger.debug "starting fibonacci"
to
@logger.info "starting fibonacci"
Your final script should look like this:
#!/usr/bin/ruby
require 'time'
require 'log4r'
include Log4r
def setupLogger()
# create a logger named 'mylog' that logs to stdout
@logger = Logger.new 'logger'
@logger.outputters = Outputter.stdout
@logger.info "Logger is now setup"
end
def fib(num)
if(num < 2)
return num
else
return fib(num-1) + fib(num-2)
end
end
#start of main script
if ARGV[0] != nil
if (ARGV[0].to_i >= 35)
@logger.debug "This might take a bit...."
end
setupLogger()
@logger.info "starting fibonacci"
start = Time.now
@logger.debug fib(ARGV[0].to_i)
stop = Time.now - start
@logger.debug "Finding the fib of #{ARGV[0]} took: "
@logger.debug "#{stop}"
@logger.debug "seconds"
end
Now let’s run the final script. You should have received output like this:
~$ ruby fib-log.rb 10 INFO logger: Logger is now setup INFO logger: starting fibonacci DEBUG logger: Fixnum: 55 DEBUG logger: Finding the fib of 10 took: DEBUG logger: 0.000823 DEBUG logger: seconds
If you are looking for a quick way to add log messages to your ruby scripts, log4r might be a
very quick and easy to implement solution for you. Offering features comparable to Apache
Foundation’s log4j, you will find quite it quite capable of handing any of your current project’s
logging needs. Check it out, and let us know what you think.
















Leave a Reply