class SemanticLogger::Base

def log_internal(level, index, message = nil, payload = nil, exception = nil)

Log message at the specified level
def log_internal(level, index, message = nil, payload = nil, exception = nil)
  # Handle variable number of arguments by detecting exception object and payload hash.
  if exception.nil? && payload.nil? && message.respond_to?(:backtrace) && message.respond_to?(:message)
    exception = message
    message   = nil
  elsif exception.nil? && payload && payload.respond_to?(:backtrace) && payload.respond_to?(:message)
    exception = payload
    payload   = nil
  elsif payload && !payload.is_a?(Hash)
    message = message.nil? ? payload : "#{message} -- #{payload}"
    payload = nil
  end
  log = Log.new(name, level, index)
  should_log =
    if exception.nil? && payload.nil? && message.is_a?(Hash)
      # All arguments as a hash in the message.
      log.assign(**log.extract_arguments(message))
    elsif exception.nil? && message && payload && payload.is_a?(Hash)
      # Message supplied along with a hash with the remaining arguments.
      log.assign(**log.extract_arguments(payload, message))
    else
      # All fields supplied directly.
      log.assign(message: message, payload: payload, exception: exception)
    end
  # Add result of block to message or payload if not nil
  if block_given?
    result = yield(log)
    case result
    when String
      log.message = log.message.nil? ? result : "#{log.message} -- #{result}"
    when Hash
      log.assign_hash(result)
    end
  end
  # Log level may change during assign due to :on_exception_level
  self.log(log) if should_log && should_log?(log)
end