In this article we'll see how to use Log4r in Ruby programs.
1. Simple logging using Log4r.
The below code shows how to log simply to the Standard output using Log4r. It doesn't use any formatting or any custom levels.
require 'log4r'
include Log4r
# create a logger named 'mylog' that logs to stdout
mylog = Logger.new 'mylog'
# You can use any Outputter here.
mylog.outputters = Outputter.stdout
# log level order is DEBUG < INFO < WARN < ERROR < FATAL
mylog.level = Log4r::INFO
# Now we can log.
def do_log(log)
log.debug "This is a message with level DEBUG"
log.info "This is a message with level INFO"
log.warn "This is a message with level WARN"
log.error "This is a message with level ERROR"
log.fatal "This is a message with level FATAL"
end
do_log(mylog)
The "do_log" method logs the messages at different levels. For logging you don't have call to a function that takes 'log level' and message as argument. Instead in Log4r each level is a method itself which takes message as argument and then logs the message depending upon the level that is set for the logger.
You can also check the logging level before logging a message using "query methods" like debug?, info? etc. You can use them like this:
if(log.debug?)
log.debug "debug message"
end
The above code will first check that if current logger can log the messages at debug level or not. The method with level name and question mark is called "query method". It will return true or false depending upon the level set for the logger.
2. Logging using Formatter and Outputter:
Above example used Standard output as destination for the logging. It also didn't use any Formatter for formatting the message. In this section we'll see what all destinations we can use for logging (with example of one of them) and what all formatting we can use (with example of one of them).
Log4r provides the following destination for logging:
1. IOOutputter -> For logging to any IO object
2. StdoutOutputter -> For logging to standard output IO i.e. $stdout
3. StderrOutputter -> For logging to standard error IO i.e. $stderr
4. FileOutputter -> For logging to file
5. RollingFileOutputter -> For logging to file and split the file as it grows
6. SyslogOutputter -> For logging to system log
7. EmailOutputter -> For emailing the logs
8. RemoteOutputter -> For remote logging
You can attach any number of outputter to a logger using 'outputters' property or by using 'add' method of logger object. Suppose you have created four outputters out1 to out4, you can add them to logger 'mylog' as follows:
mylog.outputters = out1, out2
mylog.add(out3, out4)
Log4r provides several formatters for formatting the message before logging it. It also provides a custom formatter called 'PatternFormatter' which is very flexible and powerful.
Log4r provides the following formatters:
1. BasicFormatter -> This is default formatter. Logs the message as it is.
2. PatternFormatter -> Most powerful and flexible formatter for custom formatting.
3. SimpleFormatter -> Adds log level and logger name to the message. Used only for strings. Doesn't inspect objects.
4. ObjectFormatter -> Inspect the objects and logs them as IRB(Interactive Ruby) does. Doesn't inspect strings.
5. NullFormatter -> Does nothing :)
Following code sample uses 'FileOutputter' alongwith 'PatternFormatter' for logging the message to log file.
require 'log4r'
include Log4r
# create a logger named 'mylog' that logs to stdout
mylog = Logger.new 'mylog'
# You can use any Outputter here.
mylog.outputters = Outputter.stdout
# Open a new file logger and ask him not to truncate the file before opening.
# FileOutputter.new(nameofoutputter, Hash containing(filename, trunc))
file = FileOutputter.new('fileOutputter', :filename => 'log',:trunc => false)
# You can add as many outputters you want. You can add them using reference
# or by name specified while creating
mylog.add(file)
# or mylog.add(fileOutputter) : name we have given.
# As I have set my logging level to ERROR. only messages greater than or
# equal to this level will show. Order is
# DEBUG < INFO < WARN < ERROR < FATAL
mylog.level = Log4r::INFO
# specify the format for the message.
format = PatternFormatter.new(:pattern => "[%l] %d :: %m")
# Add formatter to outputter not to logger.
# So its like this : you add outputter to logger, and add formattters to outputters.
# As we haven't added this formatter to outputter we created to log messages at
# STDOUT. Log messages at stdout will be simple
# but the log messages in file will be formatted
file.formatter = format
# Now we can log.
def do_log(log)
log.debug "This is a message with level DEBUG"
log.info "This is a message with level INFO"
log.warn "This is a message with level WARN"
log.error "This is a message with level ERROR"
log.fatal "This is a message with level FATAL"
end
do_log(mylog)
FileOuputter.new creates new instance of FileOutputter. First argument is name of the outputter, second is hash containing name of the file and whether to trunc the file while opening the file or not. For more information on outputters refer to this link.
PatternFormatter.new creates a new pattern formatter. It takes hash as input specifying the format for the message. If you are using date in the message you can optionally give date_pattern also. If no date_pattern is specified default date time patter will be chosen, which will log the date like this:
2006-12-21 13:15:50
To specify custom date formatting use the following code:
format = PatternFormatter.new(:pattern => "[%l] %d :: %m",
:date_pattern => "%a %d %b %H:%M %p %Y")
For more information of "date_pattern" directive (%a, %d etc) refer to this link. For more information about "pattern" directives (%l, %m) refer to this link.