class ReeLogger::MultiLogger

def add_appender(appender)

def add_appender(appender)
  @appenders.push(appender)
end

def debug(message = nil, parameters = {}, exception = nil, log_args = false, progname = nil, &block)

def debug(message = nil, parameters = {}, exception = nil, log_args = false, progname = nil, &block)
  if block_given?
    log_block(:debug, parameters, log_args, yield)
  else
    msg = get_message(message)
    log(:debug, msg, parameters, nil, log_args)
  end
end

def error(message = nil, parameters = {}, exception = nil, log_args = true, progname = nil, &block)

def error(message = nil, parameters = {}, exception = nil, log_args = true, progname = nil,  &block)
  if block_given?
    log_block(:error, parameters, log_args, yield)
  else
    msg = get_message(message)
    log(:error, msg, parameters, exception, log_args)
  end
end

def fatal(message = nil, parameters = {}, exception = nil, log_args = true, progname = nil, &block)

def fatal(message = nil, parameters = {}, exception = nil, log_args = true, progname = nil, &block)
  if block_given?
    log_block(:fatal, parameters, log_args, yield)
  else
    msg = get_message(message)
    log(:fatal, msg, parameters, exception, log_args)
  end
end

def get_message(message)

def get_message(message)
  message || (raise ArgumentError.new("message should be given"))
end

def higher_or_equal_level?(message_level, appender_level)

def higher_or_equal_level?(message_level, appender_level)
  LEVEL_MAPPING[message_level] >= LEVEL_MAPPING[appender_level]
end

def info(message = nil, parameters = {}, exception = nil, log_args = false, progname = nil, &block)

def info(message = nil, parameters = {}, exception = nil, log_args = false, progname = nil, &block)
  if block_given?
    log_block(:info, parameters, log_args, yield)
  else
    msg = get_message(message)
    log(:info, msg, parameters, nil)
  end
end

def initialize(progname, rate_limiter, filter_words)

def initialize(progname, rate_limiter, filter_words)
  @progname = progname
  @rate_limiter = rate_limiter
  @filter_words = filter_words || []
  @appenders = []
  @silenced  = false
end

def log(level, message, parameters = {}, exception = nil, log_args = false)

def log(level, message, parameters = {}, exception = nil, log_args = false)
  if @rate_limiter
    @rate_limiter.call do
      log_event(level, message, parameters, exception, log_args)
    end
  else
    log_event(level, message, parameters, exception, log_args)
  end
  nil
end

def log_block(error, parameters, log_args, block_parameters)

def log_block(error, parameters, log_args, block_parameters)
  if block_parameters.is_a?(Hash)
    log(error, "", block_parameters.merge(parameters), nil, log_args)
  else
    log(error, block_parameters, parameters, nil, log_args)
  end
end

def log_event(level, message, parameters, exception, log_args)

def log_event(level, message, parameters, exception, log_args)
  return if @silenced if ![:error, :fatal].include?(level)
  if log_args
    begin
      method_binding = binding.of_caller(2)
      method_name = method_binding.eval('__method__')
      obj = method_binding.eval('self')
      args = {}
      obj.method(method_name).parameters.each do |_, name|
        args[name] = method_binding.local_variable_get(name)
      end
      args = transform_values(to_hash(args)) do |k, v|
        if @filter_words.any? { k.to_s.include?(_1) }
          'FILTERED'
        else
          v
        end
      end
      parameters[:method] = {}
      parameters[:method][:name] = method_name
      parameters[:method][:args] = args
    rescue
    end
  end
  parameters = transform_values(parameters) do |k, v|
    if @filter_words.any? { k.to_s.include?(_1) }
      'FILTERED'
    else
      v
    end
  end
  event = LogEvent.new(level, message, exception, parameters)
  appenders.each do |appender|
    if higher_or_equal_level?(event.level, appender.level)
      begin
        appender.append(event, @progname)
      rescue
        # fail silently if logger is not working by some reason
      end
    end
  end
end

def silence(&block)

def silence(&block)
  if block_given?
    @silenced = true
    block.call
    unsilence
  else
    @silenced = true
  end
  @silenced
end

def unknown(message = nil, parameters = {}, exception = nil, log_args = true, progname = nil, &block)

def unknown(message = nil, parameters = {}, exception = nil, log_args = true, progname = nil,  &block)
  if block_given?
    log_block(:unknown, parameters, log_args, yield)
  else
    msg = get_message(message)
    log(:unknown, msg, parameters, exception, log_args)
  end
end

def unsilence

def unsilence
  @silenced = false
end

def warn(message = nil, parameters = {}, exception = nil, log_args = false, progname = nil, &block)

def warn(message = nil, parameters = {}, exception = nil, log_args = false, progname = nil, &block)
  if block_given?
    log_block(:warn, parameters, log_args, yield)
  else
    msg = get_message(message)
    log(:warn, msg, parameters, nil)
  end
end