# rails' logging setup is one of it's weakest points: it's troublesome to
# configure, doesn't automatically roll log files, and isn't multi
# process/thread safe.  the rolling is particularly troublesome since the logs
# also grow without bound, that is until disk is full and your server crashes.
#
# recently i wanted to setup rails to use tim pease's excellent logging.rb gem
# and found that rails 2.1 has made configuring a *better* logger that much
# harder.
#
# the following will accomplish the task, along with explaintion, and would
# work with other non-standard loggers in addition to tim's library.
#
#


# first off note that we're doing this in RAILS_ROOT/environment.rb and *not*
# in config/initializers/*.  this is because the initializer code does two
# things that rule out using an intiializer:
#
#   . it sets up the log file and initializes it with a logline *before* the
#   initializers are run
#
#   . it relays the logger to a bunch of classes like ActiveRecord::Base which
#   then keep their own private copy of the logger
#
# all this happens *before* the initializers meaning setting up logging there
# is too little too late
#

  Rails::Initializer.run do |config|


  # the first thing you'll need to do is install your alternate logger.  in my
  # case it's tim's lib so i did
  #
  #   GEM_HOME=vendor GEM_PATH=vendor gem install logging
  #
  # which is the bash command to set two environment variables and install the
  # gem into RAILS_ROOT/gems/logging-VERSION/.  the rest of the instructions
  # assume a local install of a gem or plugin, but will also work for a
  # system-wide gem install. make sure all of the following code is at the
  # very *end* of the config initializer block!
  #

  # we need to pull in our logging gem and it's supporting gem (lockfile).
  # there are two approaches we can take to do this, you only need to use one.
  # both of them are for picking a RAILS_ROOT/vendor/gems or
  # RAILS_ROOT/vendor/plugins install - if you have a system-wide install you
  # can skip this step
  #

  # method 1
  #
  # we can use the rails initializer hooks, except we have to monkey-patch in
  # Symbol#to_proc because it's not *ready* yet and the gem loading methods
  # are defined in terms of it - aka they will actually blow up if you try to
  # use them here as they're half-baked.
  #
    begin
      Symbol.method(:to_proc)
    rescue Object
      class Symbol;
        def to_proc() lambda{|object| object.send to_s} end
      end
    end

    config.gem 'logging'
    config.gem 'lockfile'

    Rails::Initializer.run(:add_gem_load_paths, config)
    Rails::Initializer.run(:load_gems, config)

  # method 2
  #
  # the roll your own approach is actually pretty simple, just get ruby to
  # look in the vendor and gem dirs in case Logging is installed locally
  # before the require
  #
    vendor_glob = File.join(RAILS_ROOT, 'vendor', 'plugins', 'logging*')
    gem_glob = File.join(RAILS_ROOT, 'vendor', 'gems', 'logging*')

    libs = ( Dir.glob(vendor_glob) + Dir.glob(gem_glob) )

    libs.each{|lib| $LOAD_PATH.unshift File.join(lib, 'lib')}
    begin
      require 'logging'
      require 'lockfile'
    ensure
      libs.size.times{ $LOAD_PATH.shift }
    end

  # so... now that we've abused rails a little to make sure our alternate
  # logger is loaded it's simple to configure a new one.  note that, because
  # we are doing this in the config block rails will relay it all over kingdom
  # come for us *after* this setup had occured, something we'd have to do by
  # hand in an initializer, and that this will short circuit rails setting up
  # it's own default logger and intializing a log and writing a line or two to
  # it before we'd get a chance to override it.
  #

    logpath             = config.log_path
    number_of_log_files = 7
    megabytes           = 2 ** 20
    max_size            = 42 * megabytes
    options             = { :safe => true } # for multi-process safe rolling

    logger = ::Logging.logger(
      logpath,
      number_of_log_files,
      max_size,
      options
    )

    config.logger = logger

  # eh viola!  the above setup will ensure that my logs auto-roll, even in the
  # with multiple mongrels, and that i never have more than 7 logs of not more
  # that 42 megabytes littering my log directory - for a total of no more that
  # about 1/4 gb of logs at maximum - with zero admin work done by anyone.
  end