2 # A simple class that allows logging at various levels.
7 VALID_LEVELS = [:error, :fatal, :debug, :warn, :info]
9 # Obtain the class name of the currently configured logger
39 # handle old code that relied on this class being a singleton
44 # increments the active log level
46 @logger.cycle_level if @configured
49 def config_and_check_level(level)
50 configure unless @configured
52 @logger.should_log?(level)
55 def check_level(level)
56 raise "Unknown log level" unless valid_level?(level)
59 def valid_level?(level)
60 VALID_LEVELS.include?(level)
63 def message_for(msgid, args={})
64 "%s: %s" % [msgid, Util.t(msgid, args)]
67 def logexception(msgid, level, e, backtrace=false, args={})
68 return false unless config_and_check_level(level)
70 path, line, method = e.backtrace[1].split(/:(\d+)/)
71 origin = "%s:%s%s" % [File.basename(path), line, method]
73 if e.is_a?(CodedError)
74 msg = "%s: %s" % [e.code, e.to_s]
76 error_string = "%s: %s" % [e.class, e.to_s]
77 msg = message_for(msgid, args.merge(:error => error_string))
80 log(level, msg, origin)
83 e.backtrace.each do |line|
84 log(level, "%s: %s" % [msgid, line], origin)
89 # Logs a message at a certain level, the message must be
90 # a token that will be looked up from the i18n localization
93 # Messages can interprolate strings from the args hash, a
94 # message with "foo %{bar}" in the localization database
95 # will use args[:bar] for the value there, the interprolation
96 # is handled by the i18n library itself
97 def logmsg(msgid, default, level, args={})
98 return false unless config_and_check_level(level)
100 msg = message_for(msgid, {:default => default}.merge(args))
105 # logs a message at a certain level
106 def log(level, msg, origin=nil)
107 return unless config_and_check_level(level)
109 origin = from unless origin
112 @logger.log(level, origin, msg)
114 t = Time.new.strftime("%H:%M:%S")
116 STDERR.puts "#{t}: #{level}: #{origin}: #{msg}"
120 # sets the logger class to use
121 def set_logger(logger)
125 # configures the logger class, if the config has not yet been loaded
126 # we default to the console logging class and do not set @configured
127 # so that future calls to the log method will keep attempting to configure
128 # the logger till we eventually get a logging preference from the config
130 def configure(logger=nil)
132 logger_type = "console"
134 config = Config.instance
137 logger_type = config.logger_type
141 require "mcollective/logger/%s_logger" % logger_type.downcase
143 logger_class = MCollective::Logger.const_get("%s_logger" % logger_type.capitalize)
145 set_logger(logger_class.new)
153 rescue Exception => e
155 STDERR.puts "Could not start logger: #{e.class} #{e}"
163 # figures out the filename that called us
165 path, line, method = execution_stack[3].split(/:(\d+)/)
166 "%s:%s%s" % [File.basename(path), line, method]
169 # this method is here to facilitate testing