Ruby on Rails
DatabaseLoggerWish

I wish that you could have the option to write the log to a database.

log4r?

Why not just directly right to a separate db table!?!

It’s not pretty, but this is what I hacked up:

# db_error_logger.rb
#
# by lee o'mara
#
# drop me in /lib
#
# replace the original logger with this one in environment.rb
# RAILS_DEFAULT_LOGGER = DBErrorLogger.new()
#
# create the log table
# CREATE TABLE `log` (
#  `id` int(10) unsigned NOT NULL auto_increment,
#  `severity` varchar(45) default NULL,
#  `timestamp` timestamp(14) NOT NULL,
#  `message` text,
#  PRIMARY KEY  (`id`)
# ) TYPE=InnoDB;
#
 

require 'logger'

class DBErrorLogger < Logger

  def initialize(connection = ActiveRecord::Base.connection, table_name = 'log')
    @progname = nil
    @level = DEBUG
    @logdev = LogDeviceDB.new(connection, table_name)
  end

  # had to overwrite to capture severity and time
  def add(severity, message = nil, progname = nil, &block)
    severity ||= UNKNOWN
    if @logdev.nil? or severity < @level
      return true
    end
    progname ||= @progname
    if message.nil?
      if block_given?
        message = yield
      else
        message = progname
        progname = @progname
      end
    end
    @logdev.write(format_severity(severity),
      format_datetime(Time.now),
      format_message(
        msg2str(message),
        progname
	)
    )
    true
  end

  def format_message(msg, progname)
    Format % [msg]
  end
end


class LogDeviceDB

  def initialize(connection, table_name)
    @dev = nil
    @table_name = table_name
    @dev = connection
  end

  def write(severity, datetime, message)
    severity = @dev.quote(severity)
    datetime = @dev.quote(datetime)
    message = @dev.quote(message) # could strip out colour-coding here
    sql = "INSERT INTO #{@table_name} (timestamp, severity, message) VALUES (#{datetime}, #{severity}, #{message})" 
    @dev.insert(sql)
  end

  def close
  end
end

class ActiveRecord::ConnectionAdapters::AbstractAdapter
 protected
   def format_log_entry(message, dump = nil)
     "%s  %s" % [message, dump]
   end
end