Ruby Singleton Logger

I have been working on a module lately that parses a XML file structure into a hash and writes it to a database. The module includes some classes and methods and I needed a central logger class.

I created a class that inherits from Ruby´s Logger class.

class MyLogger < Logger
end

I decided to make this class a Singleton. Singleton is a design pattern that restricts instantiation of a class to only one instance that is globally available. This can e.g. be done by simply including the Singleton Module.

class MyLogger < Logger
  include Singleton
end

I wanted this class to be able to either log to STDOUT or a file. The standard way to do this, is to pass the log device to the Logger class during instantiation. The problem is that the singleton module creates the singleton instance before it is actually needed, called eager instantiation. In order to tell the singleton instance to which log device it should log to, we need to set a member variable in the initialize method. Secondly we need a method to reassign the log device.

class MyLogger < Logger
  include Singleton

  LOG_FILE = File.open("myfile.log","a")

  def initialize
    @logdev = Logger::LogDevice.new(LOG_FILE)
    @level = INFO
  end

  def change_logdev_to_stdout
    @logdev = Logger::LogDevice.new(STDOUT)
  end

end

I could now use the logger methods from everywhere in my code, e.g.:

MyModule::MyLogger.instance.info("Hello World!")

In order to make things a little bit shorter, I added an additional method to the module:

def self.logger
  return MyModule::MyLogger.instance
end

Logging can now been done from everywhere by calling:

MyModule::logger.info("Hello Universe!")

No comments yet.