ActiveRecord interferring with Logger

rohitunderhill
Thu, 03 Sep 2009 23:07:34 -0000

It appears that using ActiveRecord (which requires ActiveSupport)
messes with the Logger class, resulting in difficulties in a non-Rails
ActiveRecord-using project. This can be seen with some example code:

require ''rubygems''
#require ''activerecord''
require ''logger''

log = Logger.new(STDERR)
log.sev_threshold = Logger::INFO
log.datetime_format = "%Y-%m-%d %H:%M:%S"

log.debug "debug"
log.info "info"
log.warn "warn"
log.error "error"
log.fatal "fatal"

Running this code will produce this lovely output:

I, [2009-09-02 10:49:39#27562]  INFO -- : info
W, [2009-09-02 10:49:39#27562]  WARN -- : warn
E, [2009-09-02 10:49:39#27562] ERROR -- : error
F, [2009-09-02 10:49:39#27562] FATAL -- : fatal

However, if I uncomment the require ''activerecord'' line, I
instead get
this less beautiful output:

info
warn
error
fatal

So I did some searching about and after looking at activesupport''s
logger.rb
http://github.com/rails/rails/blob/669fd84910586d4c791b6f5bf4320f68ac7845aa/activesupport/lib/active_support/core_ext/logger.rb

I found the following "working solution"

log = Logger.new(STDERR)
log.sev_threshold = Logger::INFO
log.datetime_format = "%Y-%m-%d %H:%M:%S"
class Formatter
      Format = "%s, [%s#%d] %5s -- %s: %s\n"

      attr_accessor :datetime_format

      def initialize
        @datetime_format = nil
      end

      def call(severity, time, progname, msg)
        Format % [severity[0..0], format_datetime(time), $$, severity,
progname, msg2str(msg)]
      end

      private
        def format_datetime(time)
          if @datetime_format.nil?
             time.strftime("%Y-%m-%dT%H:%M:%S.") << "%06d
" %
time.usec
          else
            time.strftime(@datetime_format)
          end
        end

        def msg2str(msg)
          case msg
          when ::String
            msg
          when ::Exception
            "#{ msg.message } (#{ msg.class })\n" <<
            (msg.backtrace || []).join("\n")
          else
            msg.inspect
          end
        end
end
f=Formatter.new
f.datetime_format = "%Y-%m-%d %H:%M:%S"
log.formatter=f

Using the above, I get the output that I like. However, that seems to
me gross and unRubylike, probably not even guarranteed to continue
working when I upgrade to a newer version of ActiveRecord. Does anyone
know if there is an easier and smarter way to get the desired result?

Many Thanks!

Rohit