   and how to process the existing options.
   """
 
-  @type backend :: :gen_event.handler
-  @type message :: IO.chardata | String.Chars.t
+  @type backend :: :gen_event.handler()
+  @type message :: IO.chardata() | String.Chars.t()
   @type level :: :error | :info | :warn | :debug
-  @type metadata :: keyword(String.Chars.t)
+  @type metadata :: keyword(String.Chars.t())
   @levels [:error, :info, :warn, :debug]
 
   @metadata :logger_metadata

  explicitly avoid embedding metadata.
  """
  @spec bare_log(level, message | (() -> message | {message, keyword}), keyword) ::
        :ok | {:error, :noproc} | {:error, term}
  def bare_log(level, chardata_or_fun, metadata \\ [])
      when level in @levels and is_list(metadata) do
    case __metadata__() do
      {true, pdict} ->
        %{mode: mode, truncate: truncate,
          level: min_level, utc_log: utc_log?} = Logger.Config.__data__

        if compare_levels(level, min_level) != :lt do
          metadata = [pid: self()] ++ Keyword.merge(pdict, metadata)

    end
  end

  defp normalize_message(fun, metadata) when is_function(fun, 0) do
    normalize_message(fun.(), metadata)
  end

  defp normalize_message({message, fun_metadata}, metadata) when is_list(fun_metadata) do
    {message, Keyword.merge(metadata, fun_metadata)}
  end

  defp normalize_message(message, metadata), do: {message, metadata}

  defp truncate(data, n) when is_list(data) or is_binary(data), do: Logger.Utils.truncate(data, n)
  defp truncate(data, n), do: Logger.Utils.truncate(to_string(data), n)

  defp form_fa({name, arity}) do
    Atom.to_string(name) <> "/" <> Integer.to_string(arity)
