lib/semantic_logger/appender/base.rb in semantic_logger-3.0.1 vs lib/semantic_logger/appender/base.rb in semantic_logger-3.1.0

- old
+ new

@@ -1,12 +1,5 @@ -require 'json' -# Load AwesomePrint if available -begin - require 'awesome_print' -rescue LoadError -end - # Base appender # # Abstract base class for appenders # # Implements common behavior such as default text formatter etc @@ -14,151 +7,79 @@ # Note: Do not create instances of this class directly # module SemanticLogger module Appender - # Formatting & colors used by optional colorized_formatter - module AnsiColors - CLEAR = "\e[0m" - BOLD = "\e[1m" - BLACK = "\e[30m" - RED = "\e[31m" - GREEN = "\e[32m" - YELLOW = "\e[33m" - BLUE = "\e[34m" - MAGENTA = "\e[35m" - CYAN = "\e[36m" - WHITE = "\e[37m" + # DEPRECATED, use SemanticLogger::AnsiColors + AnsiColors = SemanticLogger::AnsiColors - # Maps the log level to a color for colorized formatters - # Since this map is not frozen, it can be modified as needed - LEVEL_MAP = { - trace: MAGENTA, - debug: GREEN, - info: CYAN, - warn: BOLD, - error: RED, - fatal: RED - } - end - class Base < SemanticLogger::Base + # Every logger has its own formatter attr_accessor :formatter - # Default log formatter - # Replace this formatter by supplying a Block to the initializer - # Generates logs of the form: - # 2011-07-19 14:36:15.660 D [1149:ScriptThreadProcess] Rails -- Hello World - def default_formatter - Proc.new do |log, logger| - # Header with date, time, log level and process info - entry = "#{log.formatted_time} #{log.level_to_s} [#{log.process_info}]" + # Returns the current log level if set, otherwise it logs everything it receives + def level + @level || :trace + end - # Tags - entry << ' ' << log.tags.collect { |tag| "[#{tag}]" }.join(' ') if log.tags && (log.tags.size > 0) + # An appender can implement a flush method if it is able to. + def flush + # NOOP + end - # Duration - entry << " (#{log.duration_human})" if log.duration - - # Class / app name - entry << " #{log.name}" - - # Log message - entry << " -- #{log.message}" if log.message - - # Payload - if payload = log.payload_to_s(false) - entry << ' -- ' << payload - end - - # Exceptions - if log.exception - entry << " -- Exception: #{log.exception.class}: #{log.exception.message}\n" - entry << log.backtrace_to_s - end - entry - end + # DEPRECATED: use SemanticLogger::Formatters::Default.new + def default_formatter + warn '[DEPRECATION] SemanticLogger::Appender::Base.default_level is deprecated. Please use SemanticLogger::Formatters::Default.new instead.' + formatter = SemanticLogger::Formatters::Default.new + Proc.new { |log, logger| formatter.call(log, logger) } end - # Optional log formatter to colorize log output - # To use this formatter - # SemanticLogger.add_appender($stdout, &SemanticLogger::Appender::Base.colorized_formatter) - # - # 2011-07-19 14:36:15.660 D [1149:ScriptThreadProcess] Rails -- Hello World + # DEPRECATED: use SemanticLogger::Formatters::Color.new def self.colorized_formatter - Proc.new do |log, logger| - colors = SemanticLogger::Appender::AnsiColors - level_color = colors::LEVEL_MAP[log.level] - - # Header with date, time, log level and process info - entry = "#{log.formatted_time} #{level_color}#{log.level_to_s}#{colors::CLEAR} [#{log.process_info}]" - - # Tags - entry << ' ' << log.tags.collect { |tag| "[#{level_color}#{tag}#{colors::CLEAR}]" }.join(' ') if log.tags && (log.tags.size > 0) - - # Duration - entry << " (#{colors::BOLD}#{log.duration_human}#{colors::CLEAR})" if log.duration - - # Class / app name - entry << " #{level_color}#{log.name}#{colors::CLEAR}" - - # Log message - entry << " -- #{log.message}" if log.message - - # Payload - if payload = log.payload_to_s(true) - entry << ' -- ' << payload - end - - # Exceptions - if log.exception - entry << " -- Exception: #{colors::BOLD}#{log.exception.class}: #{log.exception.message}#{colors::CLEAR}\n" - entry << log.backtrace_to_s - end - entry - end + warn '[DEPRECATION] SemanticLogger::Appender::Base.colorized_formatter is deprecated. Please use SemanticLogger::Formatters::Color.new instead.' + formatter = SemanticLogger::Formatters::Color.new + Proc.new { |log, logger| formatter.call(log, logger) } end - # Optional log formatter to output data in a hash format - # To use this formatter - # SemanticLogger.add_appender($stdout, &SemanticLogger::Appender::Base.json_formatter) + # DEPRECATED: use SemanticLogger::Formatters::Json.new def self.json_formatter - Proc.new do |log, logger| - h = log.to_h - h.delete(:time) - h[:timestamp] = log.time.utc.iso8601(defined?(JRuby) ? 3 : 6) - h.to_json - end + warn '[DEPRECATION] SemanticLogger::Appender::Base.json_formatter is deprecated. Please use SemanticLogger::Formatters::Json.new instead.' + formatter = SemanticLogger::Formatters::Json.new + Proc.new { |log, logger| formatter.call(log, logger) } end - def flush - # An appender can implement a flush method if it supports it. - end - - # Returns the current log level if set, otherwise it returns the global - # default log level - def level - @level || :trace - end - private # Initializer for Abstract Class SemanticLogger::Appender # # Parameters - # level [Symbol] - # Only allow log entries of this level or higher to be written to this appender - # For example if set to :warn, this appender would only log :warn and :fatal - # log messages when other appenders could be logging :info and lower + # level: [:trace | :debug | :info | :warn | :error | :fatal] + # Override the log level for this appender. + # Default: :error # - # filter [RegExp|Proc] - # Optional regular expression to filter log entries based on the class name - # When filter is a proc, it is passed the entire log struct and must return - # true or false indicating whether to log the message - def initialize(level=nil, filter=nil, &block) - # Set the formatter to the supplied block - @formatter = block || default_formatter + # formatter: [Object|Proc] + # An instance of a class that implements #call, or a Proc to be used to format + # the output from this appender + # Default: Use the built-in formatter (See: #call) + # + # filter: [Regexp|Proc] + # RegExp: Only include log messages where the class name matches the supplied. + # regular expression. All other messages will be ignored. + # Proc: Only include log messages where the supplied Proc returns true + # The Proc must return true or false. + def initialize(options={}, &block) + # Backward compatibility + options = {level: options} unless options.is_a?(Hash) + options = options.dup + level = options.delete(:level) + filter = options.delete(:filter) + @formatter = options.delete(:formatter) + @formatter = self.class.extract_formatter(@formatter) if @formatter.is_a?(Symbol) + @formatter ||= block + # Default to #call method for formatting if defined for an appender + @formatter ||= (respond_to?(:call) ? self : SemanticLogger::Formatters::Default.new) + raise(ArgumentError, "Unknown options: #{options.inspect}") if options.size > 0 # Appenders don't take a class name, so use this class name if an appender # is logged to directly super(self.class, level, filter) end @@ -166,9 +87,14 @@ # Return the level index for fast comparisons # Returns the lowest level index if the level has not been explicitly # set for this instance def level_index @level_index || 0 + end + + # Return formatter for supplied Symbol + def self.extract_formatter(formatter) + SemanticLogger.send(:named_formatter, formatter).new end end end end