class ReeLogger::MultiLogger

def add_appender(appender)

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

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

def debug(message, parameters = {}, exception = nil, log_args = false)
  log(:debug, message, parameters, nil, false)
end

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

def error(message, parameters = {}, exception = nil, log_args = true)
  log(:error, message, parameters, exception, log_args)
end

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

def fatal(message, parameters = {}, exception = nil, log_args = true)
  log(:error, message, parameters, exception, true)
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, parameters = {}, exception = nil, log_args = false)

def info(message, parameters = {}, exception = nil, log_args = false)
  log(:info, message, parameters, nil)
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_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(as_json(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, parameters = {}, exception = nil, log_args = true)

def unknown(message, parameters = {}, exception = nil, log_args = true)
  log(:unknown, message, parameters, exception, true)
end

def unsilence

def unsilence
  @silenced = false
end

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

def warn(message, parameters = {}, exception = nil, log_args = false)
  log(:warn, message, parameters, nil)
end