defmodule LogflareLogger.Stacktrace do
@moduledoc """
Handles stacktrace formatting for logged exceptions
"""
def format(stacktrace) when is_list(stacktrace) do
for i <- stacktrace, do: i |> format_entry()
end
defp format_entry({mod, fun, arity_or_args, location}) do
%{
module: format_field(:module, mod),
file: format_field(:file, location),
line: format_field(:line, location),
function: format_field(:function, fun, arity_or_args),
arity: format_field(:arity, arity_or_args),
args: format_field(:args, arity_or_args)
}
end
defp format_field(_, ""), do: nil
defp format_field(_, nil), do: nil
defp format_field(field, term) when is_atom(term) do
format_field(field, to_string(term))
end
defp format_field(:module, mod) when is_binary(mod) do
String.replace_prefix(mod, "Elixir.", "")
end
defp format_field(field, []) when field in [:file, :line] do
nil
end
defp format_field(:file, location) do
case Keyword.get(location, :file) do
nil -> nil
x -> to_string(x)
end
end
defp format_field(:line, location) do
case Keyword.get(location, :line) do
nil -> nil
int when is_integer(int) -> int
_ -> nil
end
end
defp format_field(:arity, arity) when is_integer(arity), do: arity
defp format_field(:arity, _), do: nil
defp format_field(:args, args) when is_list(args), do: inspect(args)
defp format_field(:args, _), do: nil
defp format_field(:function, fun, args) do
arity = format_field(:arity, args)
if arity do
"#{fun}/#{arity}"
else
"#{fun}"
end
end
end