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 *