Sample of using log4r with Ruby classes, local and global loggers.

That is a very popular family of the loggers, people use when they develop a code in various languages like log4j for Java,. Today we will be talking about log4r, logger for Ruby, and I will show you of how to use them in the Ruby classes.

It seems that an official documentation mentions it very clear:

require 'log4r'
include Log4r

# create a logger named 'mylog' that logs to stdout
mylog = Logger.new 'mylog'
mylog.outputters = Outputter.stdout

# Now we can log.
def do_log(log)
log.debug "This is a message with level DEBUG"
end
do_log(mylog)

The output will look something like this:

DEBUG mylog: This is a message with level DEBUG

However, when you try to add it into you Ruby class, using so Java concepts and/or your experience with log4j, and you write a code similar to this one, you figure out that this code simply does not work:

require 'log4r'
include Log4r

class MyClass
mylog = Logger.new 'mylog'
mylog.outputters = Outputter.stdout
def my_method
log.debug "This is a message with level DEBUG"
end
end

cl = MyClass.new
cl.my_method

You are expecting that adding loggers into the existed code is a simple procedure, however, you should write some “wrapper” code. That is a code for Global (project wide) and Local (class wide) log4r loggers and their usage in different classes. As usual you can download these files from my repository.


$> cat log4r_loggers.rb
#!/usr/bin/env ruby

require 'rubygems'
require 'log4r'
include Log4r
require 'singleton'

## Global, project wide logger. May be called from any place of the project w/o
## any additional includes
## Usage sample:
## gloggerCF.debug "Logging to console and File: myHash: #{myHash}"
##
## It is currently implements three functions:
## gloggerC() - logging to STDOUT
## gloggerF() - logging to FILE
## gloggerCF() - logging to both STDOUT and FILE
##

GLOBAL_LOGGER_LOG_FILE = "/tmp/conn_pool.log"

class GlobalLogger
include Singleton
attr_reader :gloggerC
attr_reader :gloggerF
attr_reader :gloggerCF

def initialize
@gloggerC= Logger.new("GlobalLoggerConsole")
@gloggerF = Logger.new("GlobalLoggerFile")
@gloggerCF = Logger.new("GlobalLoggerConsoleAndFile")

pf = PatternFormatter.new(:pattern => "%C: #{self.class} %d %l %m Trace: %t")

so = StdoutOutputter.new("console", :formatter => pf)
@gloggerC.outputters << so
@gloggerC.level = DEBUG

fo = FileOutputter.new("f1", :filename => GLOBAL_LOGGER_LOG_FILE, :trunc => false, :formatter => pf)
@gloggerF.outputters << fo
@gloggerF.level = DEBUG

@gloggerCF.outputters << so
@gloggerCF.outputters << fo
@gloggerCF.level = DEBUG

end
end
module Kernel
def gloggerC
GlobalLogger.instance.gloggerC
end

def gloggerF
GlobalLogger.instance.gloggerF
end

def gloggerCF
GlobalLogger.instance.gloggerCF
end
end

## Local, class wide logger. Should have include LocalLogger added to the class, logger is used
## Usage sample:
## class A
## include LocalLogger
## def method
## loggerCF.debug "Logging to console and File: myHash: #{myHash}"
## end
## end
##
## It is currently implements three functions:
## loggerC() - logging to STDOUT
## loggerF() - logging to FILE
## loggerCF() - logging to both STDOUT and FILE
##
## if LOCAL_LOGGER_LOG_FILE not specified, "/tmp/" + self.class.to_s + "./log" will be used
##

LOCAL_LOGGER_LOG_FILE = nil

module LocalLogger
def loggerC
@logger = Logger.new("LocalLoggerConsole")
pf = PatternFormatter.new(:pattern => "%C: #{self.class} %d %l %m Trace: %t")

so = StdoutOutputter.new("console", :formatter => pf)
@logger.outputters << so
@logger.level = DEBUG
@logger
end

def loggerF
logFile = (LOCAL_LOGGER_LOG_FILE.nil?) ? "/tmp/" + self.class.to_s + ".log" : LOCAL_LOGGER_LOG_FILE
@logger = Logger.new("LocalLoggerFile")
pf = PatternFormatter.new(:pattern => "%C: #{self.class} %d %l %m Trace: %t")

fo = FileOutputter.new("f1", :filename => logFile, :trunc => false, :formatter => pf)
@logger.outputters << fo
@logger.level = DEBUG
@logger
end

def loggerCF
logFile = (LOCAL_LOGGER_LOG_FILE.nil?) ? "/tmp/" + self.class.to_s + ".log" : LOCAL_LOGGER_LOG_FILE
@logger = Logger.new("LocalLoggerConsoleAndFile")
pf = PatternFormatter.new(:pattern => "%C: #{self.class} %d %l %m Trace: %t")

so = StdoutOutputter.new("console", :formatter => pf)
fo = FileOutputter.new("f1", :filename => logFile, :trunc => false, :formatter => pf)

@logger.outputters << so
@logger.outputters << fo
@logger.level = DEBUG
@logger
end
end

Usage:


$> cat use_log4r_loggers.rb
#!/usr/bin/env ruby

require 'rubygems'
require './log4r_loggers.rb'

class MyGlobalClass
def fname
gloggerC.debug "Inside MyGlobalClass, debug message to console"
gloggerF.debug "Inside MyGlobalClass, debug message to file"
mySm = {'key1' => 22, 'key2' => 56}
myHash = {'a' => 1, 'b' => 5, 'c' => mySm}
gloggerC.debug "Inside MyGlobalClass, debug message to console: #{myHash}"
gloggerF.debug "Inside MyGlobalClass, debug message to file: #{myHash}"
gloggerCF.debug "Inside MyGlobalClass, debug message to console/file: #{myHash}"
end
end

class MyWomanClass
include LocalLogger
def fname
loggerC.debug "Inside MyWomanClass, debug message to console"
loggerF.debug "Inside MyWomanClass, debug message to file"
loggerCF.debug "Inside MyWomanClass, debug message to console/file"
end
end

class MyManClass
include LocalLogger
def fname
loggerC.debug "Inside MyManClass, debug message to console"
loggerF.debug "Inside MyManClass, debug message to file"
loggerCF.debug "Inside MyManClass, debug message to console/file"
end
end

myG = MyGlobalClass.new
myG.fname
myM = MyManClass.new
myM.fname
myW = MyWomanClass.new

Leave a Comment

Filed under technology

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>