Thoughts of just about anything
Making Ruby Logging Simple with Log4r
I am in the process of learning Ruby and while browsing the web I found TeensyMud which is a simple MUD server written in Ruby. The thing that caught my eye was how they implemented logging with Log4r. This here is a stripped down version of Log.rb found in the TeensyMud repository. But just so you get the idea, I’ll go through the modified version really quick.
First the Log class is created, notice that it includes Singleton and Log4r, this gives it all the functionality. Initialize is really simple, set the global level, create a pattern format, and the outputters.
The one other thing is the creation of loginit to make it easy to create a logger, pass it the name, level, and outputter and presto! you got your self a log! That so far is pretty slick! But they go even further.
class Log
include Singleton
include Log4r
# Load logger configuration
def initialize
Logger['global'].level = DEBUG
fmt = PatternFormatter.new(:pattern => "%d [%5l] (%c) %M",
:date_pattern => "%y-%m-%d %H:%M:%S")
StderrOutputter.new('stderr', :level => INFO, :formatter => fmt)
FileOutputter.new('file', :level => DEBUG, :formatter => fmt,
:filename => 'logs/trace.log' ,
:trunc => 'false')
end
def loginit(logname, loglevel, logto)
Logger.new(logname, Log4r.const_get(loglevel)).outputters = logto
Logger[logname]
end
end
At the end of the file they add this. At first I was confused but then it clicked! They created a logger function in the Module class. Big deal you say. Why would you want to do that? Well as it turn out the Module class defines what a ruby “module” should do. So by adding this function anything inside a module will have access to this function, which is pretty much everything!
class Module
def logger(loglevel='DEBUG', logto=['stderr','server'])
class_eval < <-EOD
@log = Log.instance.loginit(self.name, "#{loglevel}", #{logto.inspect})
def log
self.class.instance_variable_get :@log
end
EOD
end
end
Here’s a quick sample of how it would be used:
require 'Log'
class MyClass
logger 'DEBUG'
def initialize
log.info "Initializing MyClass"
end
end
Holly cow! How did that happen? Well when you call the logger method in the Module class it creates a new @log variable and a log method in your class. This helps hide all the logging details and makes it part of your class automatically!
I may not understand the complete details just yet, but I do know this is really nice!
| Print article | This entry was posted by Juan Frias on October 11, 2008 at 7:47 pm, and is filed under Programming, Ruby. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |