lib/lumber/lumber.rb in lumber-0.0.2 vs lib/lumber/lumber.rb in lumber-0.9.0
- old
+ new
@@ -1,6 +1,9 @@
require "socket"
+require "active_support/core_ext/duplicable"
+require "active_support/core_ext/class"
+require "active_support/core_ext/module"
module Lumber
# Initializes log4r system. Needs to happen in
# config/environment.rb before Rails::Initializer.run
@@ -34,55 +37,117 @@
if defined?(RAILS_DEFAULT_LOGGER)
Object.send(:remove_const, :RAILS_DEFAULT_LOGGER)
end
Object.const_set('RAILS_DEFAULT_LOGGER', Log4r::Logger['rails'])
+ @@registered_loggers = {}
+ self.register_inheritance_handler()
end
# Makes :logger exist independently for subclasses and sets that logger
- # to one that inherits from base_class for each subclass as its created.
+ # to one that inherits from base_class for each subclass as it is created.
# This allows you to have a finer level of control over logging, for example,
# put just a single class, or hierarchy of classes, into debug log level
#
# for example:
#
- # Lumber.setup_logger_hierarchy(ActiveRecord::Base, "rails::models")
+ # Lumber.setup_logger_hierarchy("ActiveRecord::Base", "rails::models")
#
# causes all models that get created to have a log4r logger named
# "rails::models::<class_name>". This class can individually be
# put into debug log mode in production (see {log4r docs}[http://log4r.sourceforge.net/manual.html]), and log
# output will include "<class_name>" on every log from this class
# so that you can tell where a log statement came from
#
- def self.setup_logger_hierarchy(base_class, parent_fullname)
- base_class.class_eval do
- class_inheritable_accessor :logger
- self.logger = Log4r::Logger.new(parent_fullname)
+ def self.setup_logger_hierarchy(class_name, class_logger_fullname)
+ @@registered_loggers[class_name] = class_logger_fullname
+ obj = nil
+ names = class_name.split '::'
+ names.each do |name|
+ root ||= Object
+ if root.const_defined?(name)
+ obj = root.const_get(name)
+ root = obj
+ else
+ obj = nil
+ end
+ end
+
+ if obj
+ obj.class_eval do
+ class_inheritable_accessor :logger
+ self.logger = Log4r::Logger.new(class_logger_fullname)
+ end
+ end
+ end
+
+ private
+
+ # Adds a inheritance handler to Object so we can know to add loggers
+ # for classes as they get defined.
+ def self.register_inheritance_handler()
+ return if defined?(Object.inherited_with_lumber_log4r)
+
+ Object.class_eval do
+
class << self
+
def inherited_with_lumber_log4r(subclass)
inherited_without_lumber_log4r(subclass)
- # p "#{self} -> #{subclass} -> #{self.logger}"
- # Look up the class hierarchy for a useable logger
- # A class may have a nil logger if it was created
- # before we add logger/inheritance to its superclas,
- # e.g. Object/Exception - something tries to subclass
- # Exception after we added lumber_inherited to Object,
- # but Exception was defined before we added lumber_inherited
- while self.logger.nil?
- next_class = (next_class ||self).superclass
- if next_class.nil?
- self.logger = Log4r::Logger.root
- else
- self.logger = next_class.logger
- end
+ # if the new class is in the list that were registered directly,
+ # then create their logger attribute directly, otherwise derive it
+ logger_name = @@registered_loggers[subclass.name]
+ if logger_name
+ Lumber.add_lumber_logger(subclass, logger_name)
+ else
+ Lumber.derive_lumber_logger(subclass)
end
- subclass.logger = Log4r::Logger.new("#{logger.fullname}::#{subclass.name}")
end
+
alias_method_chain :inherited, :lumber_log4r
+
end
+ end
+
+ end
+
+ def self.add_lumber_logger(clazz, logger_name)
+ clazz.class_eval do
+
+ class_inheritable_accessor :logger
+ self.logger = Log4r::Logger.new(logger_name)
+
+ class << self
+
+ # Prevent rails from overwriting our logger
+ def cattr_accessor_with_lumber_log4r(*syms)
+ without_logger = syms.reject {|s| s == :logger}
+ cattr_accessor_without_lumber_log4r(*without_logger)
+ end
+ alias_method_chain :cattr_accessor, :lumber_log4r
+
+ end
+
+ end
+ end
+
+ def self.derive_lumber_logger(clazz)
+ # otherwise, walk up the classes hierarchy till you find a logger
+ # that was registered, and use that logger as the parent for the
+ # logger of the new class
+ parent = clazz.superclass
+ while ! parent.nil?
+ if defined?(parent.logger) && parent.logger
+ parent_is_registered = @@registered_loggers.values.find {|v| parent.logger.fullname.index(v) == 0}
+ if parent_is_registered
+ clazz.logger = Log4r::Logger.new("#{parent.logger.fullname}::#{clazz.name}")
+ break
+ end
+ end
+ parent = parent.superclass
end
end
end
\ No newline at end of file