Updated mcollective.init according to OSCI-658
[packages/precise/mcollective.git] / lib / mcollective / log.rb
diff --git a/lib/mcollective/log.rb b/lib/mcollective/log.rb
new file mode 100644 (file)
index 0000000..7e3d774
--- /dev/null
@@ -0,0 +1,168 @@
+module MCollective
+  # A simple class that allows logging at various levels.
+  class Log
+    class << self
+      @logger = nil
+
+      VALID_LEVELS = [:error, :fatal, :debug, :warn, :info]
+
+      # Obtain the class name of the currently configured logger
+      def logger
+        @logger.class
+      end
+
+      # Logs at info level
+      def info(msg)
+        log(:info, msg)
+      end
+
+      # Logs at warn level
+      def warn(msg)
+        log(:warn, msg)
+      end
+
+      # Logs at debug level
+      def debug(msg)
+        log(:debug, msg)
+      end
+
+      # Logs at fatal level
+      def fatal(msg)
+        log(:fatal, msg)
+      end
+
+      # Logs at error level
+      def error(msg)
+        log(:error, msg)
+      end
+
+      # handle old code that relied on this class being a singleton
+      def instance
+        self
+      end
+
+      # increments the active log level
+      def cycle_level
+        @logger.cycle_level if @configured
+      end
+
+      def config_and_check_level(level)
+        configure unless @configured
+        check_level(level)
+        @logger.should_log?(level)
+      end
+
+      def check_level(level)
+        raise "Unknown log level" unless valid_level?(level)
+      end
+
+      def valid_level?(level)
+        VALID_LEVELS.include?(level)
+      end
+
+      def message_for(msgid, args={})
+        "%s: %s" % [msgid, Util.t(msgid, args)]
+      end
+
+      def logexception(msgid, level, e, backtrace=false, args={})
+        return false unless config_and_check_level(level)
+
+        origin = File.basename(e.backtrace[1])
+
+        if e.is_a?(CodedError)
+          msg = "%s: %s" % [e.code, e.to_s]
+        else
+          error_string = "%s: %s" % [e.class, e.to_s]
+          msg = message_for(msgid, args.merge(:error => error_string))
+        end
+
+        log(level, msg, origin)
+
+        if backtrace
+          e.backtrace.each do |line|
+            log(level, "%s:          %s" % [msgid, line], origin)
+          end
+        end
+      end
+
+      # Logs a message at a certain level, the message must be
+      # a token that will be looked up from the i18n localization
+      # database
+      #
+      # Messages can interprolate strings from the args hash, a
+      # message with "foo %{bar}" in the localization database
+      # will use args[:bar] for the value there, the interprolation
+      # is handled by the i18n library itself
+      def logmsg(msgid, default, level, args={})
+        return false unless config_and_check_level(level)
+
+        msg = message_for(msgid, {:default => default}.merge(args))
+
+        log(level, msg)
+      end
+
+      # logs a message at a certain level
+      def log(level, msg, origin=nil)
+        return unless config_and_check_level(level)
+
+        origin = from unless origin
+
+        if @logger
+          @logger.log(level, origin, msg)
+        else
+          t = Time.new.strftime("%H:%M:%S")
+
+          STDERR.puts "#{t}: #{level}: #{origin}: #{msg}"
+        end
+      end
+
+      # sets the logger class to use
+      def set_logger(logger)
+        @logger = logger
+      end
+
+      # configures the logger class, if the config has not yet been loaded
+      # we default to the console logging class and do not set @configured
+      # so that future calls to the log method will keep attempting to configure
+      # the logger till we eventually get a logging preference from the config
+      # module
+      def configure(logger=nil)
+        unless logger
+          logger_type = "console"
+
+          config = Config.instance
+
+          if config.configured
+            logger_type = config.logger_type
+            @configured = true
+          end
+
+          require "mcollective/logger/%s_logger" % logger_type.downcase
+
+          logger_class = MCollective::Logger.const_get("%s_logger" % logger_type.capitalize)
+
+          set_logger(logger_class.new)
+        else
+          set_logger(logger)
+          @configured = true
+        end
+
+
+        @logger.start
+      rescue Exception => e
+        @configured = false
+        STDERR.puts "Could not start logger: #{e.class} #{e}"
+      end
+
+      def unconfigure
+        @configured = false
+        set_logger(nil)
+      end
+
+      # figures out the filename that called us
+      def from
+        from = File.basename(caller[2])
+      end
+    end
+  end
+end