rubylogginglog4r

How can I define my own levels in log4r without a conflict with other log4r-loggers?


I can define my own log-levels with log4r:

require 'log4r'
require 'log4r/configurator'

# This is how we specify our levels
Log4r::Configurator.custom_levels "Foo", "Bar", "Baz"

log = Log4r::Logger.new('custom levels')
p log.levels  #-> ["ALL", "Foo", "Bar", "Baz", "OFF"]
log.add Log4r::StdoutOutputter.new('console')

puts log.foo? #-> true
log.foo "This is foo 1"

log.level = Log4r::Bar
puts log.foo? #->false
log.foo "This is foo 2"

The log4r-documentation says:

Also, custom levels should be set before anything else is done with Log4r, otherwise the default levels will be loaded.

This restriction is the source of two problems:

Problem 1:

Example:

require 'log4r'
require 'log4r/configurator'

#Create a dummy logger
Log4r::Logger.new('dummy')

# Define new levels -> does not work after creation of another logger.
Log4r::Configurator.custom_levels "Foo", "Bar", "Baz"
log = Log4r::Logger.new('custom levels')
p log.levels  #-> ["ALL", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "OFF"]

The custom levels are not used.

Problem 2

If I define my own levels, I have no possibility to go back to the defaults.

Example:

require 'log4r'
require 'log4r/configurator'

# Define customer levels
Log4r::Configurator.custom_levels "Foo", "Bar", "Baz"
Log4r::Logger.new('dummy with custom levels')

#Reset to standard levels ["DEBUG", "INFO", "WARN", "ERROR", "FATAL"] <- this does not work
Log4r::Configurator.custom_levels( *Log4r::Log4rConfig::LogLevels )
log2 = Log4r::Logger.new('log')
p log2.levels #-> ["ALL", "Foo", "Bar", "Baz", "OFF"], but I wanted ["DEBUG", "INFO", "WARN", "ERROR", "FATAL"]

Background:

I want to create a logger with my own levels similar to Apache: DEBUG INFO NOTICE WARN ERROR CRIT ALERT EMERG.

When I do so, I get two problems:

My question:

How can I create a logger with customized log levels and without side effects to other loggers?


Solution

  • Custom levels are process-wide and you cannot reset it after it's already set. But there might be some way to achieve what you want.

    Problem 1

    Previous custom levels must be set for a reason, and logger methods and outputter methods are created during setting up the custom levels, thus you should be careful if you're going to remove some of the custom levels which might cause unexpected errors.

    However, there is a workaround to reset the custom levels from my fork of Log4r and it's for test purpose. (This method resets log4r to the original state, wipes out all existing loggers and outputters)

    Problem 2

    There are two solutions to resolve the conflicts:

    Log4r::Logger.module_eval %{
      alias_method :foo, :debug
      alias_method :bar, :info
      alias_method :baz, :error
      alias_method :qux, :fatal
    }
    

    Hope it helps.